views:

250

answers:

1

I have a Greasemonkey script that uses a Javascript object to maintain some stored objects. It covers quite a large volume of information, but substantially less than it successfully stored and retrieved prior to encountering my problem. One value refuses to save, and I can not for the life of me determine why. The following problem code:

  • Works for other larger objects being maintained.
  • Is presently handling a smaller total amount of data than previously worked.
  • Is not colliding with any function or other object definitions.
  • Can (optionally) successfully save the problem storage key as "{}" during code startup.
this.save = function(table) {
    var tables = this.tables;
    if(table)
        tables = [table];
    for(i in tables) {
        logger.log(this[tables[i]]);
        logger.log(JSON.stringify(this[tables[i]]));
        GM_setValue(tables[i] + "_" + this.user, JSON.stringify(this[tables[i]]));
        logger.log(tables[i] + "_" + this.user + " updated");
        logger.log(GM_getValue(tables[i] + "_" + this.user));
    }
}

The problem is consistently reproducible and the logging statments produce the following output in Firebug:

  1. Object { 54,10 = Object } // Expansion shows complete contents as expected, but there is one oddity--Firebug highlights the object keys in purple instead of the usual black for anonymous objects.
  2. {"54,10":{"x":54,"y":10,"name":"Lucky Pheasant"}} // The correctly stringified JSON.
  3. bookmarks_HonoredMule updated
  4. undefined

I have tried altering the format of the object keys, to no effect. Further narrowing down the issue is that this particular value is successfully saved as an empty object ("{}") during code initialization, but skipping that also does not help. Reloading the page confirms that saving of the nonempty object truly failed.

Any idea what could cause this behavior? I've thoroughly explored the possibility of hitting size constraints, but it doesn't appear that can be the problem--as previously mentioned, I've already reduced storage usage. Other larger objects save still, and the total number of objects, which was not high already, has further been reduced by an amount greater than the quantity of data I'm attempting to store here.

+1  A: 

It turns out the issue was that of this.save() being called from an unsafeWindow context. This is a security violation, but one that should have resulted in an access violation exception being thrown:

Error: Greasemonkey access violation: unsafeWindow cannot call GM_getValue.

Instead GM_setValue returns having done nothing, and the subsequent logging instructions also execute, so there was no hint of the issue and the documentation may be out of date.

In my quest to solve this problem by any means, I abstracted away GM_ storage functions so I could use other storage mechanisms, so the workaround will be to put all save instructions in a pre-existing cleanup routine that runs in setInterval, similar to the fix described in the aforementioned documentation. (The use of an existing interval is to prevent excessive creation of timers which have in the past degraded performance over browser uptime.)

HonoredMule