[strong] More scoping related errors: object literal methods.
authormarja <marja@chromium.org>
Tue, 10 Mar 2015 16:47:50 +0000 (09:47 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 10 Mar 2015 16:48:07 +0000 (16:48 +0000)
This CL adds errors for illegal references which occur inside object literal
methods inside computed properrty names.

BUG=v8:3948,v8:3956
LOG=N

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

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

src/ast.h
src/code-stubs.h
src/globals.h
src/hydrogen-instructions.h
src/objects.h
src/preparser.h
src/scopes.cc
test/mjsunit/strong/declaration-after-use.js

index 847101480e0cc9b8e2ae1aec5a2cf6b16b17b679..8a13e21b1ef9929954f6a5301681bd5eaa21cbbc 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -2598,7 +2598,7 @@ class FunctionLiteral FINAL : public Expression {
   class HasDuplicateParameters : public BitField<ParameterFlag, 3, 1> {};
   class IsFunction : public BitField<IsFunctionFlag, 4, 1> {};
   class IsParenthesized : public BitField<IsParenthesizedFlag, 5, 1> {};
-  class FunctionKindBits : public BitField<FunctionKind, 6, 7> {};
+  class FunctionKindBits : public BitField<FunctionKind, 6, 8> {};
 };
 
 
index 2ae4ba7085e37e1a10b3c0a73acd623034324ac5..5a2d2691a0548c8142ce7cc06aba5e6a9c97341a 100644 (file)
@@ -614,7 +614,7 @@ class FastNewClosureStub : public HydrogenCodeStub {
  private:
   STATIC_ASSERT(LANGUAGE_END == 3);
   class LanguageModeBits : public BitField<LanguageMode, 0, 2> {};
-  class FunctionKindBits : public BitField<FunctionKind, 2, 7> {};
+  class FunctionKindBits : public BitField<FunctionKind, 2, 8> {};
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
   DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
index 8cccefe50b073fac85f98dc3c85478088231edca..9547ea2323a77064f3e2e13a4e43f2821530b832 100644 (file)
@@ -840,8 +840,13 @@ enum FunctionKind {
   kDefaultConstructor = 1 << 4,
   kSubclassConstructor = 1 << 5,
   kBaseConstructor = 1 << 6,
+  kInObjectLiteral = 1 << 7,
   kDefaultBaseConstructor = kDefaultConstructor | kBaseConstructor,
-  kDefaultSubclassConstructor = kDefaultConstructor | kSubclassConstructor
+  kDefaultSubclassConstructor = kDefaultConstructor | kSubclassConstructor,
+  kConciseMethodInObjectLiteral = kConciseMethod | kInObjectLiteral,
+  kConciseGeneratorMethodInObjectLiteral =
+      kConciseGeneratorMethod | kInObjectLiteral,
+  kAccessorFunctionInObjectLiteral = kAccessorFunction | kInObjectLiteral,
 };
 
 
@@ -855,7 +860,10 @@ inline bool IsValidFunctionKind(FunctionKind kind) {
          kind == FunctionKind::kDefaultBaseConstructor ||
          kind == FunctionKind::kDefaultSubclassConstructor ||
          kind == FunctionKind::kBaseConstructor ||
-         kind == FunctionKind::kSubclassConstructor;
+         kind == FunctionKind::kSubclassConstructor ||
+         kind == FunctionKind::kConciseMethodInObjectLiteral ||
+         kind == FunctionKind::kConciseGeneratorMethodInObjectLiteral ||
+         kind == FunctionKind::kAccessorFunctionInObjectLiteral;
 }
 
 
@@ -907,6 +915,19 @@ inline bool IsConstructor(FunctionKind kind) {
          (FunctionKind::kBaseConstructor | FunctionKind::kSubclassConstructor |
           FunctionKind::kDefaultConstructor);
 }
+
+
+inline bool IsInObjectLiteral(FunctionKind kind) {
+  DCHECK(IsValidFunctionKind(kind));
+  return kind & FunctionKind::kInObjectLiteral;
+}
+
+
+inline FunctionKind WithObjectLiteralBit(FunctionKind kind) {
+  kind = static_cast<FunctionKind>(kind | FunctionKind::kInObjectLiteral);
+  DCHECK(IsValidFunctionKind(kind));
+  return kind;
+}
 } }  // namespace v8::internal
 
 namespace i = v8::internal;
