-
Notifications
You must be signed in to change notification settings - Fork 339
vm.runInContext is not fully supported after upstream change #420
Comments
See eaf6763 for some of the failing tests showing missing functionality. |
Let me know if you want me to look at any changes. The |
I found another case that doesn't work: Promise microtasks.
|
Re: the above, let me know if it should be filed separately. It's not strictly anything to do with sandbox properties, but tick management. |
It seems that the package uglify-js2 is broken in node-chakracore at the moment because of |
When using |
As @MSLaguana pointed out, #478 may be related. There is also #508. |
In node-chakra v10 the var repl = require("repl")
var vm = require("vm")
var c = vm.createContext({})
var r = repl.start({})
r.eval("var a=1", c, "test", () => {
console.log("a", c.a) // logs "a", undefined instead of 1
})
r.close() |
Thanks for the report, this looks like the same root issue impacting uglify ( |
Any plans or leads on how to tackle this issue? |
I have a monkeypatching workaround for some limited scenarios (would fix most of the |
addresses nodejs#420 ChakraCore doesn't handle global objects in the same way as v8, and in particular ChakraCore doesn't support all proxy interceptors there. We attempted to work around this via interceptors in the prototype chain, but that was an imperfect solution, and a top-level "var" declaration would end up adding a property to the global object in a context without going through the interceptors. To work around this in simple cases, we now take a snapshot of properties on the global before running in a context, and diff the changes at the end to patch up changes in the sandbox. This is NOT a complete solution, and in particular will not work if there is any sort of asynchronous operation that changes the state of the global object. It also has behavioral differences if the global object is writable but the sandbox object is not; in node-v8 this will result in the variable silently not being set in the context and instead the value from the sandbox being used, while here we discover the mismatch too late and the new value has been set on the global.
I've got a PR out with a partial workaround for this issue now, although there are known deficiencies in it. It should fix the case of uglify.js and the repl example above. |
addresses nodejs#420 ChakraCore doesn't handle global objects in the same way as v8, and in particular ChakraCore doesn't support all proxy interceptors there. We attempted to work around this via interceptors in the prototype chain, but that was an imperfect solution, and a top-level "var" declaration would end up adding a property to the global object in a context without going through the interceptors. To work around this in simple cases, we now take a snapshot of properties on the global before running in a context, and diff the changes at the end to patch up changes in the sandbox. This is NOT a complete solution, and in particular will not work if there is any sort of asynchronous operation that changes the state of the global object. It also has behavioral differences if the global object is writable but the sandbox object is not; in node-v8 this will result in the variable silently not being set in the context and instead the value from the sandbox being used, while here we discover the mismatch too late and the new value has been set on the global. PR-URL: nodejs#542 Reviewed-By: Seth Brenith <sethb@microsoft.com> Reviewed-By: Kyle Farnung <kfarnung@microsoft.com>
addresses nodejs#420 ChakraCore doesn't handle global objects in the same way as v8, and in particular ChakraCore doesn't support all proxy interceptors there. We attempted to work around this via interceptors in the prototype chain, but that was an imperfect solution, and a top-level "var" declaration would end up adding a property to the global object in a context without going through the interceptors. To work around this in simple cases, we now take a snapshot of properties on the global before running in a context, and diff the changes at the end to patch up changes in the sandbox. This is NOT a complete solution, and in particular will not work if there is any sort of asynchronous operation that changes the state of the global object. It also has behavioral differences if the global object is writable but the sandbox object is not; in node-v8 this will result in the variable silently not being set in the context and instead the value from the sandbox being used, while here we discover the mismatch too late and the new value has been set on the global. PR-URL: nodejs#542 Reviewed-By: Seth Brenith <sethb@microsoft.com> Reviewed-By: Kyle Farnung <kfarnung@microsoft.com>
addresses nodejs#420 ChakraCore doesn't handle global objects in the same way as v8, and in particular ChakraCore doesn't support all proxy interceptors there. We attempted to work around this via interceptors in the prototype chain, but that was an imperfect solution, and a top-level "var" declaration would end up adding a property to the global object in a context without going through the interceptors. To work around this in simple cases, we now take a snapshot of properties on the global before running in a context, and diff the changes at the end to patch up changes in the sandbox. This is NOT a complete solution, and in particular will not work if there is any sort of asynchronous operation that changes the state of the global object. It also has behavioral differences if the global object is writable but the sandbox object is not; in node-v8 this will result in the variable silently not being set in the context and instead the value from the sandbox being used, while here we discover the mismatch too late and the new value has been set on the global. PR-URL: nodejs#542 Reviewed-By: Seth Brenith <sethb@microsoft.com> Reviewed-By: Kyle Farnung <kfarnung@microsoft.com>
@MSLaguana thanks a lot for your fixes on issues related to I shall keep a close eye on new releases of |
This fix is in the most recent node-chakracore nightly if you were interested in trying it out soon; otherwise we expect to put out a new release of 10.x in the near future. |
@MSLaguana using |
addresses nodejs#420 ChakraCore doesn't handle global objects in the same way as v8, and in particular ChakraCore doesn't support all proxy interceptors there. We attempted to work around this via interceptors in the prototype chain, but that was an imperfect solution, and a top-level "var" declaration would end up adding a property to the global object in a context without going through the interceptors. To work around this in simple cases, we now take a snapshot of properties on the global before running in a context, and diff the changes at the end to patch up changes in the sandbox. This is NOT a complete solution, and in particular will not work if there is any sort of asynchronous operation that changes the state of the global object. It also has behavioral differences if the global object is writable but the sandbox object is not; in node-v8 this will result in the variable silently not being set in the context and instead the value from the sandbox being used, while here we discover the mismatch too late and the new value has been set on the global. PR-URL: nodejs#542 Reviewed-By: Seth Brenith <sethb@microsoft.com> Reviewed-By: Kyle Farnung <kfarnung@microsoft.com>
Sorry; I meant that the fix for I had forgotten about #478; that looks to be a little harder to resolve. The root of the issue is still that we are limited in where we can put the interceptors for the context, and in this case we are attempting to check whether the sandbox has a property (in this case |
@MSLaguana thanks for the clarifications 👍 |
With the inclusion of nodejs/node#16293 we need to make some additional changes to properly support
vm.runInContext
.When running
vm.runInContext(code, context)
the context object is intended to act like the global object for the duration of the code. Currently I believe we do this by creating a proxy around thecontext
object, creating a new global object, and then setting the prototype of the new global object to the the proxy of the context object.Prior to the upstream changes, there was a step that copied properties from the global inside the context back to the context object. In fact, we already mishandled this somewhat: In node-chakracore, you could do this:
With the upstream changes, that step has been removed in favor of new v8 support for additional interceptors. I've tried adding implementations for those interceptors, but our current approach to configuring the context doesn't end up with them being called: modifications are made to the global context object, and it does not defer to the proxy that is its prototype.
It seems like we should probably be reversing the relationship here, with the sandbox object (or its proxy) deferring to the global object as its prototype instead, so modifications can be intercepted by the native code and persisted as appropriate.
The text was updated successfully, but these errors were encountered: