Skip to content
This repository has been archived by the owner on Dec 9, 2018. It is now read-only.

Can't use global.eval as a function #13

Merged
merged 2 commits into from
Jan 6, 2012
Merged

Can't use global.eval as a function #13

merged 2 commits into from
Jan 6, 2012

Conversation

assaf
Copy link
Contributor

@assaf assaf commented Jan 3, 2012

This does the right thing:

eval("foo")

But this fails, complaining The "this" object passed to eval must be the global object from which eval originated:

e = eval;
e("too")

This fails too (jQuery uses in some place):

window.eval(window, "foo")

Any idea what's going on?

@brianmcd
Copy link
Owner

brianmcd commented Jan 3, 2012

Thanks as always for the report and test cases. I've been looking into this today, and I have a fix, but I'm still investigating to make sure it's the right way to go about it. It requires a slight API change, so if I go that way, I'll also bring tmpvar into the loop since it would affect JSDOM. I should have sometime to test out later tonight or tomorrow at the latest.

brianmcd added a commit that referenced this pull request Jan 6, 2012
The issue is caused because of a security check in V8's eval
implementation that's only performend when calling eval from an alias:
    if (!this_is_global_receiver || global_is_detached)

If that check fails, it throws the exception from #13.

Previously, we were detaching the proxy global and running the context
on just the real global, but that approach fails the V8 security check
since global_is_detached is true.

To fix it, we no longer detach the proxy global from the context. We
used to do this because setting properties on the proxy global would not
propagate them to the "real" global, which is the object constructed
from our ObjectTemplate with the Named Property Handlers.

It turns out, the proxy global *will* forward everything to the real
global like it's supposed to, but only if you supply/activate
[Named|Indexed]SecurityCallbacks on the ObjectTemplate by using
SetAccessCheckCallbacks.

Adding SecurityCallbacks that always return true allows the proxy global
to forward accesses to the real global, so we don't need to detach the
proxy global, and therefore eval works in all cases.
@brianmcd brianmcd merged commit ce459a5 into brianmcd:master Jan 6, 2012
@brianmcd
Copy link
Owner

brianmcd commented Jan 6, 2012

Sorry this took a little longer than expected...the bug was more subtle than I thought. V8 contexts use a "proxy" global and a "real" global for a context, where the proxy global is supposed to forward everything to the real global to facilitate implementing a split window object. Before, whenever I'd set a property on the proxy global, it wouldn't stick and it was like I never set it, and I couldn't figure out why. I found out that I could detach the proxy global and just use the real global in its place using Context's DetachGlobal(), which "fixed" the issue. Unfortunately, when you alias eval, it does a check to see if the global has been detached and then throws the exception mentioned here.

I ended up digging through the Chromium source to see how they implement their window object, and I noticed that they used SetAccessCheckCallback on the context's global's ObjectTemplate to set a NamedSecurityCallback and IndexedSecurityCallback. I couldn't find anywhere where they were explicitly forwarding from the proxy global to the real global, and these access checks seemed to be the only thing I didn't have in Contextify. It turns out, you need those access check callbacks to enable the forwarding (I assumed not having them would be like always allowing access).

I added access check callbacks that always return true and stopped detaching the proxy global, and everything worked!

@assaf
Copy link
Contributor Author

assaf commented Jan 6, 2012

Sounds like window has a split brain syndrom :)

@brianmcd
Copy link
Owner

brianmcd commented Jan 6, 2012

It has certainly split my brain.

I just pushed 0.1.0 to npm. Thanks again for the report and tests!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants