diff --git a/lib/parse.js b/lib/parse.js index 5b52d6d16..c99016a08 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1572,66 +1572,66 @@ function parse($TEXT, options) { }); }; - function track_used_binding_identifiers(is_parameter, strict) { - var parameters = new Set(); - var duplicate = false; - var default_assignment = false; - var spread = false; - var strict_mode = !!strict; - var tracker = { - add_parameter: function(token) { - if (parameters.has(token.value)) { - if (duplicate === false) { - duplicate = token; - } - tracker.check_strict(); - } else { - parameters.add(token.value); - if (is_parameter) { - switch (token.value) { - case "arguments": - case "eval": - case "yield": - if (strict_mode) { - token_error(token, "Unexpected " + token.value + " identifier as parameter inside strict mode"); - } - break; - default: - if (RESERVED_WORDS.has(token.value)) { - unexpected(); - } + class UsedParametersTracker { + constructor(is_parameter, strict, duplicates_ok = false) { + this.is_parameter = is_parameter; + this.duplicates_ok = duplicates_ok; + this.parameters = new Set(); + this.duplicate = null; + this.default_assignment = false; + this.spread = false; + this.strict_mode = !!strict; + } + add_parameter(token) { + if (this.parameters.has(token.value)) { + if (this.duplicate === null) { + this.duplicate = token; + } + this.check_strict(); + } else { + this.parameters.add(token.value); + if (this.is_parameter) { + switch (token.value) { + case "arguments": + case "eval": + case "yield": + if (this.strict_mode) { + token_error(token, "Unexpected " + token.value + " identifier as parameter inside strict mode"); + } + break; + default: + if (RESERVED_WORDS.has(token.value)) { + unexpected(); } } } - }, - mark_default_assignment: function(token) { - if (default_assignment === false) { - default_assignment = token; - } - }, - mark_spread: function(token) { - if (spread === false) { - spread = token; - } - }, - mark_strict_mode: function() { - strict_mode = true; - }, - is_strict: function() { - return default_assignment !== false || spread !== false || strict_mode; - }, - check_strict: function() { - if (tracker.is_strict() && duplicate !== false) { - token_error(duplicate, "Parameter " + duplicate.value + " was used already"); - } } - }; - - return tracker; + } + mark_default_assignment(token) { + if (this.default_assignment === false) { + this.default_assignment = token; + } + } + mark_spread(token) { + if (this.spread === false) { + this.spread = token; + } + } + mark_strict_mode() { + this.strict_mode = true; + } + is_strict() { + return this.default_assignment !== false || this.spread !== false || this.strict_mode; + } + check_strict() { + if (this.is_strict() && this.duplicate !== null && !this.duplicates_ok) { + token_error(this.duplicate, "Parameter " + this.duplicate.value + " was used already"); + } + } } function parameters(params) { - var used_parameters = track_used_binding_identifiers(true, S.input.has_directive("use strict")); + var used_parameters = new UsedParametersTracker(true, S.input.has_directive("use strict")); expect("("); @@ -1655,7 +1655,7 @@ function parse($TEXT, options) { var param; var expand = false; if (used_parameters === undefined) { - used_parameters = track_used_binding_identifiers(true, S.input.has_directive("use strict")); + used_parameters = new UsedParametersTracker(true, S.input.has_directive("use strict")); } if (is("expand", "...")) { expand = S.token; @@ -1698,7 +1698,9 @@ function parse($TEXT, options) { var expand_token; var first_token = S.token; if (used_parameters === undefined) { - used_parameters = track_used_binding_identifiers(false, S.input.has_directive("use strict")); + const strict = S.input.has_directive("use strict"); + const duplicates_ok = symbol_type === AST_SymbolVar; + used_parameters = new UsedParametersTracker(false, strict, duplicates_ok); } symbol_type = symbol_type === undefined ? AST_SymbolFunarg : symbol_type; if (is("punc", "[")) { @@ -2091,7 +2093,7 @@ function parse($TEXT, options) { if (is("punc", "{") || is("punc", "[")) { def = new AST_VarDef({ start: S.token, - name: binding_element(undefined ,sym_type), + name: binding_element(undefined, sym_type), value: is("operator", "=") ? (expect_token("operator", "="), expression(false, no_in)) : null, end: prev() });