3

The following script logs false to the console. Does anyone know why or what benefits it brings?

From a brief glance into Greasemonkey's source code I couldn't find anything that modifies Object. Also looking into the Object it is hard to see any meaningful differences, all the functions are still native code.

// ==UserScript==
// @name        test
// @namespace   test
// @include     *
// @grant       none
// ==/UserScript==

console.log(window.Object == Object)

(tested on Greasemonkey & Firefox, not sure about Scriptish & Chrome, though any experiments welcome!).

[NOTE: this question is unrelated to the question of {a: 2} != {a: 2}, please read the question itself and not just glance at the title before you cast any close votes, thanks!].

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
simonzack
  • 19,729
  • 13
  • 73
  • 118
  • You can't just simply compare Objects, as they will never be equal (different references in memory and so on) [Object comparison in JavaScript](http://stackoverflow.com/questions/1068834/object-comparison-in-javascript) – Justinas Jan 13 '17 at 07:25
  • @Justinas I'm not sure that is relevant, this one is for the object class and the other one is for instances. – simonzack Jan 13 '17 at 07:26
  • it seems that `window` ain't the global object in this case, but instead references the window-object of the current page. So like two frames/windows don't share the same classes (identical, but not the same), `Object` and `window.Object` are not the same reference either. That's basic sandboxing, so that one frame/window doesn't interfere with the global variables of the other frame/window. Imagine one page would modify `Object.prototype` and all windows in your browser would get that change. – Thomas Jan 13 '17 at 07:46
  • Or if all pages in your browser would share the same `location` object ;) – Thomas Jan 13 '17 at 07:53
  • @Thomas Hmm good thinking, although I think that a userscript can only operate on the current page it runs on, unlike addons. In the test script there are no `@grant`s so there is no extra privilege. But perhaps something like this is still going on, I wonder where I can find the code/docs that makes this happen. – simonzack Jan 13 '17 at 07:56
  • `console.log(this === window, this, window, this.window === window)` – Thomas Jan 13 '17 at 08:53

1 Answers1

4

This is a side effect of Mozilla's current sandbox process. Even in @grant none mode, Greasemonkey sandboxes scripts using Components.utils.Sandbox -- only with Xrays off and wantExportHelpers left at false.

So, your window.Object == Object is equivalent to window.Object == this.Object.
But: In a Greasemonkey script, this (the root/global this) is always a Sandbox object, not a Window.

Firefox may have a good reason for cloning Object like that, but I couldn't find any reference saying as much.


Chrome with Tampermonkey does not do this and window.Object == Object is true for Tampermonkey scripts regardless of the @grant setting.

Chrome also does not do sandboxing the same way.

Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • So how would I correctly write `window.Object === Object` so that it works in GreaseMonkey? – Aran-Fey Jan 22 '19 at 02:39
  • @Aran-Fey, I don't support Greasemonkey 4+ (and there's a separate tag for it). But if `unsafeWindow` doesn't work for your *true* purpose then you would use script injection. See also https://stackoverflow.com/a/25785794/331508 – Brock Adams Jan 22 '19 at 02:48
  • just wanted to point out to you that irregardless is a double negative, also not a word – Alice May 03 '23 at 02:45