ES6: Add support for method shorthand in object literals
This is governed by the harmony-object-literals flag. BUG=v8:3516 LOG=Y R=rossberg@chromium.org Review URL: https://codereview.chromium.org/477263002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23846 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9261c44fd4
commit
45d8e74cd6
@ -1332,9 +1332,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
|||||||
!pretenure &&
|
!pretenure &&
|
||||||
scope()->is_function_scope() &&
|
scope()->is_function_scope() &&
|
||||||
info->num_literals() == 0) {
|
info->num_literals() == 0) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
|
||||||
info->strict_mode(),
|
|
||||||
info->is_generator());
|
|
||||||
__ mov(r2, Operand(info));
|
__ mov(r2, Operand(info));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5492,9 +5492,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|||||||
// space for nested functions that don't need literals cloning.
|
// space for nested functions that don't need literals cloning.
|
||||||
bool pretenure = instr->hydrogen()->pretenure();
|
bool pretenure = instr->hydrogen()->pretenure();
|
||||||
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
|
||||||
instr->hydrogen()->strict_mode(),
|
instr->hydrogen()->kind());
|
||||||
instr->hydrogen()->is_generator());
|
|
||||||
__ mov(r2, Operand(instr->hydrogen()->shared_info()));
|
__ mov(r2, Operand(instr->hydrogen()->shared_info()));
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1318,9 +1318,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
|||||||
!pretenure &&
|
!pretenure &&
|
||||||
scope()->is_function_scope() &&
|
scope()->is_function_scope() &&
|
||||||
info->num_literals() == 0) {
|
info->num_literals() == 0) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
|
||||||
info->strict_mode(),
|
|
||||||
info->is_generator());
|
|
||||||
__ Mov(x2, Operand(info));
|
__ Mov(x2, Operand(info));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2864,9 +2864,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|||||||
// space for nested functions that don't need literals cloning.
|
// space for nested functions that don't need literals cloning.
|
||||||
bool pretenure = instr->hydrogen()->pretenure();
|
bool pretenure = instr->hydrogen()->pretenure();
|
||||||
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
|
||||||
instr->hydrogen()->strict_mode(),
|
instr->hydrogen()->kind());
|
||||||
instr->hydrogen()->is_generator());
|
|
||||||
__ Mov(x2, Operand(instr->hydrogen()->shared_info()));
|
__ Mov(x2, Operand(instr->hydrogen()->shared_info()));
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
} else {
|
} else {
|
||||||
|
43
src/ast.h
43
src/ast.h
@ -2325,12 +2325,6 @@ class FunctionLiteral FINAL : public Expression {
|
|||||||
kNotParenthesized
|
kNotParenthesized
|
||||||
};
|
};
|
||||||
|
|
||||||
enum KindFlag {
|
|
||||||
kNormalFunction,
|
|
||||||
kArrowFunction,
|
|
||||||
kGeneratorFunction
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ArityRestriction {
|
enum ArityRestriction {
|
||||||
NORMAL_ARITY,
|
NORMAL_ARITY,
|
||||||
GETTER_ARITY,
|
GETTER_ARITY,
|
||||||
@ -2420,8 +2414,16 @@ class FunctionLiteral FINAL : public Expression {
|
|||||||
bitfield_ = IsParenthesized::update(bitfield_, kIsParenthesized);
|
bitfield_ = IsParenthesized::update(bitfield_, kIsParenthesized);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_generator() { return IsGenerator::decode(bitfield_); }
|
FunctionKind kind() { return FunctionKindBits::decode(bitfield_); }
|
||||||
bool is_arrow() { return IsArrow::decode(bitfield_); }
|
bool is_arrow() {
|
||||||
|
return IsArrowFunction(FunctionKindBits::decode(bitfield_));
|
||||||
|
}
|
||||||
|
bool is_generator() {
|
||||||
|
return IsGeneratorFunction(FunctionKindBits::decode(bitfield_));
|
||||||
|
}
|
||||||
|
bool is_concise_method() {
|
||||||
|
return IsConciseMethod(FunctionKindBits::decode(bitfield_));
|
||||||
|
}
|
||||||
|
|
||||||
int ast_node_count() { return ast_properties_.node_count(); }
|
int ast_node_count() { return ast_properties_.node_count(); }
|
||||||
AstProperties::Flags* flags() { return ast_properties_.flags(); }
|
AstProperties::Flags* flags() { return ast_properties_.flags(); }
|
||||||
@ -2445,7 +2447,7 @@ class FunctionLiteral FINAL : public Expression {
|
|||||||
int parameter_count, FunctionType function_type,
|
int parameter_count, FunctionType function_type,
|
||||||
ParameterFlag has_duplicate_parameters,
|
ParameterFlag has_duplicate_parameters,
|
||||||
IsFunctionFlag is_function,
|
IsFunctionFlag is_function,
|
||||||
IsParenthesizedFlag is_parenthesized, KindFlag kind,
|
IsParenthesizedFlag is_parenthesized, FunctionKind kind,
|
||||||
int position, IdGen* id_gen)
|
int position, IdGen* id_gen)
|
||||||
: Expression(zone, position, id_gen),
|
: Expression(zone, position, id_gen),
|
||||||
raw_name_(name),
|
raw_name_(name),
|
||||||
@ -2464,8 +2466,8 @@ class FunctionLiteral FINAL : public Expression {
|
|||||||
HasDuplicateParameters::encode(has_duplicate_parameters) |
|
HasDuplicateParameters::encode(has_duplicate_parameters) |
|
||||||
IsFunction::encode(is_function) |
|
IsFunction::encode(is_function) |
|
||||||
IsParenthesized::encode(is_parenthesized) |
|
IsParenthesized::encode(is_parenthesized) |
|
||||||
IsGenerator::encode(kind == kGeneratorFunction) |
|
FunctionKindBits::encode(kind);
|
||||||
IsArrow::encode(kind == kArrowFunction);
|
DCHECK(IsValidFunctionKind(kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -2486,14 +2488,13 @@ class FunctionLiteral FINAL : public Expression {
|
|||||||
int function_token_position_;
|
int function_token_position_;
|
||||||
|
|
||||||
unsigned bitfield_;
|
unsigned bitfield_;
|
||||||
class IsExpression: public BitField<bool, 0, 1> {};
|
class IsExpression : public BitField<bool, 0, 1> {};
|
||||||
class IsAnonymous: public BitField<bool, 1, 1> {};
|
class IsAnonymous : public BitField<bool, 1, 1> {};
|
||||||
class Pretenure: public BitField<bool, 2, 1> {};
|
class Pretenure : public BitField<bool, 2, 1> {};
|
||||||
class HasDuplicateParameters: public BitField<ParameterFlag, 3, 1> {};
|
class HasDuplicateParameters : public BitField<ParameterFlag, 3, 1> {};
|
||||||
class IsFunction: public BitField<IsFunctionFlag, 4, 1> {};
|
class IsFunction : public BitField<IsFunctionFlag, 4, 1> {};
|
||||||
class IsParenthesized: public BitField<IsParenthesizedFlag, 5, 1> {};
|
class IsParenthesized : public BitField<IsParenthesizedFlag, 5, 1> {};
|
||||||
class IsGenerator : public BitField<bool, 6, 1> {};
|
class FunctionKindBits : public BitField<FunctionKind, 6, 3> {};
|
||||||
class IsArrow : public BitField<bool, 7, 1> {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -3439,8 +3440,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
|
|||||||
FunctionLiteral::ParameterFlag has_duplicate_parameters,
|
FunctionLiteral::ParameterFlag has_duplicate_parameters,
|
||||||
FunctionLiteral::FunctionType function_type,
|
FunctionLiteral::FunctionType function_type,
|
||||||
FunctionLiteral::IsFunctionFlag is_function,
|
FunctionLiteral::IsFunctionFlag is_function,
|
||||||
FunctionLiteral::IsParenthesizedFlag is_parenthesized,
|
FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind,
|
||||||
FunctionLiteral::KindFlag kind, int position) {
|
int position) {
|
||||||
FunctionLiteral* lit = new (zone_) FunctionLiteral(
|
FunctionLiteral* lit = new (zone_) FunctionLiteral(
|
||||||
zone_, name, ast_value_factory, scope, body, materialized_literal_count,
|
zone_, name, ast_value_factory, scope, body, materialized_literal_count,
|
||||||
expected_property_count, handler_count, parameter_count, function_type,
|
expected_property_count, handler_count, parameter_count, function_type,
|
||||||
|
@ -1343,7 +1343,7 @@ HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() {
|
|||||||
NOT_TENURED, JS_FUNCTION_TYPE);
|
NOT_TENURED, JS_FUNCTION_TYPE);
|
||||||
|
|
||||||
int map_index = Context::FunctionMapIndex(casted_stub()->strict_mode(),
|
int map_index = Context::FunctionMapIndex(casted_stub()->strict_mode(),
|
||||||
casted_stub()->is_generator());
|
casted_stub()->kind());
|
||||||
|
|
||||||
// Compute the function map in the current native context and set that
|
// Compute the function map in the current native context and set that
|
||||||
// as the map of the allocated object.
|
// as the map of the allocated object.
|
||||||
|
@ -551,21 +551,27 @@ class NumberToStringStub FINAL : public HydrogenCodeStub {
|
|||||||
class FastNewClosureStub : public HydrogenCodeStub {
|
class FastNewClosureStub : public HydrogenCodeStub {
|
||||||
public:
|
public:
|
||||||
FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
|
FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
|
||||||
bool is_generator)
|
FunctionKind kind)
|
||||||
: HydrogenCodeStub(isolate) {
|
: HydrogenCodeStub(isolate) {
|
||||||
|
DCHECK(IsValidFunctionKind(kind));
|
||||||
set_sub_minor_key(StrictModeBits::encode(strict_mode) |
|
set_sub_minor_key(StrictModeBits::encode(strict_mode) |
|
||||||
IsGeneratorBits::encode(is_generator));
|
FunctionKindBits::encode(kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
StrictMode strict_mode() const {
|
StrictMode strict_mode() const {
|
||||||
return StrictModeBits::decode(sub_minor_key());
|
return StrictModeBits::decode(sub_minor_key());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_generator() const { return IsGeneratorBits::decode(sub_minor_key()); }
|
FunctionKind kind() const {
|
||||||
|
return FunctionKindBits::decode(sub_minor_key());
|
||||||
|
}
|
||||||
|
bool is_arrow() const { return IsArrowFunction(kind()); }
|
||||||
|
bool is_generator() const { return IsGeneratorFunction(kind()); }
|
||||||
|
bool is_concise_method() const { return IsConciseMethod(kind()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class StrictModeBits : public BitField<StrictMode, 0, 1> {};
|
class StrictModeBits : public BitField<StrictMode, 0, 1> {};
|
||||||
class IsGeneratorBits : public BitField<bool, 1, 1> {};
|
class FunctionKindBits : public BitField<FunctionKind, 1, 3> {};
|
||||||
|
|
||||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
|
DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
|
||||||
DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
|
DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
|
||||||
|
@ -654,8 +654,7 @@ static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
|
|||||||
function_info->set_is_function(lit->is_function());
|
function_info->set_is_function(lit->is_function());
|
||||||
function_info->set_bailout_reason(lit->dont_optimize_reason());
|
function_info->set_bailout_reason(lit->dont_optimize_reason());
|
||||||
function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
|
function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
|
||||||
function_info->set_is_generator(lit->is_generator());
|
function_info->set_kind(lit->kind());
|
||||||
function_info->set_is_arrow(lit->is_arrow());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -871,9 +870,8 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
|
|||||||
// Allocate function.
|
// Allocate function.
|
||||||
DCHECK(!info->code().is_null());
|
DCHECK(!info->code().is_null());
|
||||||
result = isolate->factory()->NewSharedFunctionInfo(
|
result = isolate->factory()->NewSharedFunctionInfo(
|
||||||
lit->name(), lit->materialized_literal_count(), lit->is_generator(),
|
lit->name(), lit->materialized_literal_count(), lit->kind(),
|
||||||
lit->is_arrow(), info->code(),
|
info->code(), ScopeInfo::Create(info->scope(), info->zone()),
|
||||||
ScopeInfo::Create(info->scope(), info->zone()),
|
|
||||||
info->feedback_vector());
|
info->feedback_vector());
|
||||||
|
|
||||||
DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
|
DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
|
||||||
@ -1094,9 +1092,8 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(
|
|||||||
|
|
||||||
// Create a shared function info object.
|
// Create a shared function info object.
|
||||||
Handle<SharedFunctionInfo> result = factory->NewSharedFunctionInfo(
|
Handle<SharedFunctionInfo> result = factory->NewSharedFunctionInfo(
|
||||||
literal->name(), literal->materialized_literal_count(),
|
literal->name(), literal->materialized_literal_count(), literal->kind(),
|
||||||
literal->is_generator(), literal->is_arrow(), info.code(), scope_info,
|
info.code(), scope_info, info.feedback_vector());
|
||||||
info.feedback_vector());
|
|
||||||
SetFunctionInfo(result, literal, false, script);
|
SetFunctionInfo(result, literal, false, script);
|
||||||
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
|
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
|
||||||
result->set_allows_lazy_compilation(allow_lazy);
|
result->set_allows_lazy_compilation(allow_lazy);
|
||||||
|
@ -553,14 +553,20 @@ class Context: public FixedArray {
|
|||||||
return kHeaderSize + index * kPointerSize - kHeapObjectTag;
|
return kHeaderSize + index * kPointerSize - kHeapObjectTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FunctionMapIndex(StrictMode strict_mode, bool is_generator) {
|
static int FunctionMapIndex(StrictMode strict_mode, FunctionKind kind) {
|
||||||
return is_generator
|
if (IsGeneratorFunction(kind)) {
|
||||||
? (strict_mode == SLOPPY
|
return strict_mode == SLOPPY ? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
|
||||||
? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
|
: STRICT_GENERATOR_FUNCTION_MAP_INDEX;
|
||||||
: STRICT_GENERATOR_FUNCTION_MAP_INDEX)
|
}
|
||||||
: (strict_mode == SLOPPY
|
|
||||||
? SLOPPY_FUNCTION_MAP_INDEX
|
if (IsConciseMethod(kind)) {
|
||||||
: STRICT_FUNCTION_MAP_INDEX);
|
return strict_mode == SLOPPY
|
||||||
|
? SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX
|
||||||
|
: STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strict_mode == SLOPPY ? SLOPPY_FUNCTION_MAP_INDEX
|
||||||
|
: STRICT_FUNCTION_MAP_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int kSize = kHeaderSize + NATIVE_CONTEXT_SLOTS * kPointerSize;
|
static const int kSize = kHeaderSize + NATIVE_CONTEXT_SLOTS * kPointerSize;
|
||||||
|
@ -1237,6 +1237,9 @@ void Factory::InitializeFunction(Handle<JSFunction> function,
|
|||||||
function->set_prototype_or_initial_map(*the_hole_value());
|
function->set_prototype_or_initial_map(*the_hole_value());
|
||||||
function->set_literals_or_bindings(*empty_fixed_array());
|
function->set_literals_or_bindings(*empty_fixed_array());
|
||||||
function->set_next_function_link(*undefined_value());
|
function->set_next_function_link(*undefined_value());
|
||||||
|
|
||||||
|
// TODO(arv): This does not look correct. We need to make sure we use
|
||||||
|
// a Map that has no prototype property.
|
||||||
if (info->is_arrow()) function->RemovePrototype();
|
if (info->is_arrow()) function->RemovePrototype();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1356,8 +1359,7 @@ Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
|
|||||||
Handle<SharedFunctionInfo> info,
|
Handle<SharedFunctionInfo> info,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
PretenureFlag pretenure) {
|
PretenureFlag pretenure) {
|
||||||
int map_index = Context::FunctionMapIndex(info->strict_mode(),
|
int map_index = Context::FunctionMapIndex(info->strict_mode(), info->kind());
|
||||||
info->is_generator());
|
|
||||||
Handle<Map> map(Map::cast(context->native_context()->get(map_index)));
|
Handle<Map> map(Map::cast(context->native_context()->get(map_index)));
|
||||||
Handle<JSFunction> result = NewFunction(map, info, context, pretenure);
|
Handle<JSFunction> result = NewFunction(map, info, context, pretenure);
|
||||||
|
|
||||||
@ -1904,13 +1906,14 @@ Handle<FixedArray> Factory::NewTypeFeedbackVector(int slot_count) {
|
|||||||
|
|
||||||
|
|
||||||
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
|
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
|
||||||
Handle<String> name, int number_of_literals, bool is_generator,
|
Handle<String> name, int number_of_literals, FunctionKind kind,
|
||||||
bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info,
|
Handle<Code> code, Handle<ScopeInfo> scope_info,
|
||||||
Handle<FixedArray> feedback_vector) {
|
Handle<FixedArray> feedback_vector) {
|
||||||
|
DCHECK(IsValidFunctionKind(kind));
|
||||||
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name, code);
|
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name, code);
|
||||||
shared->set_scope_info(*scope_info);
|
shared->set_scope_info(*scope_info);
|
||||||
shared->set_feedback_vector(*feedback_vector);
|
shared->set_feedback_vector(*feedback_vector);
|
||||||
shared->set_is_arrow(is_arrow);
|
shared->set_kind(kind);
|
||||||
int literals_array_size = number_of_literals;
|
int literals_array_size = number_of_literals;
|
||||||
// If the function contains object, regexp or array literals,
|
// If the function contains object, regexp or array literals,
|
||||||
// allocate extra space for a literals array prefix containing the
|
// allocate extra space for a literals array prefix containing the
|
||||||
@ -1919,7 +1922,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
|
|||||||
literals_array_size += JSFunction::kLiteralsPrefixSize;
|
literals_array_size += JSFunction::kLiteralsPrefixSize;
|
||||||
}
|
}
|
||||||
shared->set_num_literals(literals_array_size);
|
shared->set_num_literals(literals_array_size);
|
||||||
if (is_generator) {
|
if (IsGeneratorFunction(kind)) {
|
||||||
shared->set_instance_class_name(isolate()->heap()->Generator_string());
|
shared->set_instance_class_name(isolate()->heap()->Generator_string());
|
||||||
shared->DisableOptimization(kGenerator);
|
shared->DisableOptimization(kGenerator);
|
||||||
}
|
}
|
||||||
|
@ -598,8 +598,8 @@ class Factory FINAL {
|
|||||||
|
|
||||||
// Allocates a new SharedFunctionInfo object.
|
// Allocates a new SharedFunctionInfo object.
|
||||||
Handle<SharedFunctionInfo> NewSharedFunctionInfo(
|
Handle<SharedFunctionInfo> NewSharedFunctionInfo(
|
||||||
Handle<String> name, int number_of_literals, bool is_generator,
|
Handle<String> name, int number_of_literals, FunctionKind kind,
|
||||||
bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info,
|
Handle<Code> code, Handle<ScopeInfo> scope_info,
|
||||||
Handle<FixedArray> feedback_vector);
|
Handle<FixedArray> feedback_vector);
|
||||||
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name,
|
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name,
|
||||||
MaybeHandle<Code> code);
|
MaybeHandle<Code> code);
|
||||||
|
@ -161,6 +161,8 @@ DEFINE_BOOL(harmony_strings, false, "enable harmony string")
|
|||||||
DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays")
|
DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays")
|
||||||
DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions")
|
DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions")
|
||||||
DEFINE_BOOL(harmony_classes, false, "enable harmony classes")
|
DEFINE_BOOL(harmony_classes, false, "enable harmony classes")
|
||||||
|
DEFINE_BOOL(harmony_object_literals, false,
|
||||||
|
"enable harmony object literal extensions")
|
||||||
DEFINE_BOOL(harmony, false, "enable all harmony features (except proxies)")
|
DEFINE_BOOL(harmony, false, "enable all harmony features (except proxies)")
|
||||||
|
|
||||||
DEFINE_IMPLICATION(harmony, harmony_scoping)
|
DEFINE_IMPLICATION(harmony, harmony_scoping)
|
||||||
@ -172,6 +174,7 @@ DEFINE_IMPLICATION(harmony, harmony_strings)
|
|||||||
DEFINE_IMPLICATION(harmony, harmony_arrays)
|
DEFINE_IMPLICATION(harmony, harmony_arrays)
|
||||||
DEFINE_IMPLICATION(harmony, harmony_arrow_functions)
|
DEFINE_IMPLICATION(harmony, harmony_arrow_functions)
|
||||||
DEFINE_IMPLICATION(harmony, harmony_classes)
|
DEFINE_IMPLICATION(harmony, harmony_classes)
|
||||||
|
DEFINE_IMPLICATION(harmony, harmony_object_literals)
|
||||||
DEFINE_IMPLICATION(harmony_modules, harmony_scoping)
|
DEFINE_IMPLICATION(harmony_modules, harmony_scoping)
|
||||||
|
|
||||||
DEFINE_IMPLICATION(harmony, es_staging)
|
DEFINE_IMPLICATION(harmony, es_staging)
|
||||||
|
@ -1547,11 +1547,9 @@ void FullCodeGenerator::VisitNativeFunctionLiteral(
|
|||||||
const int literals = fun->NumberOfLiterals();
|
const int literals = fun->NumberOfLiterals();
|
||||||
Handle<Code> code = Handle<Code>(fun->shared()->code());
|
Handle<Code> code = Handle<Code>(fun->shared()->code());
|
||||||
Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
|
Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
|
||||||
bool is_generator = false;
|
|
||||||
bool is_arrow = false;
|
|
||||||
Handle<SharedFunctionInfo> shared =
|
Handle<SharedFunctionInfo> shared =
|
||||||
isolate()->factory()->NewSharedFunctionInfo(
|
isolate()->factory()->NewSharedFunctionInfo(
|
||||||
name, literals, is_generator, is_arrow, code,
|
name, literals, FunctionKind::kNormalFunction, code,
|
||||||
Handle<ScopeInfo>(fun->shared()->scope_info()),
|
Handle<ScopeInfo>(fun->shared()->scope_info()),
|
||||||
Handle<FixedArray>(fun->shared()->feedback_vector()));
|
Handle<FixedArray>(fun->shared()->feedback_vector()));
|
||||||
shared->set_construct_stub(*construct_stub);
|
shared->set_construct_stub(*construct_stub);
|
||||||
|
@ -756,6 +756,41 @@ enum MinusZeroMode {
|
|||||||
FAIL_ON_MINUS_ZERO
|
FAIL_ON_MINUS_ZERO
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum FunctionKind {
|
||||||
|
kNormalFunction = 0,
|
||||||
|
kArrowFunction = 1,
|
||||||
|
kGeneratorFunction = 2,
|
||||||
|
kConciseMethod = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline bool IsValidFunctionKind(FunctionKind kind) {
|
||||||
|
// At the moment these are mutually exclusive but in the future that wont be
|
||||||
|
// the case since ES6 allows concise generator methods.
|
||||||
|
return kind == FunctionKind::kNormalFunction ||
|
||||||
|
kind == FunctionKind::kArrowFunction ||
|
||||||
|
kind == FunctionKind::kGeneratorFunction ||
|
||||||
|
kind == FunctionKind::kConciseMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool IsArrowFunction(FunctionKind kind) {
|
||||||
|
DCHECK(IsValidFunctionKind(kind));
|
||||||
|
return kind & FunctionKind::kArrowFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool IsGeneratorFunction(FunctionKind kind) {
|
||||||
|
DCHECK(IsValidFunctionKind(kind));
|
||||||
|
return kind & FunctionKind::kGeneratorFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool IsConciseMethod(FunctionKind kind) {
|
||||||
|
DCHECK(IsValidFunctionKind(kind));
|
||||||
|
return kind & FunctionKind::kConciseMethod;
|
||||||
|
}
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
|
||||||
namespace i = v8::internal;
|
namespace i = v8::internal;
|
||||||
|
@ -7481,18 +7481,20 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
|
|||||||
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
|
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
|
||||||
bool pretenure() const { return pretenure_; }
|
bool pretenure() const { return pretenure_; }
|
||||||
bool has_no_literals() const { return has_no_literals_; }
|
bool has_no_literals() const { return has_no_literals_; }
|
||||||
bool is_generator() const { return is_generator_; }
|
bool is_arrow() const { return IsArrowFunction(kind_); }
|
||||||
|
bool is_generator() const { return IsGeneratorFunction(kind_); }
|
||||||
|
bool is_concise_method() const { return IsConciseMethod(kind_); }
|
||||||
|
FunctionKind kind() const { return kind_; }
|
||||||
StrictMode strict_mode() const { return strict_mode_; }
|
StrictMode strict_mode() const { return strict_mode_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HFunctionLiteral(HValue* context,
|
HFunctionLiteral(HValue* context, Handle<SharedFunctionInfo> shared,
|
||||||
Handle<SharedFunctionInfo> shared,
|
|
||||||
bool pretenure)
|
bool pretenure)
|
||||||
: HTemplateInstruction<1>(HType::JSObject()),
|
: HTemplateInstruction<1>(HType::JSObject()),
|
||||||
shared_info_(shared),
|
shared_info_(shared),
|
||||||
|
kind_(shared->kind()),
|
||||||
pretenure_(pretenure),
|
pretenure_(pretenure),
|
||||||
has_no_literals_(shared->num_literals() == 0),
|
has_no_literals_(shared->num_literals() == 0),
|
||||||
is_generator_(shared->is_generator()),
|
|
||||||
strict_mode_(shared->strict_mode()) {
|
strict_mode_(shared->strict_mode()) {
|
||||||
SetOperandAt(0, context);
|
SetOperandAt(0, context);
|
||||||
set_representation(Representation::Tagged());
|
set_representation(Representation::Tagged());
|
||||||
@ -7502,9 +7504,9 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
|
|||||||
virtual bool IsDeletable() const OVERRIDE { return true; }
|
virtual bool IsDeletable() const OVERRIDE { return true; }
|
||||||
|
|
||||||
Handle<SharedFunctionInfo> shared_info_;
|
Handle<SharedFunctionInfo> shared_info_;
|
||||||
|
FunctionKind kind_;
|
||||||
bool pretenure_ : 1;
|
bool pretenure_ : 1;
|
||||||
bool has_no_literals_ : 1;
|
bool has_no_literals_ : 1;
|
||||||
bool is_generator_ : 1;
|
|
||||||
StrictMode strict_mode_;
|
StrictMode strict_mode_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1254,9 +1254,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
|||||||
!pretenure &&
|
!pretenure &&
|
||||||
scope()->is_function_scope() &&
|
scope()->is_function_scope() &&
|
||||||
info->num_literals() == 0) {
|
info->num_literals() == 0) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
|
||||||
info->strict_mode(),
|
|
||||||
info->is_generator());
|
|
||||||
__ mov(ebx, Immediate(info));
|
__ mov(ebx, Immediate(info));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5290,9 +5290,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|||||||
// space for nested functions that don't need literals cloning.
|
// space for nested functions that don't need literals cloning.
|
||||||
bool pretenure = instr->hydrogen()->pretenure();
|
bool pretenure = instr->hydrogen()->pretenure();
|
||||||
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
|
||||||
instr->hydrogen()->strict_mode(),
|
instr->hydrogen()->kind());
|
||||||
instr->hydrogen()->is_generator());
|
|
||||||
__ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
|
__ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1319,9 +1319,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
|||||||
!pretenure &&
|
!pretenure &&
|
||||||
scope()->is_function_scope() &&
|
scope()->is_function_scope() &&
|
||||||
info->num_literals() == 0) {
|
info->num_literals() == 0) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
|
||||||
info->strict_mode(),
|
|
||||||
info->is_generator());
|
|
||||||
__ li(a2, Operand(info));
|
__ li(a2, Operand(info));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5479,9 +5479,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|||||||
// space for nested functions that don't need literals cloning.
|
// space for nested functions that don't need literals cloning.
|
||||||
bool pretenure = instr->hydrogen()->pretenure();
|
bool pretenure = instr->hydrogen()->pretenure();
|
||||||
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
|
||||||
instr->hydrogen()->strict_mode(),
|
instr->hydrogen()->kind());
|
||||||
instr->hydrogen()->is_generator());
|
|
||||||
__ li(a2, Operand(instr->hydrogen()->shared_info()));
|
__ li(a2, Operand(instr->hydrogen()->shared_info()));
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1314,9 +1314,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
|||||||
!pretenure &&
|
!pretenure &&
|
||||||
scope()->is_function_scope() &&
|
scope()->is_function_scope() &&
|
||||||
info->num_literals() == 0) {
|
info->num_literals() == 0) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
|
||||||
info->strict_mode(),
|
|
||||||
info->is_generator());
|
|
||||||
__ li(a2, Operand(info));
|
__ li(a2, Operand(info));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5519,9 +5519,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|||||||
// space for nested functions that don't need literals cloning.
|
// space for nested functions that don't need literals cloning.
|
||||||
bool pretenure = instr->hydrogen()->pretenure();
|
bool pretenure = instr->hydrogen()->pretenure();
|
||||||
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
|
||||||
instr->hydrogen()->strict_mode(),
|
instr->hydrogen()->kind());
|
||||||
instr->hydrogen()->is_generator());
|
|
||||||
__ li(a2, Operand(instr->hydrogen()->shared_info()));
|
__ li(a2, Operand(instr->hydrogen()->shared_info()));
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5559,6 +5559,19 @@ void SharedFunctionInfo::set_strict_mode(StrictMode strict_mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FunctionKind SharedFunctionInfo::kind() {
|
||||||
|
return FunctionKindBits::decode(compiler_hints());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SharedFunctionInfo::set_kind(FunctionKind kind) {
|
||||||
|
DCHECK(IsValidFunctionKind(kind));
|
||||||
|
int hints = compiler_hints();
|
||||||
|
hints = FunctionKindBits::update(hints, kind);
|
||||||
|
set_compiler_hints(hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
|
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
|
||||||
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
|
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
|
||||||
kInlineBuiltin)
|
kInlineBuiltin)
|
||||||
@ -5570,8 +5583,10 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
|
|||||||
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
|
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
|
||||||
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
|
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
|
||||||
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
|
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
|
||||||
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
|
|
||||||
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow)
|
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow)
|
||||||
|
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
|
||||||
|
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
|
||||||
|
kIsConciseMethod)
|
||||||
|
|
||||||
ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
|
ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
|
||||||
ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
|
ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
|
||||||
|
@ -7121,6 +7121,12 @@ class SharedFunctionInfo: public HeapObject {
|
|||||||
// Indicates that this function is an arrow function.
|
// Indicates that this function is an arrow function.
|
||||||
DECL_BOOLEAN_ACCESSORS(is_arrow)
|
DECL_BOOLEAN_ACCESSORS(is_arrow)
|
||||||
|
|
||||||
|
// Indicates that this function is a concise method.
|
||||||
|
DECL_BOOLEAN_ACCESSORS(is_concise_method)
|
||||||
|
|
||||||
|
inline FunctionKind kind();
|
||||||
|
inline void set_kind(FunctionKind kind);
|
||||||
|
|
||||||
// Indicates whether or not the code in the shared function support
|
// Indicates whether or not the code in the shared function support
|
||||||
// deoptimization.
|
// deoptimization.
|
||||||
inline bool has_deoptimization_support();
|
inline bool has_deoptimization_support();
|
||||||
@ -7315,17 +7321,20 @@ class SharedFunctionInfo: public HeapObject {
|
|||||||
kIsFunction,
|
kIsFunction,
|
||||||
kDontCache,
|
kDontCache,
|
||||||
kDontFlush,
|
kDontFlush,
|
||||||
kIsGenerator,
|
|
||||||
kIsArrow,
|
kIsArrow,
|
||||||
|
kIsGenerator,
|
||||||
|
kIsConciseMethod,
|
||||||
kCompilerHintsCount // Pseudo entry
|
kCompilerHintsCount // Pseudo entry
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeoptCountBits: public BitField<int, 0, 4> {};
|
class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 3> {};
|
||||||
class OptReenableTriesBits: public BitField<int, 4, 18> {};
|
|
||||||
class ICAgeBits: public BitField<int, 22, 8> {};
|
|
||||||
|
|
||||||
class OptCountBits: public BitField<int, 0, 22> {};
|
class DeoptCountBits : public BitField<int, 0, 4> {};
|
||||||
class DisabledOptimizationReasonBits: public BitField<int, 22, 8> {};
|
class OptReenableTriesBits : public BitField<int, 4, 18> {};
|
||||||
|
class ICAgeBits : public BitField<int, 22, 8> {};
|
||||||
|
|
||||||
|
class OptCountBits : public BitField<int, 0, 22> {};
|
||||||
|
class DisabledOptimizationReasonBits : public BitField<int, 22, 8> {};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if V8_HOST_ARCH_32_BIT
|
#if V8_HOST_ARCH_32_BIT
|
||||||
|
@ -724,18 +724,13 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
|
|||||||
|
|
||||||
|
|
||||||
FunctionLiteral* ParserTraits::ParseFunctionLiteral(
|
FunctionLiteral* ParserTraits::ParseFunctionLiteral(
|
||||||
const AstRawString* name,
|
const AstRawString* name, Scanner::Location function_name_location,
|
||||||
Scanner::Location function_name_location,
|
bool name_is_strict_reserved, FunctionKind kind,
|
||||||
bool name_is_strict_reserved,
|
int function_token_position, FunctionLiteral::FunctionType type,
|
||||||
bool is_generator,
|
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
|
||||||
int function_token_position,
|
return parser_->ParseFunctionLiteral(
|
||||||
FunctionLiteral::FunctionType type,
|
name, function_name_location, name_is_strict_reserved, kind,
|
||||||
FunctionLiteral::ArityRestriction arity_restriction,
|
function_token_position, type, arity_restriction, ok);
|
||||||
bool* ok) {
|
|
||||||
return parser_->ParseFunctionLiteral(name, function_name_location,
|
|
||||||
name_is_strict_reserved, is_generator,
|
|
||||||
function_token_position, type,
|
|
||||||
arity_restriction, ok);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -767,6 +762,7 @@ Parser::Parser(CompilationInfo* info, ParseInfo* parse_info)
|
|||||||
set_allow_arrow_functions(FLAG_harmony_arrow_functions);
|
set_allow_arrow_functions(FLAG_harmony_arrow_functions);
|
||||||
set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
|
set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
|
||||||
set_allow_classes(FLAG_harmony_classes);
|
set_allow_classes(FLAG_harmony_classes);
|
||||||
|
set_allow_harmony_object_literals(FLAG_harmony_object_literals);
|
||||||
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
|
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
|
||||||
++feature) {
|
++feature) {
|
||||||
use_counts_[feature] = 0;
|
use_counts_[feature] = 0;
|
||||||
@ -911,8 +907,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
|||||||
function_state.handler_count(), 0,
|
function_state.handler_count(), 0,
|
||||||
FunctionLiteral::kNoDuplicateParameters,
|
FunctionLiteral::kNoDuplicateParameters,
|
||||||
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
|
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
|
||||||
FunctionLiteral::kNotParenthesized, FunctionLiteral::kNormalFunction,
|
FunctionLiteral::kNotParenthesized, FunctionKind::kNormalFunction, 0);
|
||||||
0);
|
|
||||||
result->set_ast_properties(factory()->visitor()->ast_properties());
|
result->set_ast_properties(factory()->visitor()->ast_properties());
|
||||||
result->set_dont_optimize_reason(
|
result->set_dont_optimize_reason(
|
||||||
factory()->visitor()->dont_optimize_reason());
|
factory()->visitor()->dont_optimize_reason());
|
||||||
@ -999,18 +994,16 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
|
|||||||
? FunctionLiteral::ANONYMOUS_EXPRESSION
|
? FunctionLiteral::ANONYMOUS_EXPRESSION
|
||||||
: FunctionLiteral::NAMED_EXPRESSION)
|
: FunctionLiteral::NAMED_EXPRESSION)
|
||||||
: FunctionLiteral::DECLARATION;
|
: FunctionLiteral::DECLARATION;
|
||||||
bool is_generator = shared_info->is_generator();
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
if (shared_info->is_arrow()) {
|
if (shared_info->is_arrow()) {
|
||||||
DCHECK(!is_generator);
|
|
||||||
Expression* expression = ParseExpression(false, &ok);
|
Expression* expression = ParseExpression(false, &ok);
|
||||||
DCHECK(expression->IsFunctionLiteral());
|
DCHECK(expression->IsFunctionLiteral());
|
||||||
result = expression->AsFunctionLiteral();
|
result = expression->AsFunctionLiteral();
|
||||||
} else {
|
} else {
|
||||||
result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
|
result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
|
||||||
false, // Strict mode name already checked.
|
false, // Strict mode name already checked.
|
||||||
is_generator, RelocInfo::kNoPosition,
|
shared_info->kind(), RelocInfo::kNoPosition,
|
||||||
function_type,
|
function_type,
|
||||||
FunctionLiteral::NORMAL_ARITY, &ok);
|
FunctionLiteral::NORMAL_ARITY, &ok);
|
||||||
}
|
}
|
||||||
@ -1894,14 +1887,12 @@ Statement* Parser::ParseFunctionDeclaration(
|
|||||||
bool is_strict_reserved = false;
|
bool is_strict_reserved = false;
|
||||||
const AstRawString* name = ParseIdentifierOrStrictReservedWord(
|
const AstRawString* name = ParseIdentifierOrStrictReservedWord(
|
||||||
&is_strict_reserved, CHECK_OK);
|
&is_strict_reserved, CHECK_OK);
|
||||||
FunctionLiteral* fun = ParseFunctionLiteral(name,
|
FunctionLiteral* fun =
|
||||||
scanner()->location(),
|
ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
|
||||||
is_strict_reserved,
|
is_generator ? FunctionKind::kGeneratorFunction
|
||||||
is_generator,
|
: FunctionKind::kNormalFunction,
|
||||||
pos,
|
pos, FunctionLiteral::DECLARATION,
|
||||||
FunctionLiteral::DECLARATION,
|
FunctionLiteral::NORMAL_ARITY, CHECK_OK);
|
||||||
FunctionLiteral::NORMAL_ARITY,
|
|
||||||
CHECK_OK);
|
|
||||||
// Even if we're not at the top-level of the global or a function
|
// Even if we're not at the top-level of the global or a function
|
||||||
// scope, we treat it as such and introduce the function with its
|
// scope, we treat it as such and introduce the function with its
|
||||||
// initial value upon entering the corresponding scope.
|
// initial value upon entering the corresponding scope.
|
||||||
@ -3365,14 +3356,10 @@ int ParserTraits::DeclareArrowParametersFromExpression(
|
|||||||
|
|
||||||
|
|
||||||
FunctionLiteral* Parser::ParseFunctionLiteral(
|
FunctionLiteral* Parser::ParseFunctionLiteral(
|
||||||
const AstRawString* function_name,
|
const AstRawString* function_name, Scanner::Location function_name_location,
|
||||||
Scanner::Location function_name_location,
|
bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
|
||||||
bool name_is_strict_reserved,
|
|
||||||
bool is_generator,
|
|
||||||
int function_token_pos,
|
|
||||||
FunctionLiteral::FunctionType function_type,
|
FunctionLiteral::FunctionType function_type,
|
||||||
FunctionLiteral::ArityRestriction arity_restriction,
|
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
|
||||||
bool* ok) {
|
|
||||||
// Function ::
|
// Function ::
|
||||||
// '(' FormalParameterList? ')' '{' FunctionBody '}'
|
// '(' FormalParameterList? ')' '{' FunctionBody '}'
|
||||||
//
|
//
|
||||||
@ -3385,6 +3372,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
int pos = function_token_pos == RelocInfo::kNoPosition
|
int pos = function_token_pos == RelocInfo::kNoPosition
|
||||||
? peek_position() : function_token_pos;
|
? peek_position() : function_token_pos;
|
||||||
|
|
||||||
|
bool is_generator = IsGeneratorFunction(kind);
|
||||||
|
|
||||||
// Anonymous functions were passed either the empty symbol or a null
|
// Anonymous functions were passed either the empty symbol or a null
|
||||||
// handle as the function name. Remember if we were passed a non-empty
|
// handle as the function name. Remember if we were passed a non-empty
|
||||||
// handle to decide whether to invoke function name inference.
|
// handle to decide whether to invoke function name inference.
|
||||||
@ -3593,7 +3582,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate strict mode.
|
// Validate strict mode.
|
||||||
if (strict_mode() == STRICT) {
|
// Concise methods use StrictFormalParameters.
|
||||||
|
if (strict_mode() == STRICT || IsConciseMethod(kind)) {
|
||||||
CheckStrictFunctionNameAndParameters(function_name,
|
CheckStrictFunctionNameAndParameters(function_name,
|
||||||
name_is_strict_reserved,
|
name_is_strict_reserved,
|
||||||
function_name_location,
|
function_name_location,
|
||||||
@ -3601,6 +3591,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
dupe_error_loc,
|
dupe_error_loc,
|
||||||
reserved_loc,
|
reserved_loc,
|
||||||
CHECK_OK);
|
CHECK_OK);
|
||||||
|
}
|
||||||
|
if (strict_mode() == STRICT) {
|
||||||
CheckOctalLiteral(scope->start_position(),
|
CheckOctalLiteral(scope->start_position(),
|
||||||
scope->end_position(),
|
scope->end_position(),
|
||||||
CHECK_OK);
|
CHECK_OK);
|
||||||
@ -3613,9 +3605,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionLiteral::KindFlag kind = is_generator
|
|
||||||
? FunctionLiteral::kGeneratorFunction
|
|
||||||
: FunctionLiteral::kNormalFunction;
|
|
||||||
FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
|
FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
|
||||||
function_name, ast_value_factory_, scope, body,
|
function_name, ast_value_factory_, scope, body,
|
||||||
materialized_literal_count, expected_property_count, handler_count,
|
materialized_literal_count, expected_property_count, handler_count,
|
||||||
@ -3775,6 +3764,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
|
|||||||
reusable_preparser_->set_allow_harmony_numeric_literals(
|
reusable_preparser_->set_allow_harmony_numeric_literals(
|
||||||
allow_harmony_numeric_literals());
|
allow_harmony_numeric_literals());
|
||||||
reusable_preparser_->set_allow_classes(allow_classes());
|
reusable_preparser_->set_allow_classes(allow_classes());
|
||||||
|
reusable_preparser_->set_allow_harmony_object_literals(
|
||||||
|
allow_harmony_object_literals());
|
||||||
}
|
}
|
||||||
PreParser::PreParseResult result =
|
PreParser::PreParseResult result =
|
||||||
reusable_preparser_->PreParseLazyFunction(strict_mode(),
|
reusable_preparser_->PreParseLazyFunction(strict_mode(),
|
||||||
|
24
src/parser.h
24
src/parser.h
@ -573,14 +573,10 @@ class ParserTraits {
|
|||||||
// Temporary glue; these functions will move to ParserBase.
|
// Temporary glue; these functions will move to ParserBase.
|
||||||
Expression* ParseV8Intrinsic(bool* ok);
|
Expression* ParseV8Intrinsic(bool* ok);
|
||||||
FunctionLiteral* ParseFunctionLiteral(
|
FunctionLiteral* ParseFunctionLiteral(
|
||||||
const AstRawString* name,
|
const AstRawString* name, Scanner::Location function_name_location,
|
||||||
Scanner::Location function_name_location,
|
bool name_is_strict_reserved, FunctionKind kind,
|
||||||
bool name_is_strict_reserved,
|
int function_token_position, FunctionLiteral::FunctionType type,
|
||||||
bool is_generator,
|
FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
|
||||||
int function_token_position,
|
|
||||||
FunctionLiteral::FunctionType type,
|
|
||||||
FunctionLiteral::ArityRestriction arity_restriction,
|
|
||||||
bool* ok);
|
|
||||||
V8_INLINE void SkipLazyFunctionBody(const AstRawString* name,
|
V8_INLINE void SkipLazyFunctionBody(const AstRawString* name,
|
||||||
int* materialized_literal_count,
|
int* materialized_literal_count,
|
||||||
int* expected_property_count, bool* ok);
|
int* expected_property_count, bool* ok);
|
||||||
@ -746,14 +742,10 @@ class Parser : public ParserBase<ParserTraits> {
|
|||||||
Statement* body, bool* ok);
|
Statement* body, bool* ok);
|
||||||
|
|
||||||
FunctionLiteral* ParseFunctionLiteral(
|
FunctionLiteral* ParseFunctionLiteral(
|
||||||
const AstRawString* name,
|
const AstRawString* name, Scanner::Location function_name_location,
|
||||||
Scanner::Location function_name_location,
|
bool name_is_strict_reserved, FunctionKind kind,
|
||||||
bool name_is_strict_reserved,
|
int function_token_position, FunctionLiteral::FunctionType type,
|
||||||
bool is_generator,
|
FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
|
||||||
int function_token_position,
|
|
||||||
FunctionLiteral::FunctionType type,
|
|
||||||
FunctionLiteral::ArityRestriction arity_restriction,
|
|
||||||
bool* ok);
|
|
||||||
|
|
||||||
// Magical syntax support.
|
// Magical syntax support.
|
||||||
Expression* ParseV8Intrinsic(bool* ok);
|
Expression* ParseV8Intrinsic(bool* ok);
|
||||||
|
@ -102,16 +102,12 @@ PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
|
|||||||
|
|
||||||
|
|
||||||
PreParserExpression PreParserTraits::ParseFunctionLiteral(
|
PreParserExpression PreParserTraits::ParseFunctionLiteral(
|
||||||
PreParserIdentifier name,
|
PreParserIdentifier name, Scanner::Location function_name_location,
|
||||||
Scanner::Location function_name_location,
|
bool name_is_strict_reserved, FunctionKind kind,
|
||||||
bool name_is_strict_reserved,
|
int function_token_position, FunctionLiteral::FunctionType type,
|
||||||
bool is_generator,
|
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
|
||||||
int function_token_position,
|
|
||||||
FunctionLiteral::FunctionType type,
|
|
||||||
FunctionLiteral::ArityRestriction arity_restriction,
|
|
||||||
bool* ok) {
|
|
||||||
return pre_parser_->ParseFunctionLiteral(
|
return pre_parser_->ParseFunctionLiteral(
|
||||||
name, function_name_location, name_is_strict_reserved, is_generator,
|
name, function_name_location, name_is_strict_reserved, kind,
|
||||||
function_token_position, type, arity_restriction, ok);
|
function_token_position, type, arity_restriction, ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,14 +336,11 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
|
|||||||
bool is_strict_reserved = false;
|
bool is_strict_reserved = false;
|
||||||
Identifier name = ParseIdentifierOrStrictReservedWord(
|
Identifier name = ParseIdentifierOrStrictReservedWord(
|
||||||
&is_strict_reserved, CHECK_OK);
|
&is_strict_reserved, CHECK_OK);
|
||||||
ParseFunctionLiteral(name,
|
ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
|
||||||
scanner()->location(),
|
is_generator ? FunctionKind::kGeneratorFunction
|
||||||
is_strict_reserved,
|
: FunctionKind::kNormalFunction,
|
||||||
is_generator,
|
pos, FunctionLiteral::DECLARATION,
|
||||||
pos,
|
FunctionLiteral::NORMAL_ARITY, CHECK_OK);
|
||||||
FunctionLiteral::DECLARATION,
|
|
||||||
FunctionLiteral::NORMAL_ARITY,
|
|
||||||
CHECK_OK);
|
|
||||||
return Statement::FunctionDeclaration();
|
return Statement::FunctionDeclaration();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,14 +798,10 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
|
|||||||
|
|
||||||
|
|
||||||
PreParser::Expression PreParser::ParseFunctionLiteral(
|
PreParser::Expression PreParser::ParseFunctionLiteral(
|
||||||
Identifier function_name,
|
Identifier function_name, Scanner::Location function_name_location,
|
||||||
Scanner::Location function_name_location,
|
bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
|
||||||
bool name_is_strict_reserved,
|
|
||||||
bool is_generator,
|
|
||||||
int function_token_pos,
|
|
||||||
FunctionLiteral::FunctionType function_type,
|
FunctionLiteral::FunctionType function_type,
|
||||||
FunctionLiteral::ArityRestriction arity_restriction,
|
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
|
||||||
bool* ok) {
|
|
||||||
// Function ::
|
// Function ::
|
||||||
// '(' FormalParameterList? ')' '{' FunctionBody '}'
|
// '(' FormalParameterList? ')' '{' FunctionBody '}'
|
||||||
|
|
||||||
@ -821,7 +810,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
|||||||
PreParserScope function_scope(scope_, FUNCTION_SCOPE);
|
PreParserScope function_scope(scope_, FUNCTION_SCOPE);
|
||||||
FunctionState function_state(&function_state_, &scope_, &function_scope, NULL,
|
FunctionState function_state(&function_state_, &scope_, &function_scope, NULL,
|
||||||
this->ast_value_factory());
|
this->ast_value_factory());
|
||||||
function_state.set_is_generator(is_generator);
|
function_state.set_is_generator(IsGeneratorFunction(kind));
|
||||||
// FormalParameterList ::
|
// FormalParameterList ::
|
||||||
// '(' (Identifier)*[','] ')'
|
// '(' (Identifier)*[','] ')'
|
||||||
Expect(Token::LPAREN, CHECK_OK);
|
Expect(Token::LPAREN, CHECK_OK);
|
||||||
@ -876,7 +865,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
|||||||
|
|
||||||
// Validate strict mode. We can do this only after parsing the function,
|
// Validate strict mode. We can do this only after parsing the function,
|
||||||
// since the function can declare itself strict.
|
// since the function can declare itself strict.
|
||||||
if (strict_mode() == STRICT) {
|
// Concise methods use StrictFormalParameters.
|
||||||
|
if (strict_mode() == STRICT || IsConciseMethod(kind)) {
|
||||||
if (function_name.IsEvalOrArguments()) {
|
if (function_name.IsEvalOrArguments()) {
|
||||||
ReportMessageAt(function_name_location, "strict_eval_arguments");
|
ReportMessageAt(function_name_location, "strict_eval_arguments");
|
||||||
*ok = false;
|
*ok = false;
|
||||||
|
196
src/preparser.h
196
src/preparser.h
@ -85,6 +85,7 @@ class ParserBase : public Traits {
|
|||||||
allow_natives_syntax_(false),
|
allow_natives_syntax_(false),
|
||||||
allow_generators_(false),
|
allow_generators_(false),
|
||||||
allow_arrow_functions_(false),
|
allow_arrow_functions_(false),
|
||||||
|
allow_harmony_object_literals_(false),
|
||||||
zone_(zone),
|
zone_(zone),
|
||||||
ast_node_id_gen_(ast_node_id_gen) {}
|
ast_node_id_gen_(ast_node_id_gen) {}
|
||||||
|
|
||||||
@ -100,6 +101,9 @@ class ParserBase : public Traits {
|
|||||||
return scanner()->HarmonyNumericLiterals();
|
return scanner()->HarmonyNumericLiterals();
|
||||||
}
|
}
|
||||||
bool allow_classes() const { return scanner()->HarmonyClasses(); }
|
bool allow_classes() const { return scanner()->HarmonyClasses(); }
|
||||||
|
bool allow_harmony_object_literals() const {
|
||||||
|
return allow_harmony_object_literals_;
|
||||||
|
}
|
||||||
|
|
||||||
// Setters that determine whether certain syntactical constructs are
|
// Setters that determine whether certain syntactical constructs are
|
||||||
// allowed to be parsed by this instance of the parser.
|
// allowed to be parsed by this instance of the parser.
|
||||||
@ -114,8 +118,9 @@ class ParserBase : public Traits {
|
|||||||
void set_allow_harmony_numeric_literals(bool allow) {
|
void set_allow_harmony_numeric_literals(bool allow) {
|
||||||
scanner()->SetHarmonyNumericLiterals(allow);
|
scanner()->SetHarmonyNumericLiterals(allow);
|
||||||
}
|
}
|
||||||
void set_allow_classes(bool allow) {
|
void set_allow_classes(bool allow) { scanner()->SetHarmonyClasses(allow); }
|
||||||
scanner()->SetHarmonyClasses(allow);
|
void set_allow_harmony_object_literals(bool allow) {
|
||||||
|
allow_harmony_object_literals_ = allow;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -481,6 +486,7 @@ class ParserBase : public Traits {
|
|||||||
ExpressionT ParseObjectLiteral(bool* ok);
|
ExpressionT ParseObjectLiteral(bool* ok);
|
||||||
ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker,
|
ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker,
|
||||||
bool* ok);
|
bool* ok);
|
||||||
|
IdentifierT ParsePropertyName(bool* is_getter, bool* is_setter, bool* ok);
|
||||||
typename Traits::Type::ExpressionList ParseArguments(bool* ok);
|
typename Traits::Type::ExpressionList ParseArguments(bool* ok);
|
||||||
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
|
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
|
||||||
ExpressionT ParseYieldExpression(bool* ok);
|
ExpressionT ParseYieldExpression(bool* ok);
|
||||||
@ -579,6 +585,7 @@ class ParserBase : public Traits {
|
|||||||
bool allow_natives_syntax_;
|
bool allow_natives_syntax_;
|
||||||
bool allow_generators_;
|
bool allow_generators_;
|
||||||
bool allow_arrow_functions_;
|
bool allow_arrow_functions_;
|
||||||
|
bool allow_harmony_object_literals_;
|
||||||
|
|
||||||
typename Traits::Type::Zone* zone_; // Only used by Parser.
|
typename Traits::Type::Zone* zone_; // Only used by Parser.
|
||||||
AstNode::IdGen* ast_node_id_gen_;
|
AstNode::IdGen* ast_node_id_gen_;
|
||||||
@ -1054,8 +1061,8 @@ class PreParserFactory {
|
|||||||
FunctionLiteral::ParameterFlag has_duplicate_parameters,
|
FunctionLiteral::ParameterFlag has_duplicate_parameters,
|
||||||
FunctionLiteral::FunctionType function_type,
|
FunctionLiteral::FunctionType function_type,
|
||||||
FunctionLiteral::IsFunctionFlag is_function,
|
FunctionLiteral::IsFunctionFlag is_function,
|
||||||
FunctionLiteral::IsParenthesizedFlag is_parenthesized,
|
FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind,
|
||||||
FunctionLiteral::KindFlag kind, int position) {
|
int position) {
|
||||||
return PreParserExpression::Default();
|
return PreParserExpression::Default();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1331,14 +1338,10 @@ class PreParserTraits {
|
|||||||
// Temporary glue; these functions will move to ParserBase.
|
// Temporary glue; these functions will move to ParserBase.
|
||||||
PreParserExpression ParseV8Intrinsic(bool* ok);
|
PreParserExpression ParseV8Intrinsic(bool* ok);
|
||||||
PreParserExpression ParseFunctionLiteral(
|
PreParserExpression ParseFunctionLiteral(
|
||||||
PreParserIdentifier name,
|
PreParserIdentifier name, Scanner::Location function_name_location,
|
||||||
Scanner::Location function_name_location,
|
bool name_is_strict_reserved, FunctionKind kind,
|
||||||
bool name_is_strict_reserved,
|
int function_token_position, FunctionLiteral::FunctionType type,
|
||||||
bool is_generator,
|
FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
|
||||||
int function_token_position,
|
|
||||||
FunctionLiteral::FunctionType type,
|
|
||||||
FunctionLiteral::ArityRestriction arity_restriction,
|
|
||||||
bool* ok);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PreParser* pre_parser_;
|
PreParser* pre_parser_;
|
||||||
@ -1469,14 +1472,10 @@ class PreParser : public ParserBase<PreParserTraits> {
|
|||||||
bool is_generator, bool* ok);
|
bool is_generator, bool* ok);
|
||||||
|
|
||||||
Expression ParseFunctionLiteral(
|
Expression ParseFunctionLiteral(
|
||||||
Identifier name,
|
Identifier name, Scanner::Location function_name_location,
|
||||||
Scanner::Location function_name_location,
|
bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
|
||||||
bool name_is_strict_reserved,
|
|
||||||
bool is_generator,
|
|
||||||
int function_token_pos,
|
|
||||||
FunctionLiteral::FunctionType function_type,
|
FunctionLiteral::FunctionType function_type,
|
||||||
FunctionLiteral::ArityRestriction arity_restriction,
|
FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
|
||||||
bool* ok);
|
|
||||||
void ParseLazyFunctionLiteralBody(bool* ok);
|
void ParseLazyFunctionLiteralBody(bool* ok);
|
||||||
|
|
||||||
bool CheckInOrOf(bool accept_OF);
|
bool CheckInOrOf(bool accept_OF);
|
||||||
@ -1851,85 +1850,86 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class Traits>
|
||||||
|
typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName(
|
||||||
|
bool* is_getter, bool* is_setter, bool* ok) {
|
||||||
|
Token::Value next = peek();
|
||||||
|
switch (next) {
|
||||||
|
case Token::STRING:
|
||||||
|
Consume(Token::STRING);
|
||||||
|
return this->GetSymbol(scanner_);
|
||||||
|
case Token::NUMBER:
|
||||||
|
Consume(Token::NUMBER);
|
||||||
|
return this->GetNumberAsSymbol(scanner_);
|
||||||
|
default:
|
||||||
|
return ParseIdentifierNameOrGetOrSet(is_getter, is_setter,
|
||||||
|
CHECK_OK_CUSTOM(EmptyIdentifier));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class Traits>
|
template <class Traits>
|
||||||
typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
|
typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
|
||||||
Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
|
Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
|
||||||
LiteralT key = this->EmptyLiteral();
|
// TODO(arv): Add support for concise generator methods.
|
||||||
Token::Value next = peek();
|
ExpressionT value = this->EmptyExpression();
|
||||||
|
bool is_getter = false;
|
||||||
|
bool is_setter = false;
|
||||||
|
Token::Value name_token = peek();
|
||||||
int next_pos = peek_position();
|
int next_pos = peek_position();
|
||||||
|
IdentifierT name = ParsePropertyName(
|
||||||
|
&is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
||||||
|
if (fni_ != NULL) this->PushLiteralName(fni_, name);
|
||||||
|
|
||||||
switch (next) {
|
if (peek() == Token::COLON) {
|
||||||
case Token::STRING: {
|
// PropertyDefinition : PropertyName ':' AssignmentExpression
|
||||||
Consume(Token::STRING);
|
checker->CheckProperty(name_token, kValueProperty,
|
||||||
IdentifierT string = this->GetSymbol(scanner_);
|
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
||||||
if (fni_ != NULL) this->PushLiteralName(fni_, string);
|
Consume(Token::COLON);
|
||||||
uint32_t index;
|
value = this->ParseAssignmentExpression(
|
||||||
if (this->IsArrayIndex(string, &index)) {
|
true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
||||||
key = factory()->NewNumberLiteral(index, next_pos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
key = factory()->NewStringLiteral(string, next_pos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Token::NUMBER: {
|
|
||||||
Consume(Token::NUMBER);
|
|
||||||
key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
|
|
||||||
factory());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
bool is_getter = false;
|
|
||||||
bool is_setter = false;
|
|
||||||
IdentifierT id = ParseIdentifierNameOrGetOrSet(
|
|
||||||
&is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
|
||||||
if (fni_ != NULL) this->PushLiteralName(fni_, id);
|
|
||||||
|
|
||||||
if ((is_getter || is_setter) && peek() != Token::COLON) {
|
} else if (allow_harmony_object_literals_ && peek() == Token::LPAREN) {
|
||||||
// Special handling of getter and setter syntax:
|
// Concise Method
|
||||||
// { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
|
checker->CheckProperty(name_token, kValueProperty,
|
||||||
// We have already read the "get" or "set" keyword.
|
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
||||||
IdentifierT name = this->EmptyIdentifier();
|
value = this->ParseFunctionLiteral(
|
||||||
switch (peek()) {
|
name, scanner()->location(),
|
||||||
case Token::STRING:
|
false, // reserved words are allowed here
|
||||||
Consume(Token::STRING);
|
FunctionKind::kConciseMethod, RelocInfo::kNoPosition,
|
||||||
name = this->GetSymbol(scanner_);
|
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::NORMAL_ARITY,
|
||||||
break;
|
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
||||||
case Token::NUMBER:
|
|
||||||
Consume(Token::NUMBER);
|
} else if (is_getter || is_setter) {
|
||||||
name = this->GetNumberAsSymbol(scanner_);
|
// Accessor
|
||||||
break;
|
bool dont_care = false;
|
||||||
default:
|
name_token = peek();
|
||||||
name = ParseIdentifierName(
|
name = ParsePropertyName(&dont_care, &dont_care,
|
||||||
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
||||||
}
|
// Validate the property.
|
||||||
// Validate the property.
|
checker->CheckProperty(name_token,
|
||||||
PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
|
is_getter ? kGetterProperty : kSetterProperty,
|
||||||
checker->CheckProperty(next, type,
|
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
||||||
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
|
||||||
typename Traits::Type::FunctionLiteral value =
|
name, scanner()->location(),
|
||||||
this->ParseFunctionLiteral(
|
false, // reserved words are allowed here
|
||||||
name, scanner()->location(),
|
FunctionKind::kNormalFunction, RelocInfo::kNoPosition,
|
||||||
false, // reserved words are allowed here
|
FunctionLiteral::ANONYMOUS_EXPRESSION,
|
||||||
false, // not a generator
|
is_getter ? FunctionLiteral::GETTER_ARITY
|
||||||
RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
|
: FunctionLiteral::SETTER_ARITY,
|
||||||
is_getter ? FunctionLiteral::GETTER_ARITY
|
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
||||||
: FunctionLiteral::SETTER_ARITY,
|
return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
|
||||||
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
} else {
|
||||||
return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
|
Token::Value next = Next();
|
||||||
}
|
ReportUnexpectedToken(next);
|
||||||
// Failed to parse as get/set property, so it's just a normal property
|
*ok = false;
|
||||||
// (which might be called "get" or "set" or something else).
|
return this->EmptyObjectLiteralProperty();
|
||||||
key = factory()->NewStringLiteral(id, next_pos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the property
|
uint32_t index;
|
||||||
checker->CheckProperty(next, kValueProperty,
|
LiteralT key = this->IsArrayIndex(name, &index)
|
||||||
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
? factory()->NewNumberLiteral(index, next_pos)
|
||||||
|
: factory()->NewStringLiteral(name, next_pos);
|
||||||
Expect(Token::COLON, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
|
||||||
ExpressionT value = this->ParseAssignmentExpression(
|
|
||||||
true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
|
|
||||||
|
|
||||||
return factory()->NewObjectLiteralProperty(key, value);
|
return factory()->NewObjectLiteralProperty(key, value);
|
||||||
}
|
}
|
||||||
@ -2428,14 +2428,12 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) {
|
|||||||
function_name_location = scanner()->location();
|
function_name_location = scanner()->location();
|
||||||
function_type = FunctionLiteral::NAMED_EXPRESSION;
|
function_type = FunctionLiteral::NAMED_EXPRESSION;
|
||||||
}
|
}
|
||||||
result = this->ParseFunctionLiteral(name,
|
result = this->ParseFunctionLiteral(
|
||||||
function_name_location,
|
name, function_name_location, is_strict_reserved_name,
|
||||||
is_strict_reserved_name,
|
is_generator ? FunctionKind::kGeneratorFunction
|
||||||
is_generator,
|
: FunctionKind::kNormalFunction,
|
||||||
function_token_position,
|
function_token_position, function_type, FunctionLiteral::NORMAL_ARITY,
|
||||||
function_type,
|
CHECK_OK);
|
||||||
FunctionLiteral::NORMAL_ARITY,
|
|
||||||
CHECK_OK);
|
|
||||||
} else if (peek() == Token::SUPER) {
|
} else if (peek() == Token::SUPER) {
|
||||||
int beg_pos = position();
|
int beg_pos = position();
|
||||||
Consume(Token::SUPER);
|
Consume(Token::SUPER);
|
||||||
@ -2596,7 +2594,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
|
|||||||
materialized_literal_count, expected_property_count, handler_count,
|
materialized_literal_count, expected_property_count, handler_count,
|
||||||
num_parameters, FunctionLiteral::kNoDuplicateParameters,
|
num_parameters, FunctionLiteral::kNoDuplicateParameters,
|
||||||
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction,
|
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction,
|
||||||
FunctionLiteral::kNotParenthesized, FunctionLiteral::kArrowFunction,
|
FunctionLiteral::kNotParenthesized, FunctionKind::kArrowFunction,
|
||||||
start_pos);
|
start_pos);
|
||||||
|
|
||||||
function_literal->set_function_token_position(start_pos);
|
function_literal->set_function_token_position(start_pos);
|
||||||
|
@ -2775,6 +2775,14 @@ RUNTIME_FUNCTION(Runtime_FunctionIsArrow) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(Runtime_FunctionIsConciseMethod) {
|
||||||
|
SealHandleScope shs(isolate);
|
||||||
|
DCHECK(args.length() == 1);
|
||||||
|
CONVERT_ARG_CHECKED(JSFunction, f, 0);
|
||||||
|
return isolate->heap()->ToBoolean(f->shared()->is_concise_method());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
|
RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
|
||||||
SealHandleScope shs(isolate);
|
SealHandleScope shs(isolate);
|
||||||
DCHECK(args.length() == 1);
|
DCHECK(args.length() == 1);
|
||||||
@ -8125,8 +8133,8 @@ RUNTIME_FUNCTION(Runtime_NewClosureFromStubFailure) {
|
|||||||
CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
|
CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
|
||||||
Handle<Context> context(isolate->context());
|
Handle<Context> context(isolate->context());
|
||||||
PretenureFlag pretenure_flag = NOT_TENURED;
|
PretenureFlag pretenure_flag = NOT_TENURED;
|
||||||
return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
|
return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
|
||||||
shared, context, pretenure_flag);
|
pretenure_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,6 +197,7 @@ namespace internal {
|
|||||||
F(FunctionMarkNameShouldPrintAsAnonymous, 1, 1) \
|
F(FunctionMarkNameShouldPrintAsAnonymous, 1, 1) \
|
||||||
F(FunctionIsGenerator, 1, 1) \
|
F(FunctionIsGenerator, 1, 1) \
|
||||||
F(FunctionIsArrow, 1, 1) \
|
F(FunctionIsArrow, 1, 1) \
|
||||||
|
F(FunctionIsConciseMethod, 1, 1) \
|
||||||
F(FunctionBindArguments, 4, 1) \
|
F(FunctionBindArguments, 4, 1) \
|
||||||
F(BoundFunctionGetBindings, 1, 1) \
|
F(BoundFunctionGetBindings, 1, 1) \
|
||||||
F(FunctionRemovePrototype, 1, 1) \
|
F(FunctionRemovePrototype, 1, 1) \
|
||||||
|
@ -1757,7 +1757,12 @@ function FunctionSourceString(func) {
|
|||||||
var name = %FunctionNameShouldPrintAsAnonymous(func)
|
var name = %FunctionNameShouldPrintAsAnonymous(func)
|
||||||
? 'anonymous'
|
? 'anonymous'
|
||||||
: %FunctionGetName(func);
|
: %FunctionGetName(func);
|
||||||
var head = %FunctionIsGenerator(func) ? 'function* ' : 'function ';
|
|
||||||
|
// TODO(arv): Handle concise generator methods.
|
||||||
|
|
||||||
|
var head = %FunctionIsConciseMethod(func)
|
||||||
|
? ''
|
||||||
|
: %FunctionIsGenerator(func) ? 'function* ' : 'function ';
|
||||||
return head + name + source;
|
return head + name + source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1288,9 +1288,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
|||||||
!pretenure &&
|
!pretenure &&
|
||||||
scope()->is_function_scope() &&
|
scope()->is_function_scope() &&
|
||||||
info->num_literals() == 0) {
|
info->num_literals() == 0) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
|
||||||
info->strict_mode(),
|
|
||||||
info->is_generator());
|
|
||||||
__ Move(rbx, info);
|
__ Move(rbx, info);
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5457,9 +5457,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|||||||
// space for nested functions that don't need literals cloning.
|
// space for nested functions that don't need literals cloning.
|
||||||
bool pretenure = instr->hydrogen()->pretenure();
|
bool pretenure = instr->hydrogen()->pretenure();
|
||||||
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
|
||||||
instr->hydrogen()->strict_mode(),
|
instr->hydrogen()->kind());
|
||||||
instr->hydrogen()->is_generator());
|
|
||||||
__ Move(rbx, instr->hydrogen()->shared_info());
|
__ Move(rbx, instr->hydrogen()->shared_info());
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1251,9 +1251,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
|||||||
!pretenure &&
|
!pretenure &&
|
||||||
scope()->is_function_scope() &&
|
scope()->is_function_scope() &&
|
||||||
info->num_literals() == 0) {
|
info->num_literals() == 0) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
|
||||||
info->strict_mode(),
|
|
||||||
info->is_generator());
|
|
||||||
__ mov(ebx, Immediate(info));
|
__ mov(ebx, Immediate(info));
|
||||||
__ CallStub(&stub);
|
__ CallStub(&stub);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5295,9 +5295,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|||||||
// space for nested functions that don't need literals cloning.
|
// space for nested functions that don't need literals cloning.
|
||||||
bool pretenure = instr->hydrogen()->pretenure();
|
bool pretenure = instr->hydrogen()->pretenure();
|
||||||
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
if (!pretenure && instr->hydrogen()->has_no_literals()) {
|
||||||
FastNewClosureStub stub(isolate(),
|
FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
|
||||||
instr->hydrogen()->strict_mode(),
|
instr->hydrogen()->kind());
|
||||||
instr->hydrogen()->is_generator());
|
|
||||||
__ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
|
__ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1217,7 +1217,8 @@ enum ParserFlag {
|
|||||||
kAllowGenerators,
|
kAllowGenerators,
|
||||||
kAllowHarmonyNumericLiterals,
|
kAllowHarmonyNumericLiterals,
|
||||||
kAllowArrowFunctions,
|
kAllowArrowFunctions,
|
||||||
kAllowClasses
|
kAllowClasses,
|
||||||
|
kAllowHarmonyObjectLiterals
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1237,6 +1238,8 @@ void SetParserFlags(i::ParserBase<Traits>* parser,
|
|||||||
parser->set_allow_generators(flags.Contains(kAllowGenerators));
|
parser->set_allow_generators(flags.Contains(kAllowGenerators));
|
||||||
parser->set_allow_harmony_numeric_literals(
|
parser->set_allow_harmony_numeric_literals(
|
||||||
flags.Contains(kAllowHarmonyNumericLiterals));
|
flags.Contains(kAllowHarmonyNumericLiterals));
|
||||||
|
parser->set_allow_harmony_object_literals(
|
||||||
|
flags.Contains(kAllowHarmonyObjectLiterals));
|
||||||
parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
|
parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
|
||||||
parser->set_allow_classes(flags.Contains(kAllowClasses));
|
parser->set_allow_classes(flags.Contains(kAllowClasses));
|
||||||
}
|
}
|
||||||
@ -1446,9 +1449,11 @@ TEST(ParserSync) {
|
|||||||
CcTest::i_isolate()->stack_guard()->SetStackLimit(
|
CcTest::i_isolate()->stack_guard()->SetStackLimit(
|
||||||
i::GetCurrentStackPosition() - 128 * 1024);
|
i::GetCurrentStackPosition() - 128 * 1024);
|
||||||
|
|
||||||
static const ParserFlag flags1[] = {kAllowLazy, kAllowHarmonyScoping,
|
static const ParserFlag flags1[] = {
|
||||||
kAllowModules, kAllowGenerators,
|
kAllowLazy, kAllowHarmonyScoping,
|
||||||
kAllowArrowFunctions};
|
kAllowModules, kAllowGenerators,
|
||||||
|
kAllowArrowFunctions, kAllowHarmonyNumericLiterals,
|
||||||
|
kAllowHarmonyObjectLiterals};
|
||||||
for (int i = 0; context_data[i][0] != NULL; ++i) {
|
for (int i = 0; context_data[i][0] != NULL; ++i) {
|
||||||
for (int j = 0; statement_data[j] != NULL; ++j) {
|
for (int j = 0; statement_data[j] != NULL; ++j) {
|
||||||
for (int k = 0; termination_data[k] != NULL; ++k) {
|
for (int k = 0; termination_data[k] != NULL; ++k) {
|
||||||
@ -1523,9 +1528,12 @@ void RunParserSyncTest(const char* context_data[][2],
|
|||||||
i::GetCurrentStackPosition() - 128 * 1024);
|
i::GetCurrentStackPosition() - 128 * 1024);
|
||||||
|
|
||||||
static const ParserFlag default_flags[] = {
|
static const ParserFlag default_flags[] = {
|
||||||
kAllowLazy, kAllowHarmonyScoping, kAllowModules,
|
kAllowArrowFunctions, kAllowClasses,
|
||||||
kAllowGenerators, kAllowNativesSyntax, kAllowArrowFunctions,
|
kAllowGenerators, kAllowHarmonyNumericLiterals,
|
||||||
kAllowClasses};
|
kAllowHarmonyObjectLiterals, kAllowHarmonyScoping,
|
||||||
|
kAllowLazy, kAllowModules,
|
||||||
|
kAllowNativesSyntax,
|
||||||
|
};
|
||||||
ParserFlag* generated_flags = NULL;
|
ParserFlag* generated_flags = NULL;
|
||||||
if (flags == NULL) {
|
if (flags == NULL) {
|
||||||
flags = default_flags;
|
flags = default_flags;
|
||||||
@ -2520,23 +2528,36 @@ TEST(ErrorsObjectLiteralChecking) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const char* statement_data[] = {
|
const char* statement_data[] = {
|
||||||
",", "foo: 1, get foo() {}", "foo: 1, set foo(v) {}",
|
",",
|
||||||
"\"foo\": 1, get \"foo\"() {}", "\"foo\": 1, set \"foo\"(v) {}",
|
"foo: 1, get foo() {}",
|
||||||
"1: 1, get 1() {}", "1: 1, set 1() {}",
|
"foo: 1, set foo(v) {}",
|
||||||
|
"\"foo\": 1, get \"foo\"() {}",
|
||||||
|
"\"foo\": 1, set \"foo\"(v) {}",
|
||||||
|
"1: 1, get 1() {}",
|
||||||
|
"1: 1, set 1() {}",
|
||||||
|
"get foo() {}, get foo() {}",
|
||||||
|
"set foo(_) {}, set foo(_) {}",
|
||||||
// It's counter-intuitive, but these collide too (even in classic
|
// It's counter-intuitive, but these collide too (even in classic
|
||||||
// mode). Note that we can have "foo" and foo as properties in classic
|
// mode). Note that we can have "foo" and foo as properties in classic
|
||||||
// mode,
|
// mode,
|
||||||
// but we cannot have "foo" and get foo, or foo and get "foo".
|
// but we cannot have "foo" and get foo, or foo and get "foo".
|
||||||
"foo: 1, get \"foo\"() {}", "foo: 1, set \"foo\"(v) {}",
|
"foo: 1, get \"foo\"() {}",
|
||||||
"\"foo\": 1, get foo() {}", "\"foo\": 1, set foo(v) {}",
|
"foo: 1, set \"foo\"(v) {}",
|
||||||
"1: 1, get \"1\"() {}", "1: 1, set \"1\"() {}",
|
"\"foo\": 1, get foo() {}",
|
||||||
|
"\"foo\": 1, set foo(v) {}",
|
||||||
|
"1: 1, get \"1\"() {}",
|
||||||
|
"1: 1, set \"1\"() {}",
|
||||||
"\"1\": 1, get 1() {}"
|
"\"1\": 1, get 1() {}"
|
||||||
"\"1\": 1, set 1(v) {}"
|
"\"1\": 1, set 1(v) {}"
|
||||||
// Wrong number of parameters
|
// Wrong number of parameters
|
||||||
"get bar(x) {}",
|
"get bar(x) {}",
|
||||||
"get bar(x, y) {}", "set bar() {}", "set bar(x, y) {}",
|
"get bar(x, y) {}",
|
||||||
|
"set bar() {}",
|
||||||
|
"set bar(x, y) {}",
|
||||||
// Parsing FunctionLiteral for getter or setter fails
|
// Parsing FunctionLiteral for getter or setter fails
|
||||||
"get foo( +", "get foo() \"error\"", NULL};
|
"get foo( +",
|
||||||
|
"get foo() \"error\"",
|
||||||
|
NULL};
|
||||||
|
|
||||||
RunParserSyncTest(context_data, statement_data, kError);
|
RunParserSyncTest(context_data, statement_data, kError);
|
||||||
}
|
}
|
||||||
@ -2573,6 +2594,8 @@ TEST(NoErrorsObjectLiteralChecking) {
|
|||||||
"\"foo\": 1, set \"bar\"(v) {}",
|
"\"foo\": 1, set \"bar\"(v) {}",
|
||||||
"1: 1, get 2() {}",
|
"1: 1, get 2() {}",
|
||||||
"1: 1, set 2(v) {}",
|
"1: 1, set 2(v) {}",
|
||||||
|
"get: 1, get foo() {}",
|
||||||
|
"set: 1, set foo(_) {}",
|
||||||
// Keywords, future reserved and strict future reserved are also allowed as
|
// Keywords, future reserved and strict future reserved are also allowed as
|
||||||
// property names.
|
// property names.
|
||||||
"if: 4",
|
"if: 4",
|
||||||
@ -3392,3 +3415,144 @@ TEST(ErrorsSuper) {
|
|||||||
RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
|
RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
|
||||||
always_flags, arraysize(always_flags));
|
always_flags, arraysize(always_flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(NoErrorsMethodDefinition) {
|
||||||
|
const char* context_data[][2] = {{"({", "});"},
|
||||||
|
{"'use strict'; ({", "});"},
|
||||||
|
{NULL, NULL}};
|
||||||
|
|
||||||
|
const char* object_literal_body_data[] = {
|
||||||
|
"m() {}",
|
||||||
|
"m(x) { return x; }",
|
||||||
|
"m(x, y) {}, n() {}",
|
||||||
|
"set(x, y) {}",
|
||||||
|
"get(x, y) {}",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
|
||||||
|
RunParserSyncTest(context_data, object_literal_body_data, kSuccess, NULL, 0,
|
||||||
|
always_flags, arraysize(always_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(MethodDefinitionNames) {
|
||||||
|
const char* context_data[][2] = {{"({", "(x, y) {}});"},
|
||||||
|
{"'use strict'; ({", "(x, y) {}});"},
|
||||||
|
{NULL, NULL}};
|
||||||
|
|
||||||
|
const char* name_data[] = {
|
||||||
|
"m",
|
||||||
|
"'m'",
|
||||||
|
"\"m\"",
|
||||||
|
"\"m n\"",
|
||||||
|
"true",
|
||||||
|
"false",
|
||||||
|
"null",
|
||||||
|
"0",
|
||||||
|
"1.2",
|
||||||
|
"1e1",
|
||||||
|
"1E1",
|
||||||
|
"1e+1",
|
||||||
|
"1e-1",
|
||||||
|
|
||||||
|
// Keywords
|
||||||
|
"async",
|
||||||
|
"await",
|
||||||
|
"break",
|
||||||
|
"case",
|
||||||
|
"catch",
|
||||||
|
"class",
|
||||||
|
"const",
|
||||||
|
"continue",
|
||||||
|
"debugger",
|
||||||
|
"default",
|
||||||
|
"delete",
|
||||||
|
"do",
|
||||||
|
"else",
|
||||||
|
"enum",
|
||||||
|
"export",
|
||||||
|
"extends",
|
||||||
|
"finally",
|
||||||
|
"for",
|
||||||
|
"function",
|
||||||
|
"if",
|
||||||
|
"implements",
|
||||||
|
"import",
|
||||||
|
"in",
|
||||||
|
"instanceof",
|
||||||
|
"interface",
|
||||||
|
"let",
|
||||||
|
"new",
|
||||||
|
"package",
|
||||||
|
"private",
|
||||||
|
"protected",
|
||||||
|
"public",
|
||||||
|
"return",
|
||||||
|
"static",
|
||||||
|
"super",
|
||||||
|
"switch",
|
||||||
|
"this",
|
||||||
|
"throw",
|
||||||
|
"try",
|
||||||
|
"typeof",
|
||||||
|
"var",
|
||||||
|
"void",
|
||||||
|
"while",
|
||||||
|
"with",
|
||||||
|
"yield",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
|
||||||
|
RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
|
||||||
|
always_flags, arraysize(always_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(MethodDefinitionStrictFormalParamereters) {
|
||||||
|
const char* context_data[][2] = {{"({method(", "){}});"},
|
||||||
|
{"'use strict'; ({method(", "){}});"},
|
||||||
|
{NULL, NULL}};
|
||||||
|
|
||||||
|
const char* params_data[] = {
|
||||||
|
"x, x",
|
||||||
|
"x, y, x",
|
||||||
|
"eval",
|
||||||
|
"arguments",
|
||||||
|
"var",
|
||||||
|
"const",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
|
||||||
|
RunParserSyncTest(context_data, params_data, kError, NULL, 0,
|
||||||
|
always_flags, arraysize(always_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(MethodDefinitionDuplicateProperty) {
|
||||||
|
// Duplicate properties are allowed in ES6 but we haven't removed that check
|
||||||
|
// yet.
|
||||||
|
const char* context_data[][2] = {{"'use strict'; ({", "});"},
|
||||||
|
{NULL, NULL}};
|
||||||
|
|
||||||
|
const char* params_data[] = {
|
||||||
|
"x: 1, x() {}",
|
||||||
|
"x() {}, x: 1",
|
||||||
|
"x() {}, get x() {}",
|
||||||
|
"x() {}, set x(_) {}",
|
||||||
|
"x() {}, x() {}",
|
||||||
|
"x() {}, y() {}, x() {}",
|
||||||
|
"x() {}, \"x\"() {}",
|
||||||
|
"x() {}, 'x'() {}",
|
||||||
|
"0() {}, '0'() {}",
|
||||||
|
"1.0() {}, 1: 1",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
|
||||||
|
RunParserSyncTest(context_data, params_data, kError, NULL, 0,
|
||||||
|
always_flags, arraysize(always_flags));
|
||||||
|
}
|
||||||
|
123
test/mjsunit/harmony/object-literals-method.js
Normal file
123
test/mjsunit/harmony/object-literals-method.js
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// Copyright 2014 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: --harmony-object-literals --allow-natives-syntax
|
||||||
|
|
||||||
|
|
||||||
|
(function TestDescriptor() {
|
||||||
|
var object = {
|
||||||
|
method() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assertEquals(42, object.method());
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
(function TestDescriptor() {
|
||||||
|
var object = {
|
||||||
|
method() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(object, 'method');
|
||||||
|
assertTrue(desc.enumerable);
|
||||||
|
assertTrue(desc.configurable);
|
||||||
|
assertTrue(desc.writable);
|
||||||
|
assertEquals('function', typeof desc.value);
|
||||||
|
|
||||||
|
assertEquals(42, desc.value());
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
(function TestProto() {
|
||||||
|
var object = {
|
||||||
|
method() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
assertEquals(Function.prototype, Object.getPrototypeOf(object.method));
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
(function TestNotConstructable() {
|
||||||
|
var object = {
|
||||||
|
method() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
assertThrows(function() {
|
||||||
|
new object.method;
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
(function TestFunctionName() {
|
||||||
|
var object = {
|
||||||
|
method() {
|
||||||
|
return 42;
|
||||||
|
},
|
||||||
|
1() {},
|
||||||
|
2.0() {}
|
||||||
|
};
|
||||||
|
var f = object.method;
|
||||||
|
assertEquals('method', f.name);
|
||||||
|
var g = object[1];
|
||||||
|
assertEquals('1', g.name);
|
||||||
|
|
||||||
|
var h = object[2];
|
||||||
|
assertEquals('2', h.name);
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
(function TestNoBinding() {
|
||||||
|
var method = 'local';
|
||||||
|
var calls = 0;
|
||||||
|
var object = {
|
||||||
|
method() {
|
||||||
|
calls++;
|
||||||
|
assertEquals('local', method);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
object.method();
|
||||||
|
assertEquals(1, calls);
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
(function TestNoPrototype() {
|
||||||
|
var object = {
|
||||||
|
method() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var f = object.method;
|
||||||
|
assertFalse(f.hasOwnProperty('prototype'));
|
||||||
|
assertEquals(undefined, f.prototype);
|
||||||
|
|
||||||
|
f.prototype = 42;
|
||||||
|
assertEquals(42, f.prototype);
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
(function TestToString() {
|
||||||
|
var object = {
|
||||||
|
method() { 42; }
|
||||||
|
};
|
||||||
|
assertEquals('method() { 42; }', object.method.toString());
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
(function TestOptimized() {
|
||||||
|
var object = {
|
||||||
|
method() { return 42; }
|
||||||
|
};
|
||||||
|
assertEquals(42, object.method());
|
||||||
|
assertEquals(42, object.method());
|
||||||
|
%OptimizeFunctionOnNextCall(object.method);
|
||||||
|
assertEquals(42, object.method());
|
||||||
|
assertFalse(object.method.hasOwnProperty('prototype'));
|
||||||
|
})();
|
5
test/mjsunit/runtime-gen/functionisconcisemethod.js
Normal file
5
test/mjsunit/runtime-gen/functionisconcisemethod.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||||
|
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
|
||||||
|
// Flags: --allow-natives-syntax --harmony --harmony-proxies
|
||||||
|
var _f = function() {};
|
||||||
|
%FunctionIsConciseMethod(_f);
|
Loading…
Reference in New Issue
Block a user