Setting through el.dataset.x doesn't reflect on the HTML. #1571

MayhemYDG opened this Issue Jun 21, 2012 · 15 comments


None yet
3 participants
// ==UserScript==
// @name           x
// @version        1
// @namespace      x
// @include        http://*
// ==/UserScript==

(function() {

    d = document;
    a = d.createElement('a');
    a.href = '';
    // doesn't work
    a.dataset.test1 = 'test';
    // works
    a.setAttribute('data-test2', 'test');


See title and sample code.
Retrieving through el.dataset.x works IF the data-x attribute is set, but setting through el.dataset.x doesn't set the data-x HTML attribute.


arantius commented Jun 21, 2012
This sounds very much like pitfall #4. "el.dataset" isn't a standard thing is it?


arantius commented Jun 21, 2012

Thanks for the info. Perhaps you can use ? Or try the 1.0 betas and use "@grant none" which has a similar effect (except of course all users of the script would have to do this -- and the beta really is a beta, it's not necessarily ready for wide use yet).

I'll keep using setAttribute until it's fixed.


arantius commented Jun 21, 2012

Ok! I'm leaving this open until it is fixed; but this sounds like the sort of thing that will be very hard, if possible, to fix. The goal for version 1.0 is for user scripts to run in the content scope where everything "just works", rather than in the traditional security-restricted sandbox. For reasons just like this.

I'd like to add that retrieving values through element.dataset.key works, so saving a value through the same means is what I'd like to use.
Conversion between element.dataset.key = ... into an HTML attribute isn't important for me, as I have no use for element.getAttribute('data-key').

tl;dr: el.dataset.key setter itself is more important than conversion into an html attribute.


arantius commented Jan 24, 2013

When I install this script and visit any page (Firefox 19.0, GM 1.7.1), in the console I see:

el_work: test
el_fail: test

And the HTML output looks like (lots of other stuff in the document HEAD and):

<div data-test2="test" id="el_work"></div><div data-test1="test" id="el_fail"></div>

So, this works as expected? It seems to continue to work if I specify @grant none or @grant GM_log.

Nope, doesn't work when I use  @grand GM_log.

Here's the test:

Here's what I get:

[17:22:26.711] work: uno
[17:22:26.712] fail: dos
[17:22:26.714] ["<body data-one=\"uno\">"]
[17:22:28.861] work: uno
[17:22:28.861] fail: undefined
[17:22:28.863] ["<body data-one=\"uno\">"]

The fail test works the first time because the browser didn't do its garbage collection round.
Wait a bit and the fail test will indeed fail.

I'm on GM 1.6 and Fx 18 it that matters.

Same thing happens on GM 1.7.1 + Fx 18.


this sounds like the sort of thing that will be very hard, if possible, to fix.

It might be a long shot, but you may be able to fix this using Proxies.
The doc says proxies are non-standard because ES6 hasn't been finalized yet.

It also needs to handle the camelCase -> dashed conversion.

Since datasets aren't in the prototype, you'll have to somehow set this on every elements. I hope it's possible for GM.

Something like

function dataDashing(key) {
  return 'data-' + key.replace(/[A-Z]/g, function(c) {
    return '-' + c.toLowerCase();
function setDataset(el) {
  el.dataset = new Proxy({}, {
    get: function(obj, key) {
      return el.getAttribute(dashing(key));
    set: function(obj, key, val) {
      el.setAttribute(dashing(key), val);
      return val;
    'delete': function(obj, key) {
      return true;

janekptacijarabaci commented Jul 14, 2013

Maybe it's been fixed (GM 1.10 + FF 22.0). But maybe I'm wrong...

Looks like it is indeed, thanks.

MayhemYDG closed this Jul 14, 2013

Actually it's not entirely fixed,

delete el.dataset.key;

doesn't work from a userscript.

MayhemYDG reopened this Nov 15, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment