[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:
marja 2015-03-10 09:47:50 -07:00 committed by Commit bot
parent 9c8bead966
commit 6ad87e4f86
8 changed files with 69 additions and 37 deletions

View File

@ -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> {};
};

View 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);

View 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;

View 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_;

View 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> {};

View 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));

View 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;

View 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();
})();