[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}
This commit is contained in:
parent
9c8bead966
commit
6ad87e4f86
@ -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> {};
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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_;
|
||||
|
@ -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> {};
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user