-
Notifications
You must be signed in to change notification settings - Fork 7.3k
vm
module behaves oddly W.R.T. context-objects and functions in exterior scopes
#1801
Conversation
P.S. I’ve looked into this a bit, with the assistance of others from the IRC channel; it looks like @ry’s It sounds like we can rewrite that to utilize the passed context object itself as the prototype for the |
So, solved and implemented. Tests updaded to ensure the functionality. I’d love input especially from @ry, @isaacs, @mraleph, and @bnoordhuis, as I’ve discussed this with you all previously. This is my first commit to Node since late 2009, so please let me know if there’s any styling or conventions that I messed up; I’m sorry if my code doesn’t quite “fit in” at first blush. (I did my best!) Worth noting: All tests that passed before the commits pass after, though some have had minor functionality removed intentionally (stuff that doesn’t make any sense with the new system.) Tested on OS X and Linux, can’t imagine this causing any other platform-specific issues though. |
-1 to forcing customized prototyope to the global object. |
Short summary of the points I’ve considered, considering exploring the global state of the The old methodology of copying any values of the Some alternatives include:
I’m not sure which of these (or something else entirely) is the most friendly / useful API. I’m open to suggestions as to where to continue from here. |
@Herby any particular reasoning behind “it’s dangerous?” I’ve talked to the v8 guys, there’s explicitly Nothing Wrong™ with doing this. All of the magic happens with the As for the “JavaScript”-ness of it, which I can see why you might be a little confused about … well, it’s exactly the same ‘hack’ that v8 itself uses to handle placing of the |
@ELLIOTTCABLE: Well, if they say it's fine, I'm ok with it. I just have the experience that doing nasty things can lead to plethora of other problems that are initially hidden but begin to show themselves through use, so I rather defensively avoid doing thing that I do not believe to be right. But since they say this is not a nasty thing, why not? |
If I understand your suggested alternatives, does #1 change this behavior?
Personally, I use the last-evaluated expression from vm.run* methods, I would like that to stay the same if possible. |
@rehanift I’m basically agreed, there. It’s sort of an Perhaps that’s yet another alternative: changing the current APIs to be more VM-like and less Then again of course, there’s the consideration of backwards compatibility: how much code out there is currently using VM? I mean, we’re pre-1.0.0, so it’s not such a consideration, but there’s still the argument that “even if the API is better designed, it’s not worth the improvement to break backwards compatibility.” I’m personally very anti-backwards-compatibility whenever it is at the expense of API quality, but I’m pretty sure @ry et. al might disagree with me there. ;D |
So, a discussion with @isaacs in IRC resulted in us deciding to restrict this pull-request itself to the non-API-changing prototypal-insertion elements of this code. I’ve reverted the API-changing elements, and we’re going to discuss how, exactly, these are best implemented on the mailing list, with a goal of implementing a replacement for 0.7. |
Here's what I'd like to see:
@Herby @bnoordhuis @mraleph Does this plan sound sane? Comments on this pull req for item 1? @ELLIOTTCABLE Can you add another commit to make sure it doesn't add any new lint errors? |
@isaacs: Yes, it looks fine. Except the " If it's impossible/expensive/bad to do this, then we should explicitly remove the copy-back step, and provide some new API for getting the global object from the VM", it looks, well, ugly to me. |
Pass global to the vm (!!!!!!!!! ???????????) Maybe we should wait a little bit before proceeding. I think we are addressing here a non-issue. Let's start from @ELLIOTTCABLE tests above, modifying : function node_vm_context_behaves_oddly() { o.inFunc=function() {}; o.outFunc = function(){ Just works, because outFunc is defined in the initial context and does execute there, so does not know inFunc defined in vm context unless inFunc exists in initial context (my modification) For me, this is exactly the same issue as #1770 answered and closed by @bennoordhuis (and he was right) Then I think that the tests above should replace o by "this" inside the functions (and then we come back to #1674, see below) I have released today the node-dom project (not documented yet) which uses vm in all possible ways I believe, and I have explained today what I think should happen in #1674 and I do propose to try some modifications in cloneObjectMethod, at least node-dom gives a real example of implementation, I could give more tricky examples (like handling in node-dom something like body onload="console.log(this)" and how to have "this" refers to body which is not trivial) VM is indeed confusing whether we are in the calling context or VM's one (I tried to give enough details in #1674 again), while having to do the same things in both to be consistent. But to close the loop and allow modifications in both, we just have to do : context.context=context (@isaacs comment Adding/removing/modifying a property on one should be immediately visible on the other,) This is not an invention, global is doing the very same thing for example, context will behave the same but still will be separated from other contexts, then limits security pb I would then agree with @Herby changes are strange and dangerous As another example I was thinking about some deviation or how not to use vm, so everything happens in the same context, which is not far from what is proposed here, we could do : //from initial context Then if code is doing something like 'remove all files from your server using fs'.......... I might be wrong in some parts but node-dom gave me so many problems with vm/initial context that I think these remarks are valid, context in vm should have nothing to do with others, and I will propose something for the "this" pb. |
@bnoordhuis not bennoordhuis |
@nais what you suggest is unclear; I’m not seeing what you’re talking about. As I said above, @Herby was simply a little unclear on the Regarding security, that’s a non-argument; the security or lack thereof of VMs are irrelevant, as VMs are not intended to be a secure API. (On that note, @isaacs and I are discussing a new truely secure For this commit, what we’re doing is neither dangerous, nor unintuitive; it’s simply using a straightforward technique to fix an outstanding bug: that the sandbox is static-copy (a hack), not dynamic. |
For whatever reason, there were several duplicate test files related to `Script` and the `'vm'` module. I removed these, and fixed a few other small issues. (More fixes coming in subsequent commits.) Squashes: 19e86045a0..1e3dcff4eb
God, I hate the ~50-character limit on commit messages. Almost impossible to fit useful info in there. Anyway. As described in GH-1801, the `'vm'` module was handling the `sandbox` object provided by the API consumer in a particularly terrible and fragile fashion: it was simply shallow-copying any enumerable properties from the sandbox onto the global context before executing the code, and then eventually copying any values on the global context back into the sandbox object *afterwards*. This commit removes all of that implementation, and utilizes the passed sandbox object as the *prototype of the context* instead. A bit of a hack, but a very effective one. This no longer allows for new variables created in the global context to be placed into your sandbox after execution has completed, but that’s for the best anyway, as it’s not very in line with the concept of a “box of passed-in context.” I’m planning to further implement an interface for API consumers to acquire the *actual global* from within the VM soon, thus allowing for separation-of-concerns: providing data *to* the VM via the sandbox-prototype, and exploring the internal environment of the VM itself. // GitHub cruft: closes #1801 Squashes: 2c1f5206bb..2ab8ab1292
Squashes: e50dba8d7b
After a long discussion with @isaacs, we’ve decided to defer consideration of API changes to ~0.7, and reduce this change to a relatively safe subset of changes that don’t affect the API for immediate inclusion in 0.6. The changes reverted in this commit will be coming back in 0.7, after a discussion of the alternatives. This reverts commit 2c1f5206bbb23bd34624acbcfb475dddcda0b883.
Final note for anybody following this: the clean-up functionality originally discussed here, and then discarded from this pull request, will be discussed on the mailing list for ~0.7. Additionally, it’s possible that we’re going to one-up this entire tactic, by patching |
Could we please revert back for now ? With this + "vm context with accessors" everything is broken now in VM, see the test case below (I have followed what Elliot said in #1674), and it does not even solve #1674, the issues are :
If you uncomment the getter to window in the code, then tests will work but this can not be the solution
|
Reverted in 9d27faa until I have a chance to review. |
Thanks, we should revert too "vm context with accessors", looks not so easy to solve finally (getters/setters), I don't know why ecma specs do allow it but it's not rare that getOwnPropertyDescriptor returns undefined (proto for example), #1674 (even if disturbing) is not blocking, others issues mentionned above are. |
Er, @nais, as I’ve said in #1674, you’re misunderstanding how this is supposed to work. The API is, definitely, a little unclear right now; we’re planning on re-working the entire API for this in 0.7, to make it very explicit and easy to use. The change in this pull request is definitely not reponsible for the “brokenness” you are experiencing, though; that’s simply because you’re using the API in an unintended way. As you put it, “after createContext, the context has nothing to do with the initial object and vice-versa …,” that is intended functionality. @nais, on a related note, please reply to my latest comment on #1674; I’d love to figure out what you were expecting out of |
Er, I don’t know how this got closed. @github’s screwing up. M’bad. |
Haha, I don't get how I "referenced" the revert commit either. So I agree, GitHub's screwin' up... |
@TooTallNate that’s probably entirely my fault. I used undocumented APIs to turn this “Issue” into a “Pull Request,” which @github normally treats as a different thing. I probably borked teh ’hub in the process. #mybad |
@ELLIOTTCABLE, I will reply (again) on #1674, I am not misunderstanding how it is supposed to work, maybe it will be more clear once I have documented https://github.com/Nais/node-dom, you must be able to access window context in the initial context and in vm, then turning window into a context and assigning window global var into that context referring to the context itself so it is available in vm and initial context seems perfectly logical. I gave plenty of examples in both posts, right now if I set a global var in vm, it is not reflected in window for example, so this breaks everything, I know the API is not finished yet but it appears context and window are separate and there is no way to handle this for me. Since there are plenty of parallel discussions, I would appreciate on your side a simple example of what current changes are doing and supposed to solve and what you think should be the result of NOK tests above, if you don't agree with the NOK statement Indeed last changes do break for me the "logical" behavior, since you say it is intended, then please let me know how I should proceed now to correlate window in both contexts. |
@nais I messaged, let’s talk about this in IRC and get everything clear, so we stop wasting space on Issues until we understand eachother. |
I think this was squashed into 200df86. Should be closed? |
PR-URL: nodejs/node#1996 Notable changes * module: The number of syscalls made during a require() have been significantly reduced again (see nodejs#1801 from v2.2.0 for previous work), which should lead to a performance improvement (Pierre Inglebert) nodejs#1920. * npm: - Upgrade to v2.11.2 (Rebecca Turner) nodejs#1956. - Upgrade to v2.11.3 (Forrest L Norvell) nodejs#2018. * zlib: A bug was discovered where the process would abort if the final part of a zlib decompression results in a buffer that would exceed the maximum length of 0x3fffffff bytes (~1GiB). This was likely to only occur during buffered decompression (rather than streaming). This is now fixed and will instead result in a thrown RangeError (Michaël Zasso) nodejs#1811.
I’m not even sure how to go about describing this. What could possibly be going wrong is still far beyond my ability to understand, but I have derived a simple testcase to demonstrate the issue.
The first three testcases demonstrate that the error isn’t anything obvious:
vm
modulevm
is completeThe first three testcases throw no errors; only the last one does.
I’m using the current stable Node as of this posting, Node.js v0.4.12.