New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enforce TDZ within initializer of lexical declaration (refactored) #2733
Conversation
7577d37
to
f188a26
Compare
👍
You could make the diff --git a/src/jshint.js b/src/jshint.js
index 0758967..4bb41f0 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -3570,4 +3570,5 @@ var JSHINT = (function() {
state.funct["(scope)"].addlabel(t.id, {
type: type,
+ initialized: false,
token: t.token });
names.push(t.token);
@@ -3743,4 +3744,5 @@ var JSHINT = (function() {
state.funct["(scope)"].addlabel(this.name, {
type: "class",
+ initialized: false,
token: state.tokens.curr });
# ------------------------------------------------- #
# Here I omitted the diff where I removed the extra #
# calls to `state.function["(scope)"].initialize` #
# ------------------------------------------------- #
diff --git a/src/scope-manager.js b/src/scope-manager.js
index 11e141a..767abf2 100644
--- a/src/scope-manager.js
+++ b/src/scope-manager.js
@@ -649,5 +649,5 @@ var scopeManager = function(state, predefined, exported, declared) {
}
- scopeManagerInst.block.add(labelName, type, token, !isexported);
+ scopeManagerInst.block.add(labelName, type, token, !isexported, opts.initialized);
} else {
@@ -813,9 +813,9 @@ var scopeManager = function(state, predefined, exported, declared) {
* Adds a new variable
*/
- add: function(labelName, type, tok, unused) {
+ add: function(labelName, type, tok, unused, initialized) {
_current["(labels)"][labelName] = {
"(type)" : type,
"(token)": tok,
- "(initialized)": false,
+ "(initialized)": initialized !== false,
"(blockscoped)": true,
"(unused)": unused }; |
I had some similar code when I first drafted this patch, but I held off on it because of a gut reaction to the boolean trap for the It's been over two weeks, though, and I've come around on the idea of simply adding that additional boolean parameter. It's an internal method, so the usability concern is kind of minimal. That said, I decided to implement |
Conceptually, the initialization state of a given variable is a property of that variable. Model that relationship in the code organization by tracking variable initialization using a dedicated property on the representation of the variable itself. Beyond improving code clarity (the "label" objects remain the single source of truth for the state of each variable), this also reduces memory allocation costs (no new objects need to be created).
a1e34b1
to
85e4804
Compare
@rwaldron I've rebased this patch (the original version which conflicts with |
Oh very cool :) I will try to review this tomorrow. Feel free to nudge me if I haven't reported back by noon |
@rwaldron Nudging, as requested. |
@jugglinmike is this ready to land when I'm done reviewing? |
Yes, sir. |
I poked and prodded this one for a bit. Nice work! |
Thanks, Rick! |
And thanks, @nicolo-ribaudo! |
…shint#2733) * [[FIX]] Enforce TDZ within initializer of lexical declaration Fixes jshint#2637 * [[FIX]] Enforce TDZ within class heritage definition * [[FIX]] Enforce TDZ within for in/of head Fixes jshintgh-2693 * [[CHORE]] Refactor var initialization tracking Conceptually, the initialization state of a given variable is a property of that variable. Model that relationship in the code organization by tracking variable initialization using a dedicated property on the representation of the variable itself. Beyond improving code clarity (the "label" objects remain the single source of truth for the state of each variable), this also reduces memory allocation costs (no new objects need to be created).
This patch includes work by @nicolo-ribaudo (originally submitted in gh-2701) and a refactoring of my own design.
I initially expected that this approach would reduce some of the noise
associated with explicit maintence of the standalone "definition" objects (e.g.
the calls to
state.funct["(scope)"].definition.reset
). While this turned outto be true, I found that it also introduced a different kind of noise--see
the extra calls to
state.funct["(scope)"].initialize
.I think the latter is preferable because it makes the source code more closely
match the spec language. Readers are more likely to know what it means to
"initialize a label" than what it means to "clear a definition."
Resolves #2637