0

I have a unique Javascript evaluation environment that sits on top of Node.

I need to insert an identifier into the current scope's temporal dead zone (TDZ) so that if that identifier is accessed it throws an uninitialized error. These identifiers are not in the originally parsed javascript.

I've spend some time on this, but frankly I'm starting to wonder if it's even possible, or if this is something v8 locks down pretty tightly.

Is it possible to modify the current scope's TDZ to add/remove identifiers using a node/v8 extension?

Thanks!

Me1000
  • 1,760
  • 1
  • 12
  • 14
  • How do you plan to access the block scope at all? It won't exist in your addon? I don't see how you could add a reference in a scope other than the global scope at all. – mmomtchev Mar 07 '22 at 13:26
  • The identifiers exist only before compilation - after compilation you have only references - I don't think this is possible – mmomtchev Mar 07 '22 at 13:42

1 Answers1

0

Out of curiosity, I spent some time investigating this, and I am positive: the identifiers exist only until compilation of the script.

The global scope is a notable exception: it is not really a scope, but an object - global - and the identifiers are properties of this object.

Once a script is compiled, there are no more identifiers - local variables and all values from eventual closures are only references to memory locations.

What you want cannot be accomplished by a Node.js addon - you will have to modify V8 itself.

mmomtchev
  • 2,497
  • 1
  • 8
  • 23
  • I'm fairly certain this is not correct. You can test this by doing `eval("t"); const t = 20;`. You will get a TDZ error in that eval because it is trying to access the `t` variable before it is initialized. However, if you reverse the order of those statements (`const t = 20; eval("t");`), it works fine. In both cases, v8 is relying on the variable name `t` and not a memory location since the eval happens at runtime. – Francisco Ryan Tolmasky I Mar 10 '22 at 16:16
  • You are correct, there is another special case for handling `eval` scopes - and it seems that an `eval` scope is allowed to extend its variables – mmomtchev Mar 10 '22 at 17:44
  • @FranciscoRyanTolmaskyI, when you have `nativeFn(); let t = 20;` that `t=20` is going to reference a memory location, it is not going to load the variable `t` by its identifier. `t` will be resolved when compiling. – mmomtchev Mar 10 '22 at 19:46
  • 1
    OK, but let's say I keep restrict the above problem to always be in an eval scope, such that every line just calls another internal eval (can gist this separately if that doesn't make sense), now we have a scenario where we in theory have access to said references, right? Would we be able to access them in that case? – Francisco Ryan Tolmasky I Mar 10 '22 at 20:54
  • 1
    Here is an example of what I mean: https://gist.github.com/tolmasky/291a70f6cae7d7332a24369d06373c90 – Francisco Ryan Tolmasky I Mar 10 '22 at 20:56
  • 1
    Ugh, hit return expecting to insert newline. Anyways, in the above example, we keep pushing eval scopes, so all the relevant scopes are eval scopes, and in theory not subject to the memory location situation, right? In this scenario we would be capable of doing this? – Francisco Ryan Tolmasky I Mar 10 '22 at 20:57
  • Not counting the fact that it is remarkably ugly, yes, it could probably work. But if you are going all-eval, lots of other possibilities exist - static code analysis, simply inserting 'let xx = undefined' statements in the code, etc... From what I saw in the V8 sources, if a function contains `eval`, rules are somewhat more relaxed - and maybe in this case it would be possible to insert a reference by C++ code - but it will still be impossible to make the already compiled calling function use it – mmomtchev Mar 10 '22 at 21:39