So I created the following script as I was experimenting with strict-mode and found a very weird behaviour. If you execute the following code in a script, it logs 19 twice. In the REPL we get the expected error - Uncaught SyntaxError: Identifier 'undefined' has already been declared, same for Infinity as well.
I'm not sure if this is an expected behaviour for a script or a bug
'use strict'
const undefined = 19
const Infinity = 19
console.log(undefined)
console.log(Infinity)
just save this to a file and run the code to observe the behaviour described above.
Maybe throw the same error that we see in the REPL?
I tested this on d8, jsc and spidermonkey, all threw an error when trying to assign to undefined or Infinity. But this doesn't seem to be a spec violation (at least I couldn't find anything on https://www.ecma-international.org/ecma-262/10.0/ that prevents users from assigning to those identifiers). With that being said, I think it makes sense for us to prevent assigning to those identifiers as well as other common ones, but that will be a breaking change.
CommonJS is actually a function wrapper!
globalThis.undefined is non-writable non-configurable property, so assigning to it or trying to shadow it at the top level doesn't work, but functions introduce a new scope.
$ eshost -ts -e "(function() { 'use strict'; const undefined = 42; print(undefined) })()"
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ engine262 โ 42 โ
โ GraalJS โ undefined โ
โ JavaScriptCore โ โ
โ SpiderMonkey โ โ
โ V8 โ โ
โโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Moddable XS โ undefined โ
โ โ undefined โ
โโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ QuickJS โ โ
โ โ SyntaxError: invalid lexical variable name โ
โโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
You can also do this without a function, just introduce a new lexical scope: { const undefined = 42; print(undefined); }
I'm closing this as answered.
Most helpful comment
CommonJS is actually a function wrapper!
globalThis.undefinedis non-writable non-configurable property, so assigning to it or trying to shadow it at the top level doesn't work, but functions introduce a new scope.You can also do this without a function, just introduce a new lexical scope:
{ const undefined = 42; print(undefined); }