index c6e8a588332696fea655d071d6e3e8428b6c9593..bce610ab6a506709e6879aa2bb53bcca821e7e71 100644 (file)
@@ -7580,11 +7580,11 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
 
   bool IsDeletable() const OVERRIDE { return true; }
 
-  class FunctionKindField : public BitField<FunctionKind, 0, 6> {};
-  class PretenureField : public BitField<bool, 6, 1> {};
-  class HasNoLiteralsField : public BitField<bool, 7, 1> {};
+  class FunctionKindField : public BitField<FunctionKind, 0, 8> {};
+  class PretenureField : public BitField<bool, 8, 1> {};
+  class HasNoLiteralsField : public BitField<bool, 9, 1> {};
   STATIC_ASSERT(LANGUAGE_END == 3);
-  class LanguageModeField : public BitField<LanguageMode, 8, 2> {};
+  class LanguageModeField : public BitField<LanguageMode, 10, 2> {};
 
   Handle<SharedFunctionInfo> shared_info_;
   uint32_t bit_field_;
index d4b00fb182b1b9ad4afd0e3bb80b8ec224457ece..ab7778ffba5c302580064068085c476833b76cde 100644 (file)
@@ -4378,7 +4378,7 @@ class ScopeInfo : public FixedArray {
   class BlockScopeIsClassScopeField
       : public BitField<bool, IsSimpleParameterListField::kNext, 1> {};
   class FunctionKindField
-      : public BitField<FunctionKind, BlockScopeIsClassScopeField::kNext, 7> {};
+      : public BitField<FunctionKind, BlockScopeIsClassScopeField::kNext, 8> {};
 
   // BitFields representing the encoded information for context locals in the
   // ContextLocalInfoEntries part.
@@ -7181,6 +7181,7 @@ class SharedFunctionInfo: public HeapObject {
     kIsDefaultConstructor,
     kIsSubclassConstructor,
     kIsBaseConstructor,
+    kInClassLiteral,
     kIsAsmFunction,
     kDeserialized,
     kCompilerHintsCount  // Pseudo entry
@@ -7188,7 +7189,7 @@ class SharedFunctionInfo: public HeapObject {
   // Add hints for other modes when they're added.
   STATIC_ASSERT(LANGUAGE_END == 3);
 
-  class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 7> {};
+  class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 8> {};
 
   class DeoptCountBits : public BitField<int, 0, 4> {};
   class OptReenableTriesBits : public BitField<int, 4, 18> {};
index 1b9af9e732600c75d36b9f3e14d8919e0f3e7bae..054a33c640bd7b6b8f503d631f117e9427a5510e 100644 (file)
@@ -2148,6 +2148,8 @@ ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker,
                          : FunctionKind::kBaseConstructor;
     }
 
+    if (!in_class) kind = WithObjectLiteralBit(kind);
+
     value = this->ParseFunctionLiteral(
         name, scanner()->location(),
         false,  // reserved words are allowed here
@@ -2179,11 +2181,12 @@ ParserBase<Traits>::ParsePropertyDefinition(ObjectLiteralCheckerBase* checker,
                              CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
     }
 
+    FunctionKind kind = FunctionKind::kAccessorFunction;
+    if (!in_class) kind = WithObjectLiteralBit(kind);
     typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
         name, scanner()->location(),
         false,  // reserved words are allowed here
-        FunctionKind::kAccessorFunction, RelocInfo::kNoPosition,
-        FunctionLiteral::ANONYMOUS_EXPRESSION,
+        kind, RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
         is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY,
         CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 
index 4374b7e6e4ebe51daafeb44316adaef5a7866caf..b8c357c47ec3ef30ea547493b60949aa93d9aaed 100644 (file)
@@ -1157,6 +1157,7 @@ bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) {
 
 Variable* Scope::ClassVariableForMethod() const {
   if (!is_function_scope()) return nullptr;
+  if (IsInObjectLiteral(function_kind_)) return nullptr;
   if (!IsConciseMethod(function_kind_) && !IsConstructor(function_kind_) &&
       !IsAccessorFunction(function_kind_)) {
     return nullptr;
index b51b2f7938b07fe4e2baea82a7db674d04d5d904..8bdccacf6c6f480295a017f16b0d96d91b6e00c5 100644 (file)
@@ -105,6 +105,11 @@ function assertThrowsHelper(code, error) {
       "'use strong'; if (false) { let C = class C2 { method() { C; } } }",
       ReferenceError);
 
+  assertThrowsHelper(
+      "'use strong'; if (false) { " +
+      "let C = class C2 { *generator_method() { C; } } }",
+      ReferenceError);
+
   assertThrowsHelper(
       "'use strong'; if (false) { let C = class C2 { " +
           "static a() { return 'A'; } [C.a()]() { return 'B'; } }; }",
@@ -145,14 +150,11 @@ function assertThrowsHelper(code, error) {
           "{ return 'B'; } } }",
       ReferenceError);
 
-  // Methods inside object literals are not sufficiently distinguished from
-  // methods inside classes.
-  // https://code.google.com/p/v8/issues/detail?id=3948
-  // assertThrowsHelper(
-  //     "'use strong'; if (false) { let C = class C2 { " +
-  //         "[({m() { C2; return 'A'; }}).m()]() " +
-  //         "{ return 'B'; } } }",
-  //     ReferenceError);
+  assertThrowsHelper(
+      "'use strong'; if (false) { let C = class C2 { " +
+          "[({m() { C2; return 'A'; }}).m()]() " +
+          "{ return 'B'; } } }",
+      ReferenceError);
 
   assertThrowsHelper(
       "'use strong'; if (false) { let C = class C2 { " +
@@ -160,20 +162,20 @@ function assertThrowsHelper(code, error) {
           "{ return 'B'; } } }",
       ReferenceError);
 
-  // assertThrowsHelper(
-  //     "'use strong';\n" +
-  //         "if (false) {\n" +
-  //         "  class COuter {\n" +
-  //         "    m() {\n" +
-  //         "      class CInner {\n" +
-  //         "        [({ m() { CInner; return 'A'; } }).m()]() {\n" +
-  //         "            return 'B';\n" +
-  //         "        }\n" +
-  //         "      }\n" +
-  //         "    }\n" +
-  //         "  }\n" +
-  //         "}",
-  //     ReferenceError);
+  assertThrowsHelper(
+      "'use strong';\n" +
+          "if (false) {\n" +
+          "  class COuter {\n" +
+          "    m() {\n" +
+          "      class CInner {\n" +
+          "        [({ m() { CInner; return 'A'; } }).m()]() {\n" +
+          "            return 'B';\n" +
+          "        }\n" +
+          "      }\n" +
+          "    }\n" +
+          "  }\n" +
+          "}",
+      ReferenceError);
 })();
 
 
@@ -241,8 +243,8 @@ function assertThrowsHelper(code, error) {
   class C1 { constructor() { C1; } }; new C1();
   let C2 = class C3 { constructor() { C3; } }; new C2();
 
-  class C4 { method() { C4; } }; new C4();
-  let C5 = class C6 { method() { C6; } }; new C5();
+  class C4 { method() { C4; } *generator_method() { C4; } }; new C4();
+  let C5 = class C6 { method() { C6; } *generator_method() { C6; } }; new C5();
 
   class C7 { static method() { C7; } }; new C7();
   let C8 = class C9 { static method() { C9; } }; new C8();
@@ -251,7 +253,7 @@ function assertThrowsHelper(code, error) {
   let C11 = class C12 { get x() { C12; } }; new C11();
 
   // Regression test for unnamed classes.
-  let C12 = class { m() { var1; } };
+  let C13 = class { m() { var1; } };
 
   class COuter {
     m() {
@@ -266,4 +268,8 @@ function assertThrowsHelper(code, error) {
     }
   }
   (new COuter()).m().n();
+
+  // Making sure the check which is supposed to prevent "object literal inside
+  // computed property name references the class name" is not too generic:
+  class C14 { m() { let obj = { n() { C14 } }; obj.n(); } }; (new C14()).m();
 })();