Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some problems about global #362

Closed
eight04 opened this issue Feb 25, 2017 · 12 comments
Closed

Some problems about global #362

eight04 opened this issue Feb 25, 2017 · 12 comments

Comments

@eight04
Copy link

eight04 commented Feb 25, 2017

Someone reported that Linkify Plus Plus makes disqus fail to load. I found that it is because browserify would assign a require to global, and conflict with disqus. Here is an userscript to illustrate what happened (try it on this page):

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @include	     *
// @grant        none
// ==/UserScript==

foo = "123";	// now you can access 'foo' from page script
console.log(typeof require);	// you can also access the variable defined by page script, if it is assigned to global

So, it seems that userscript share the same global with page script. Is it by-design or a bug?

@tophf
Copy link

tophf commented Feb 26, 2017

This is exactly what @grant none does by design.

@eight04
Copy link
Author

eight04 commented Feb 26, 2017

You can @grant other stuff instead of @grant none, the result won't change.

@tophf
Copy link

tophf commented Feb 26, 2017

Houston we've got a problem. Could be an old one.
I've tested this:

// ==UserScript==
// @name         Sandbox bug
// @include	 *
// @grant        GM_getValue
// ==/UserScript==

foo = "123";
try { console.log(require); } catch(e) { console.log('require is not defined'); }
  • foo: working as expected AFAIK in the absence of 'use strict', the variable was exposed as an expando property on window.
  • require: the actual page object was displayed (bug) on the first load, also on normal refresh via F5, also on hard-refresh via Ctrl-F5 but with a 50/50 chance.

@derjanb
Copy link
Member

derjanb commented Feb 26, 2017

Is it by-design or a bug?

It's "by-design" because there is no way in JavaScript and with the currently usable APIs to catch such global variable declarations. But this can be solved by the userscripts:

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @include	     *
// @grant        GM_log
// ==/UserScript==

window.foo = '123';
this.bar = '123';

(function() {
    'use strict';
    blub = 1; // throws an error
})();

@derjanb derjanb closed this as completed Feb 26, 2017
@eight04
Copy link
Author

eight04 commented Feb 26, 2017

Currently I added a var require; statement to the script (https://github.com/eight04/linkify-plus-plus/blob/29058566a2a2eefc491cfabe706503d8ac937181/linkify-plus-plus.user.js#L31), but I'm not sure if it is the correct way to fix it, and will still work in the future.

@tophf
Copy link

tophf commented Feb 26, 2017

@eight04, I think you should use var in the initial declaration inside linkify-plus-plus-core.js. Currently it adds an expando property in DOM window, which is shared with the page, and AFAIK this is the "correct" behavior from the standpoint of JavaScript in the absence of 'use strict'.

@derjanb
Copy link
Member

derjanb commented Feb 26, 2017

Indeed, using "var" also is a valid solution.

@eight04
Copy link
Author

eight04 commented Feb 26, 2017

Browserify uses a strategy similar to:

require = function(){
	if (typeof require == "function") return require;
	return createRequireFunction();
}();

, to detect "require" in current scope.

I guess I have to make a custom build.

@tophf
Copy link

tophf commented Feb 26, 2017

browserify and other web-related stuff doesn't account for the use case of sandboxed scripting environment running alongside the web page.

@derjanb
Copy link
Member

derjanb commented Feb 26, 2017

I have no chance to check if it is working at the moment, but you can try to require another script first, that does nothing else than to declare a variable "require" at the current scope?

@eight04
Copy link
Author

eight04 commented Feb 26, 2017

require another script first, that does nothing else than to declare a variable "require" at the current scope

I can confirm that this method works. It also works if I put the new require script (the script declaring the "require" variable) AFTER linkify-plus-plus-core.

@CollinChaffin
Copy link

I was the one that reported this bug to @eight04 in his awesome linkify. Just caught up on this thread and have to say you guys absolutely rock in how quickly you drilled down to the root cause on this one! I was trying to debug it myself and just am not nearly the JS guru that you guys are, so thank you!

mWalrus added a commit to mWalrus/longs that referenced this issue Dec 14, 2022
TamperMonkey cannot access global variables like we normally can
in javascript so this commit is working around that restriction
by setting all the "global" variables on the window object since
that is globally accessible.

See this comment on the TamperMonkey GitHub for reference:
Tampermonkey/tampermonkey#362 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants