Skip to content

Commit

Permalink
forbid "eval" and "arguments" as function names
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Feb 18, 2021
1 parent 030715a commit 281733b
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 6 deletions.
18 changes: 12 additions & 6 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -4261,7 +4261,7 @@ func (p *parser) parseImportClause() ([]js_ast.ClauseItem, bool) {
}

// Reject forbidden names
if originalName == "eval" || originalName == "arguments" {
if isEvalOrArguments(originalName) {
r := js_lexer.RangeOfIdentifier(p.source, name.Loc)
p.log.AddRangeError(&p.source, r, fmt.Sprintf("Cannot use %q as an identifier here", originalName))
}
Expand Down Expand Up @@ -7359,10 +7359,8 @@ func (p *parser) visitBinding(binding js_ast.Binding, opts bindingOpts) {
case *js_ast.BIdentifier:
p.recordDeclaredSymbol(b.Ref)
name := p.symbols[b.Ref.InnerIndex].OriginalName
if p.isStrictMode() {
if name == "eval" || name == "arguments" {
p.markStrictModeFeature(evalOrArguments, js_lexer.RangeOfIdentifier(p.source, binding.Loc), name)
}
if isEvalOrArguments(name) {
p.markStrictModeFeature(evalOrArguments, js_lexer.RangeOfIdentifier(p.source, binding.Loc), name)
}
if opts.duplicateArgCheck != nil {
if opts.duplicateArgCheck[name] {
Expand Down Expand Up @@ -9572,11 +9570,16 @@ func canBeDeleted(expr js_ast.Expr) bool {
return false
}

// This function exists to tie all of these checks together in one place
func isEvalOrArguments(name string) bool {
return name == "eval" || name == "arguments"
}

func (p *parser) isValidAssignmentTarget(expr js_ast.Expr) bool {
switch e := expr.Data.(type) {
case *js_ast.EIdentifier:
if p.isStrictMode() {
if name := p.loadNameFromRef(e.Ref); name == "eval" || name == "arguments" {
if name := p.loadNameFromRef(e.Ref); isEvalOrArguments(name) {
return false
}
}
Expand Down Expand Up @@ -11370,6 +11373,9 @@ func (p *parser) visitFn(fn *js_ast.Fn, scopeLoc logger.Loc) {

if fn.Name != nil {
p.recordDeclaredSymbol(fn.Name.Ref)
if name := p.symbols[fn.Name.Ref.InnerIndex].OriginalName; isEvalOrArguments(name) {
p.markStrictModeFeature(evalOrArguments, js_lexer.RangeOfIdentifier(p.source, fn.Name.Loc), name)
}
}

p.pushScopeForVisitPass(js_ast.ScopeFunctionArgs, scopeLoc)
Expand Down
6 changes: 6 additions & 0 deletions internal/js_parser/js_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,16 @@ func TestStrictMode(t *testing.T) {
expectParseError(t, "'use strict'; arguments += 0", "<stdin>: error: Invalid assignment target\n")
expectParseError(t, "'use strict'; [arguments] = 0", "<stdin>: error: Invalid assignment target\n")

expectPrinted(t, "function eval() {}", "function eval() {\n}\n")
expectPrinted(t, "function f(eval) {}", "function f(eval) {\n}\n")
expectPrinted(t, "function arguments() {}", "function arguments() {\n}\n")
expectPrinted(t, "function f(arguments) {}", "function f(arguments) {\n}\n")
expectParseError(t, "'use strict'; function eval() {}",
"<stdin>: error: Declarations with the name \"eval\" cannot be used in strict mode\n")
expectParseError(t, "'use strict'; function f(eval) {}",
"<stdin>: error: Declarations with the name \"eval\" cannot be used in strict mode\n")
expectParseError(t, "'use strict'; function arguments() {}",
"<stdin>: error: Declarations with the name \"arguments\" cannot be used in strict mode\n")
expectParseError(t, "'use strict'; function f(arguments) {}",
"<stdin>: error: Declarations with the name \"arguments\" cannot be used in strict mode\n")

Expand Down

0 comments on commit 281733b

Please sign in to comment.