From 6ad87e4f869523f2cfe048f4538dfe568ad04b5d Mon Sep 17 00:00:00 2001 From: marja Date: Tue, 10 Mar 2015 09:47:50 -0700 Subject: [PATCH] [strong] More scoping related errors: object literal methods. 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 | 2 +- src/code-stubs.h | 2 +- src/globals.h | 25 ++++++++- src/hydrogen-instructions.h | 8 +-- src/objects.h | 5 +- src/preparser.h | 7 ++- src/scopes.cc | 1 + test/mjsunit/strong/declaration-after-use.js | 56 +++++++++++--------- 8 files changed, 69 insertions(+), 37 deletions(-) diff --git a/src/ast.h b/src/ast.h index 847101480e..8a13e21b1e 100644 --- a/src/ast.h +++ b/src/ast.h @@ -2598,7 +2598,7 @@ class FunctionLiteral FINAL : public Expression { class HasDuplicateParameters : public BitField {}; class IsFunction : public BitField {}; class IsParenthesized : public BitField {}; - class FunctionKindBits : public BitField {}; + class FunctionKindBits : public BitField {}; }; diff --git a/src/code-stubs.h b/src/code-stubs.h index 2ae4ba7085..5a2d2691a0 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -614,7 +614,7 @@ class FastNewClosureStub : public HydrogenCodeStub { private: STATIC_ASSERT(LANGUAGE_END == 3); class LanguageModeBits : public BitField {}; - class FunctionKindBits : public BitField {}; + class FunctionKindBits : public BitField {}; DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure); DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub); diff --git a/src/globals.h b/src/globals.h index 8cccefe50b..9547ea2323 100644 --- a/src/globals.h +++ b/src/globals.h @@ -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(kind | FunctionKind::kInObjectLiteral); + DCHECK(IsValidFunctionKind(kind)); + return kind; +} } } // namespace v8::internal namespace i = v8::internal; diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index c6e8a58833..bce610ab6a 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -7580,11 +7580,11 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> { bool IsDeletable() const OVERRIDE { return true; } - class FunctionKindField : public BitField {}; - class PretenureField : public BitField {}; - class HasNoLiteralsField : public BitField {}; + class FunctionKindField : public BitField {}; + class PretenureField : public BitField {}; + class HasNoLiteralsField : public BitField {}; STATIC_ASSERT(LANGUAGE_END == 3); - class LanguageModeField : public BitField {}; + class LanguageModeField : public BitField {}; Handle shared_info_; uint32_t bit_field_; diff --git a/src/objects.h b/src/objects.h index d4b00fb182..ab7778ffba 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4378,7 +4378,7 @@ class ScopeInfo : public FixedArray { class BlockScopeIsClassScopeField : public BitField {}; class FunctionKindField - : public BitField {}; + : public BitField {}; // 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 {}; + class FunctionKindBits : public BitField {}; class DeoptCountBits : public BitField {}; class OptReenableTriesBits : public BitField {}; diff --git a/src/preparser.h b/src/preparser.h index 1b9af9e732..054a33c640 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -2148,6 +2148,8 @@ ParserBase::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::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)); diff --git a/src/scopes.cc b/src/scopes.cc index 4374b7e6e4..b8c357c47e 100644 --- a/src/scopes.cc +++ b/src/scopes.cc @@ -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; diff --git a/test/mjsunit/strong/declaration-after-use.js b/test/mjsunit/strong/declaration-after-use.js index b51b2f7938..8bdccacf6c 100644 --- a/test/mjsunit/strong/declaration-after-use.js +++ b/test/mjsunit/strong/declaration-after-use.js @@ -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(); })();