[strong] make function and class declarations lexical & immutable
authorrossberg <rossberg@chromium.org>
Thu, 19 Feb 2015 16:49:11 +0000 (08:49 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 19 Feb 2015 16:49:19 +0000 (16:49 +0000)
R=arv@chromium.org
BUG=

Review URL: https://codereview.chromium.org/932283003

Cr-Commit-Position: refs/heads/master@{#26755}

src/ast.h
src/parser.cc
test/mjsunit/strong/arguments.js [deleted file]
test/mjsunit/strong/classes.js [new file with mode: 0644]
test/mjsunit/strong/functions.js [new file with mode: 0644]

index 42c8177251e89824f04003e0905703f1c34fac9c..faccb90457675627e553b42291f40c75b26b9dce 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -577,8 +577,7 @@ class FunctionDeclaration FINAL : public Declaration {
                       int pos)
       : Declaration(zone, proxy, mode, scope, pos),
         fun_(fun) {
-    // At the moment there are no "const functions" in JavaScript...
-    DCHECK(mode == VAR || mode == LET);
+    DCHECK(mode == VAR || mode == LET || mode == CONST);
     DCHECK(fun != NULL);
   }
 
index 84a94efbfc6a991bb99b5b6d0a1a038e70a0e1cf..985a90f8dc5f0154a1829680e99f37cb2e008085 100644 (file)
@@ -1975,6 +1975,7 @@ Statement* Parser::ParseFunctionDeclaration(
   // In ES6, a function behaves as a lexical binding, except in
   // a script scope, or the initial scope of eval or another function.
   VariableMode mode =
+      is_strong(language_mode()) ? CONST :
       allow_harmony_scoping() && is_strict(language_mode()) &&
               !(scope_->is_script_scope() || scope_->is_eval_scope() ||
                 scope_->is_function_scope())
@@ -2018,13 +2019,15 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
   ClassLiteral* value = ParseClassLiteral(name, scanner()->location(),
                                           is_strict_reserved, pos, CHECK_OK);
 
-  VariableProxy* proxy = NewUnresolved(name, LET);
+  VariableMode mode = is_strong(language_mode()) ? CONST : LET;
+  VariableProxy* proxy = NewUnresolved(name, mode);
   Declaration* declaration =
-      factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
+      factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
   Declare(declaration, true, CHECK_OK);
   proxy->var()->set_initializer_position(pos);
 
-  Token::Value init_op = Token::INIT_LET;
+  Token::Value init_op =
+      is_strong(language_mode()) ? Token::INIT_CONST : Token::INIT_LET;
   Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos);
   Statement* assignment_statement =
       factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
diff --git a/test/mjsunit/strong/arguments.js b/test/mjsunit/strong/arguments.js
deleted file mode 100644 (file)
index b40b661..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --strong-mode
-
-(function NoArguments() {
-  assertThrows("'use strong'; arguments", SyntaxError);
-  assertThrows("'use strong'; function f() { arguments }", SyntaxError);
-  assertThrows("'use strong'; let f = function() { arguments }", SyntaxError);
-  assertThrows("'use strong'; let f = () => arguments", SyntaxError);
-  // The following are strict mode errors already.
-  assertThrows("'use strong'; let arguments", SyntaxError);
-  assertThrows("'use strong'; function f(arguments) {}", SyntaxError);
-  assertThrows("'use strong'; let f = (arguments) => {}", SyntaxError);
-})();
diff --git a/test/mjsunit/strong/classes.js b/test/mjsunit/strong/classes.js
new file mode 100644 (file)
index 0000000..3c7caf5
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode
+
+'use strong';
+
+class C {}
+
+(function ImmutableClassBindings() {
+  class D {}
+  assertThrows(function(){ eval("C = 0") }, TypeError);
+  assertThrows(function(){ eval("D = 0") }, TypeError);
+  assertEquals('function', typeof C);
+  assertEquals('function', typeof D);
+})();
diff --git a/test/mjsunit/strong/functions.js b/test/mjsunit/strong/functions.js
new file mode 100644 (file)
index 0000000..4869ac6
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode
+
+'use strong';
+
+(function NoArguments() {
+  assertThrows("'use strong'; arguments", SyntaxError);
+  assertThrows("'use strong'; function f() { arguments }", SyntaxError);
+  assertThrows("'use strong'; let f = function() { arguments }", SyntaxError);
+  assertThrows("'use strong'; let f = () => arguments", SyntaxError);
+  // The following are strict mode errors already.
+  assertThrows("'use strong'; let arguments", SyntaxError);
+  assertThrows("'use strong'; function f(arguments) {}", SyntaxError);
+  assertThrows("'use strong'; let f = (arguments) => {}", SyntaxError);
+})();
+
+function g() {}
+
+(function LexicalFunctionBindings(global) {
+  assertEquals('function', typeof g);
+  assertEquals(undefined, global.g);
+})(this);
+
+(function ImmutableFunctionBindings() {
+  function f() {}
+  assertThrows(function(){ eval("g = 0") }, TypeError);
+  assertThrows(function(){ eval("f = 0") }, TypeError);
+  assertEquals('function', typeof g);
+  assertEquals('function', typeof f);
+})();