!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(isolate(),
- info->strict_mode(),
- info->is_generator());
+ FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
__ mov(r2, Operand(info));
__ CallStub(&stub);
} else {
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(isolate(),
- instr->hydrogen()->strict_mode(),
- instr->hydrogen()->is_generator());
+ FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+ instr->hydrogen()->kind());
__ mov(r2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else {
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(isolate(),
- info->strict_mode(),
- info->is_generator());
+ FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
__ Mov(x2, Operand(info));
__ CallStub(&stub);
} else {
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(isolate(),
- instr->hydrogen()->strict_mode(),
- instr->hydrogen()->is_generator());
+ FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+ instr->hydrogen()->kind());
__ Mov(x2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else {
kNotParenthesized
};
- enum KindFlag {
- kNormalFunction,
- kArrowFunction,
- kGeneratorFunction
- };
-
enum ArityRestriction {
NORMAL_ARITY,
GETTER_ARITY,
bitfield_ = IsParenthesized::update(bitfield_, kIsParenthesized);
}
- bool is_generator() { return IsGenerator::decode(bitfield_); }
- bool is_arrow() { return IsArrow::decode(bitfield_); }
+ FunctionKind kind() { return FunctionKindBits::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(); }
AstProperties::Flags* flags() { return ast_properties_.flags(); }
int parameter_count, FunctionType function_type,
ParameterFlag has_duplicate_parameters,
IsFunctionFlag is_function,
- IsParenthesizedFlag is_parenthesized, KindFlag kind,
+ IsParenthesizedFlag is_parenthesized, FunctionKind kind,
int position, IdGen* id_gen)
: Expression(zone, position, id_gen),
raw_name_(name),
HasDuplicateParameters::encode(has_duplicate_parameters) |
IsFunction::encode(is_function) |
IsParenthesized::encode(is_parenthesized) |
- IsGenerator::encode(kind == kGeneratorFunction) |
- IsArrow::encode(kind == kArrowFunction);
+ FunctionKindBits::encode(kind);
+ DCHECK(IsValidFunctionKind(kind));
}
private:
int function_token_position_;
unsigned bitfield_;
- class IsExpression: public BitField<bool, 0, 1> {};
- class IsAnonymous: public BitField<bool, 1, 1> {};
- class Pretenure: public BitField<bool, 2, 1> {};
- class HasDuplicateParameters: public BitField<ParameterFlag, 3, 1> {};
- class IsFunction: public BitField<IsFunctionFlag, 4, 1> {};
- class IsParenthesized: public BitField<IsParenthesizedFlag, 5, 1> {};
- class IsGenerator : public BitField<bool, 6, 1> {};
- class IsArrow : public BitField<bool, 7, 1> {};
+ class IsExpression : public BitField<bool, 0, 1> {};
+ class IsAnonymous : public BitField<bool, 1, 1> {};
+ class Pretenure : public BitField<bool, 2, 1> {};
+ 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, 3> {};
};
FunctionLiteral::ParameterFlag has_duplicate_parameters,
FunctionLiteral::FunctionType function_type,
FunctionLiteral::IsFunctionFlag is_function,
- FunctionLiteral::IsParenthesizedFlag is_parenthesized,
- FunctionLiteral::KindFlag kind, int position) {
+ FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind,
+ int position) {
FunctionLiteral* lit = new (zone_) FunctionLiteral(
zone_, name, ast_value_factory, scope, body, materialized_literal_count,
expected_property_count, handler_count, parameter_count, function_type,
NOT_TENURED, JS_FUNCTION_TYPE);
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
// as the map of the allocated object.
class FastNewClosureStub : public HydrogenCodeStub {
public:
FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
- bool is_generator)
+ FunctionKind kind)
: HydrogenCodeStub(isolate) {
+ DCHECK(IsValidFunctionKind(kind));
set_sub_minor_key(StrictModeBits::encode(strict_mode) |
- IsGeneratorBits::encode(is_generator));
+ FunctionKindBits::encode(kind));
}
StrictMode strict_mode() const {
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:
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_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
function_info->set_is_function(lit->is_function());
function_info->set_bailout_reason(lit->dont_optimize_reason());
function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
- function_info->set_is_generator(lit->is_generator());
- function_info->set_is_arrow(lit->is_arrow());
+ function_info->set_kind(lit->kind());
}
// Allocate function.
DCHECK(!info->code().is_null());
result = isolate->factory()->NewSharedFunctionInfo(
- lit->name(), lit->materialized_literal_count(), lit->is_generator(),
- lit->is_arrow(), info->code(),
- ScopeInfo::Create(info->scope(), info->zone()),
+ lit->name(), lit->materialized_literal_count(), lit->kind(),
+ info->code(), ScopeInfo::Create(info->scope(), info->zone()),
info->feedback_vector());
DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
// Create a shared function info object.
Handle<SharedFunctionInfo> result = factory->NewSharedFunctionInfo(
- literal->name(), literal->materialized_literal_count(),
- literal->is_generator(), literal->is_arrow(), info.code(), scope_info,
- info.feedback_vector());
+ literal->name(), literal->materialized_literal_count(), literal->kind(),
+ info.code(), scope_info, info.feedback_vector());
SetFunctionInfo(result, literal, false, script);
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
result->set_allows_lazy_compilation(allow_lazy);
return kHeaderSize + index * kPointerSize - kHeapObjectTag;
}
- static int FunctionMapIndex(StrictMode strict_mode, bool is_generator) {
- return is_generator
- ? (strict_mode == SLOPPY
- ? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
- : STRICT_GENERATOR_FUNCTION_MAP_INDEX)
- : (strict_mode == SLOPPY
- ? SLOPPY_FUNCTION_MAP_INDEX
- : STRICT_FUNCTION_MAP_INDEX);
+ static int FunctionMapIndex(StrictMode strict_mode, FunctionKind kind) {
+ if (IsGeneratorFunction(kind)) {
+ return strict_mode == SLOPPY ? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
+ : STRICT_GENERATOR_FUNCTION_MAP_INDEX;
+ }
+
+ if (IsConciseMethod(kind)) {
+ 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;
function->set_prototype_or_initial_map(*the_hole_value());
function->set_literals_or_bindings(*empty_fixed_array());
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();
}
Handle<SharedFunctionInfo> info,
Handle<Context> context,
PretenureFlag pretenure) {
- int map_index = Context::FunctionMapIndex(info->strict_mode(),
- info->is_generator());
+ int map_index = Context::FunctionMapIndex(info->strict_mode(), info->kind());
Handle<Map> map(Map::cast(context->native_context()->get(map_index)));
Handle<JSFunction> result = NewFunction(map, info, context, pretenure);
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
- Handle<String> name, int number_of_literals, bool is_generator,
- bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info,
+ Handle<String> name, int number_of_literals, FunctionKind kind,
+ Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<FixedArray> feedback_vector) {
+ DCHECK(IsValidFunctionKind(kind));
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name, code);
shared->set_scope_info(*scope_info);
shared->set_feedback_vector(*feedback_vector);
- shared->set_is_arrow(is_arrow);
+ shared->set_kind(kind);
int literals_array_size = number_of_literals;
// If the function contains object, regexp or array literals,
// allocate extra space for a literals array prefix containing the
literals_array_size += JSFunction::kLiteralsPrefixSize;
}
shared->set_num_literals(literals_array_size);
- if (is_generator) {
+ if (IsGeneratorFunction(kind)) {
shared->set_instance_class_name(isolate()->heap()->Generator_string());
shared->DisableOptimization(kGenerator);
}
// Allocates a new SharedFunctionInfo object.
Handle<SharedFunctionInfo> NewSharedFunctionInfo(
- Handle<String> name, int number_of_literals, bool is_generator,
- bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info,
+ Handle<String> name, int number_of_literals, FunctionKind kind,
+ Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<FixedArray> feedback_vector);
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name,
MaybeHandle<Code> code);
DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays")
DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions")
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_IMPLICATION(harmony, harmony_scoping)
DEFINE_IMPLICATION(harmony, harmony_arrays)
DEFINE_IMPLICATION(harmony, harmony_arrow_functions)
DEFINE_IMPLICATION(harmony, harmony_classes)
+DEFINE_IMPLICATION(harmony, harmony_object_literals)
DEFINE_IMPLICATION(harmony_modules, harmony_scoping)
DEFINE_IMPLICATION(harmony, es_staging)
const int literals = fun->NumberOfLiterals();
Handle<Code> code = Handle<Code>(fun->shared()->code());
Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
- bool is_generator = false;
- bool is_arrow = false;
Handle<SharedFunctionInfo> shared =
isolate()->factory()->NewSharedFunctionInfo(
- name, literals, is_generator, is_arrow, code,
+ name, literals, FunctionKind::kNormalFunction, code,
Handle<ScopeInfo>(fun->shared()->scope_info()),
Handle<FixedArray>(fun->shared()->feedback_vector()));
shared->set_construct_stub(*construct_stub);
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 i = v8::internal;
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
bool pretenure() const { return pretenure_; }
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_; }
private:
- HFunctionLiteral(HValue* context,
- Handle<SharedFunctionInfo> shared,
+ HFunctionLiteral(HValue* context, Handle<SharedFunctionInfo> shared,
bool pretenure)
: HTemplateInstruction<1>(HType::JSObject()),
shared_info_(shared),
+ kind_(shared->kind()),
pretenure_(pretenure),
has_no_literals_(shared->num_literals() == 0),
- is_generator_(shared->is_generator()),
strict_mode_(shared->strict_mode()) {
SetOperandAt(0, context);
set_representation(Representation::Tagged());
virtual bool IsDeletable() const OVERRIDE { return true; }
Handle<SharedFunctionInfo> shared_info_;
+ FunctionKind kind_;
bool pretenure_ : 1;
bool has_no_literals_ : 1;
- bool is_generator_ : 1;
StrictMode strict_mode_;
};
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(isolate(),
- info->strict_mode(),
- info->is_generator());
+ FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
__ mov(ebx, Immediate(info));
__ CallStub(&stub);
} else {
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(isolate(),
- instr->hydrogen()->strict_mode(),
- instr->hydrogen()->is_generator());
+ FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+ instr->hydrogen()->kind());
__ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else {
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(isolate(),
- info->strict_mode(),
- info->is_generator());
+ FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
__ li(a2, Operand(info));
__ CallStub(&stub);
} else {
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(isolate(),
- instr->hydrogen()->strict_mode(),
- instr->hydrogen()->is_generator());
+ FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+ instr->hydrogen()->kind());
__ li(a2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else {
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(isolate(),
- info->strict_mode(),
- info->is_generator());
+ FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
__ li(a2, Operand(info));
__ CallStub(&stub);
} else {
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(isolate(),
- instr->hydrogen()->strict_mode(),
- instr->hydrogen()->is_generator());
+ FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+ instr->hydrogen()->kind());
__ li(a2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else {
}
+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, inline_builtin,
kInlineBuiltin)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
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_generator, kIsGenerator)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
+ kIsConciseMethod)
ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
// Indicates that this function is an arrow function.
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
// deoptimization.
inline bool has_deoptimization_support();
kIsFunction,
kDontCache,
kDontFlush,
- kIsGenerator,
kIsArrow,
+ kIsGenerator,
+ kIsConciseMethod,
kCompilerHintsCount // Pseudo entry
};
- class DeoptCountBits: public BitField<int, 0, 4> {};
- class OptReenableTriesBits: public BitField<int, 4, 18> {};
- class ICAgeBits: public BitField<int, 22, 8> {};
+ class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 3> {};
+
+ class DeoptCountBits : public BitField<int, 0, 4> {};
+ 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> {};
+ class OptCountBits : public BitField<int, 0, 22> {};
+ class DisabledOptimizationReasonBits : public BitField<int, 22, 8> {};
private:
#if V8_HOST_ARCH_32_BIT
FunctionLiteral* ParserTraits::ParseFunctionLiteral(
- const AstRawString* name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_position,
- FunctionLiteral::FunctionType type,
- FunctionLiteral::ArityRestriction arity_restriction,
- bool* ok) {
- return parser_->ParseFunctionLiteral(name, function_name_location,
- name_is_strict_reserved, is_generator,
- function_token_position, type,
- arity_restriction, ok);
+ const AstRawString* name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind,
+ int function_token_position, FunctionLiteral::FunctionType type,
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
+ return parser_->ParseFunctionLiteral(
+ name, function_name_location, name_is_strict_reserved, kind,
+ function_token_position, type, arity_restriction, ok);
}
set_allow_arrow_functions(FLAG_harmony_arrow_functions);
set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
set_allow_classes(FLAG_harmony_classes);
+ set_allow_harmony_object_literals(FLAG_harmony_object_literals);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
use_counts_[feature] = 0;
function_state.handler_count(), 0,
FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
- FunctionLiteral::kNotParenthesized, FunctionLiteral::kNormalFunction,
- 0);
+ FunctionLiteral::kNotParenthesized, FunctionKind::kNormalFunction, 0);
result->set_ast_properties(factory()->visitor()->ast_properties());
result->set_dont_optimize_reason(
factory()->visitor()->dont_optimize_reason());
? FunctionLiteral::ANONYMOUS_EXPRESSION
: FunctionLiteral::NAMED_EXPRESSION)
: FunctionLiteral::DECLARATION;
- bool is_generator = shared_info->is_generator();
bool ok = true;
if (shared_info->is_arrow()) {
- DCHECK(!is_generator);
Expression* expression = ParseExpression(false, &ok);
DCHECK(expression->IsFunctionLiteral());
result = expression->AsFunctionLiteral();
} else {
result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
false, // Strict mode name already checked.
- is_generator, RelocInfo::kNoPosition,
+ shared_info->kind(), RelocInfo::kNoPosition,
function_type,
FunctionLiteral::NORMAL_ARITY, &ok);
}
bool is_strict_reserved = false;
const AstRawString* name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
- FunctionLiteral* fun = ParseFunctionLiteral(name,
- scanner()->location(),
- is_strict_reserved,
- is_generator,
- pos,
- FunctionLiteral::DECLARATION,
- FunctionLiteral::NORMAL_ARITY,
- CHECK_OK);
+ FunctionLiteral* fun =
+ ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
+ is_generator ? FunctionKind::kGeneratorFunction
+ : FunctionKind::kNormalFunction,
+ pos, FunctionLiteral::DECLARATION,
+ FunctionLiteral::NORMAL_ARITY, CHECK_OK);
// 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
// initial value upon entering the corresponding scope.
FunctionLiteral* Parser::ParseFunctionLiteral(
- const AstRawString* function_name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_pos,
+ const AstRawString* function_name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
FunctionLiteral::FunctionType function_type,
- FunctionLiteral::ArityRestriction arity_restriction,
- bool* ok) {
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
// Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}'
//
int pos = function_token_pos == RelocInfo::kNoPosition
? peek_position() : function_token_pos;
+ bool is_generator = IsGeneratorFunction(kind);
+
// 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 to decide whether to invoke function name inference.
}
// Validate strict mode.
- if (strict_mode() == STRICT) {
+ // Concise methods use StrictFormalParameters.
+ if (strict_mode() == STRICT || IsConciseMethod(kind)) {
CheckStrictFunctionNameAndParameters(function_name,
name_is_strict_reserved,
function_name_location,
dupe_error_loc,
reserved_loc,
CHECK_OK);
+ }
+ if (strict_mode() == STRICT) {
CheckOctalLiteral(scope->start_position(),
scope->end_position(),
CHECK_OK);
}
}
- FunctionLiteral::KindFlag kind = is_generator
- ? FunctionLiteral::kGeneratorFunction
- : FunctionLiteral::kNormalFunction;
FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
function_name, ast_value_factory_, scope, body,
materialized_literal_count, expected_property_count, handler_count,
reusable_preparser_->set_allow_harmony_numeric_literals(
allow_harmony_numeric_literals());
reusable_preparser_->set_allow_classes(allow_classes());
+ reusable_preparser_->set_allow_harmony_object_literals(
+ allow_harmony_object_literals());
}
PreParser::PreParseResult result =
reusable_preparser_->PreParseLazyFunction(strict_mode(),
// Temporary glue; these functions will move to ParserBase.
Expression* ParseV8Intrinsic(bool* ok);
FunctionLiteral* ParseFunctionLiteral(
- const AstRawString* name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_position,
- FunctionLiteral::FunctionType type,
- FunctionLiteral::ArityRestriction arity_restriction,
- bool* ok);
+ const AstRawString* name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind,
+ int function_token_position, FunctionLiteral::FunctionType type,
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
V8_INLINE void SkipLazyFunctionBody(const AstRawString* name,
int* materialized_literal_count,
int* expected_property_count, bool* ok);
Statement* body, bool* ok);
FunctionLiteral* ParseFunctionLiteral(
- const AstRawString* name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_position,
- FunctionLiteral::FunctionType type,
- FunctionLiteral::ArityRestriction arity_restriction,
- bool* ok);
+ const AstRawString* name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind,
+ int function_token_position, FunctionLiteral::FunctionType type,
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
// Magical syntax support.
Expression* ParseV8Intrinsic(bool* ok);
PreParserExpression PreParserTraits::ParseFunctionLiteral(
- PreParserIdentifier name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_position,
- FunctionLiteral::FunctionType type,
- FunctionLiteral::ArityRestriction arity_restriction,
- bool* ok) {
+ PreParserIdentifier name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind,
+ int function_token_position, FunctionLiteral::FunctionType type,
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
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);
}
bool is_strict_reserved = false;
Identifier name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
- ParseFunctionLiteral(name,
- scanner()->location(),
- is_strict_reserved,
- is_generator,
- pos,
- FunctionLiteral::DECLARATION,
- FunctionLiteral::NORMAL_ARITY,
- CHECK_OK);
+ ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
+ is_generator ? FunctionKind::kGeneratorFunction
+ : FunctionKind::kNormalFunction,
+ pos, FunctionLiteral::DECLARATION,
+ FunctionLiteral::NORMAL_ARITY, CHECK_OK);
return Statement::FunctionDeclaration();
}
PreParser::Expression PreParser::ParseFunctionLiteral(
- Identifier function_name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_pos,
+ Identifier function_name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
FunctionLiteral::FunctionType function_type,
- FunctionLiteral::ArityRestriction arity_restriction,
- bool* ok) {
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
// Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}'
PreParserScope function_scope(scope_, FUNCTION_SCOPE);
FunctionState function_state(&function_state_, &scope_, &function_scope, NULL,
this->ast_value_factory());
- function_state.set_is_generator(is_generator);
+ function_state.set_is_generator(IsGeneratorFunction(kind));
// FormalParameterList ::
// '(' (Identifier)*[','] ')'
Expect(Token::LPAREN, CHECK_OK);
// Validate strict mode. We can do this only after parsing the function,
// 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()) {
ReportMessageAt(function_name_location, "strict_eval_arguments");
*ok = false;
allow_natives_syntax_(false),
allow_generators_(false),
allow_arrow_functions_(false),
+ allow_harmony_object_literals_(false),
zone_(zone),
ast_node_id_gen_(ast_node_id_gen) {}
return scanner()->HarmonyNumericLiterals();
}
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
// allowed to be parsed by this instance of the parser.
void set_allow_harmony_numeric_literals(bool allow) {
scanner()->SetHarmonyNumericLiterals(allow);
}
- void set_allow_classes(bool allow) {
- scanner()->SetHarmonyClasses(allow);
+ void set_allow_classes(bool allow) { scanner()->SetHarmonyClasses(allow); }
+ void set_allow_harmony_object_literals(bool allow) {
+ allow_harmony_object_literals_ = allow;
}
protected:
ExpressionT ParseObjectLiteral(bool* ok);
ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker,
bool* ok);
+ IdentifierT ParsePropertyName(bool* is_getter, bool* is_setter, bool* ok);
typename Traits::Type::ExpressionList ParseArguments(bool* ok);
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool* ok);
bool allow_natives_syntax_;
bool allow_generators_;
bool allow_arrow_functions_;
+ bool allow_harmony_object_literals_;
typename Traits::Type::Zone* zone_; // Only used by Parser.
AstNode::IdGen* ast_node_id_gen_;
FunctionLiteral::ParameterFlag has_duplicate_parameters,
FunctionLiteral::FunctionType function_type,
FunctionLiteral::IsFunctionFlag is_function,
- FunctionLiteral::IsParenthesizedFlag is_parenthesized,
- FunctionLiteral::KindFlag kind, int position) {
+ FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind,
+ int position) {
return PreParserExpression::Default();
}
// Temporary glue; these functions will move to ParserBase.
PreParserExpression ParseV8Intrinsic(bool* ok);
PreParserExpression ParseFunctionLiteral(
- PreParserIdentifier name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_position,
- FunctionLiteral::FunctionType type,
- FunctionLiteral::ArityRestriction arity_restriction,
- bool* ok);
+ PreParserIdentifier name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind,
+ int function_token_position, FunctionLiteral::FunctionType type,
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
private:
PreParser* pre_parser_;
bool is_generator, bool* ok);
Expression ParseFunctionLiteral(
- Identifier name,
- Scanner::Location function_name_location,
- bool name_is_strict_reserved,
- bool is_generator,
- int function_token_pos,
+ Identifier name, Scanner::Location function_name_location,
+ bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
FunctionLiteral::FunctionType function_type,
- FunctionLiteral::ArityRestriction arity_restriction,
- bool* ok);
+ FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
void ParseLazyFunctionLiteralBody(bool* ok);
bool CheckInOrOf(bool accept_OF);
template <class Traits>
-typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
- Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
- LiteralT key = this->EmptyLiteral();
+typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName(
+ bool* is_getter, bool* is_setter, bool* ok) {
Token::Value next = peek();
- int next_pos = peek_position();
-
switch (next) {
- case Token::STRING: {
+ case Token::STRING:
Consume(Token::STRING);
- IdentifierT string = this->GetSymbol(scanner_);
- if (fni_ != NULL) this->PushLiteralName(fni_, string);
- uint32_t index;
- if (this->IsArrayIndex(string, &index)) {
- key = factory()->NewNumberLiteral(index, next_pos);
- break;
- }
- key = factory()->NewStringLiteral(string, next_pos);
- break;
- }
- case Token::NUMBER: {
+ return this->GetSymbol(scanner_);
+ 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) {
- // Special handling of getter and setter syntax:
- // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
- // We have already read the "get" or "set" keyword.
- IdentifierT name = this->EmptyIdentifier();
- switch (peek()) {
- case Token::STRING:
- Consume(Token::STRING);
- name = this->GetSymbol(scanner_);
- break;
- case Token::NUMBER:
- Consume(Token::NUMBER);
- name = this->GetNumberAsSymbol(scanner_);
- break;
- default:
- name = ParseIdentifierName(
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- }
- // Validate the property.
- PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
- checker->CheckProperty(next, type,
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- typename Traits::Type::FunctionLiteral value =
- this->ParseFunctionLiteral(
- name, scanner()->location(),
- false, // reserved words are allowed here
- false, // not a generator
- RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
- is_getter ? FunctionLiteral::GETTER_ARITY
- : FunctionLiteral::SETTER_ARITY,
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
- }
- // Failed to parse as get/set property, so it's just a normal property
- // (which might be called "get" or "set" or something else).
- key = factory()->NewStringLiteral(id, next_pos);
- }
+ return this->GetNumberAsSymbol(scanner_);
+ default:
+ return ParseIdentifierNameOrGetOrSet(is_getter, is_setter,
+ CHECK_OK_CUSTOM(EmptyIdentifier));
}
+}
+
- // Validate the property
- checker->CheckProperty(next, kValueProperty,
- CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+template <class Traits>
+typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
+ Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
+ // TODO(arv): Add support for concise generator methods.
+ ExpressionT value = this->EmptyExpression();
+ bool is_getter = false;
+ bool is_setter = false;
+ Token::Value name_token = peek();
+ int next_pos = peek_position();
+ IdentifierT name = ParsePropertyName(
+ &is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ if (fni_ != NULL) this->PushLiteralName(fni_, name);
+
+ if (peek() == Token::COLON) {
+ // PropertyDefinition : PropertyName ':' AssignmentExpression
+ checker->CheckProperty(name_token, kValueProperty,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ Consume(Token::COLON);
+ value = this->ParseAssignmentExpression(
+ true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+ } else if (allow_harmony_object_literals_ && peek() == Token::LPAREN) {
+ // Concise Method
+ checker->CheckProperty(name_token, kValueProperty,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ value = this->ParseFunctionLiteral(
+ name, scanner()->location(),
+ false, // reserved words are allowed here
+ FunctionKind::kConciseMethod, RelocInfo::kNoPosition,
+ FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::NORMAL_ARITY,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
+ } else if (is_getter || is_setter) {
+ // Accessor
+ bool dont_care = false;
+ name_token = peek();
+ name = ParsePropertyName(&dont_care, &dont_care,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ // Validate the property.
+ checker->CheckProperty(name_token,
+ is_getter ? kGetterProperty : kSetterProperty,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
+ name, scanner()->location(),
+ false, // reserved words are allowed here
+ FunctionKind::kNormalFunction, RelocInfo::kNoPosition,
+ FunctionLiteral::ANONYMOUS_EXPRESSION,
+ is_getter ? FunctionLiteral::GETTER_ARITY
+ : FunctionLiteral::SETTER_ARITY,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
+ } else {
+ Token::Value next = Next();
+ ReportUnexpectedToken(next);
+ *ok = false;
+ return this->EmptyObjectLiteralProperty();
+ }
- Expect(Token::COLON, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- ExpressionT value = this->ParseAssignmentExpression(
- true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ uint32_t index;
+ LiteralT key = this->IsArrayIndex(name, &index)
+ ? factory()->NewNumberLiteral(index, next_pos)
+ : factory()->NewStringLiteral(name, next_pos);
return factory()->NewObjectLiteralProperty(key, value);
}
function_name_location = scanner()->location();
function_type = FunctionLiteral::NAMED_EXPRESSION;
}
- result = this->ParseFunctionLiteral(name,
- function_name_location,
- is_strict_reserved_name,
- is_generator,
- function_token_position,
- function_type,
- FunctionLiteral::NORMAL_ARITY,
- CHECK_OK);
+ result = this->ParseFunctionLiteral(
+ name, function_name_location, is_strict_reserved_name,
+ is_generator ? FunctionKind::kGeneratorFunction
+ : FunctionKind::kNormalFunction,
+ function_token_position, function_type, FunctionLiteral::NORMAL_ARITY,
+ CHECK_OK);
} else if (peek() == Token::SUPER) {
int beg_pos = position();
Consume(Token::SUPER);
materialized_literal_count, expected_property_count, handler_count,
num_parameters, FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction,
- FunctionLiteral::kNotParenthesized, FunctionLiteral::kArrowFunction,
+ FunctionLiteral::kNotParenthesized, FunctionKind::kArrowFunction,
start_pos);
function_literal->set_function_token_position(start_pos);
}
+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) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
Handle<Context> context(isolate->context());
PretenureFlag pretenure_flag = NOT_TENURED;
- return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
- shared, context, pretenure_flag);
+ return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
+ pretenure_flag);
}
F(FunctionMarkNameShouldPrintAsAnonymous, 1, 1) \
F(FunctionIsGenerator, 1, 1) \
F(FunctionIsArrow, 1, 1) \
+ F(FunctionIsConciseMethod, 1, 1) \
F(FunctionBindArguments, 4, 1) \
F(BoundFunctionGetBindings, 1, 1) \
F(FunctionRemovePrototype, 1, 1) \
var name = %FunctionNameShouldPrintAsAnonymous(func)
? 'anonymous'
: %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;
}
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(isolate(),
- info->strict_mode(),
- info->is_generator());
+ FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
__ Move(rbx, info);
__ CallStub(&stub);
} else {
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(isolate(),
- instr->hydrogen()->strict_mode(),
- instr->hydrogen()->is_generator());
+ FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+ instr->hydrogen()->kind());
__ Move(rbx, instr->hydrogen()->shared_info());
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else {
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(isolate(),
- info->strict_mode(),
- info->is_generator());
+ FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
__ mov(ebx, Immediate(info));
__ CallStub(&stub);
} else {
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(isolate(),
- instr->hydrogen()->strict_mode(),
- instr->hydrogen()->is_generator());
+ FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
+ instr->hydrogen()->kind());
__ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else {
kAllowGenerators,
kAllowHarmonyNumericLiterals,
kAllowArrowFunctions,
- kAllowClasses
+ kAllowClasses,
+ kAllowHarmonyObjectLiterals
};
parser->set_allow_generators(flags.Contains(kAllowGenerators));
parser->set_allow_harmony_numeric_literals(
flags.Contains(kAllowHarmonyNumericLiterals));
+ parser->set_allow_harmony_object_literals(
+ flags.Contains(kAllowHarmonyObjectLiterals));
parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
parser->set_allow_classes(flags.Contains(kAllowClasses));
}
CcTest::i_isolate()->stack_guard()->SetStackLimit(
i::GetCurrentStackPosition() - 128 * 1024);
- static const ParserFlag flags1[] = {kAllowLazy, kAllowHarmonyScoping,
- kAllowModules, kAllowGenerators,
- kAllowArrowFunctions};
+ static const ParserFlag flags1[] = {
+ kAllowLazy, kAllowHarmonyScoping,
+ kAllowModules, kAllowGenerators,
+ kAllowArrowFunctions, kAllowHarmonyNumericLiterals,
+ kAllowHarmonyObjectLiterals};
for (int i = 0; context_data[i][0] != NULL; ++i) {
for (int j = 0; statement_data[j] != NULL; ++j) {
for (int k = 0; termination_data[k] != NULL; ++k) {
i::GetCurrentStackPosition() - 128 * 1024);
static const ParserFlag default_flags[] = {
- kAllowLazy, kAllowHarmonyScoping, kAllowModules,
- kAllowGenerators, kAllowNativesSyntax, kAllowArrowFunctions,
- kAllowClasses};
+ kAllowArrowFunctions, kAllowClasses,
+ kAllowGenerators, kAllowHarmonyNumericLiterals,
+ kAllowHarmonyObjectLiterals, kAllowHarmonyScoping,
+ kAllowLazy, kAllowModules,
+ kAllowNativesSyntax,
+ };
ParserFlag* generated_flags = NULL;
if (flags == NULL) {
flags = default_flags;
};
const char* statement_data[] = {
- ",", "foo: 1, get foo() {}", "foo: 1, set foo(v) {}",
- "\"foo\": 1, get \"foo\"() {}", "\"foo\": 1, set \"foo\"(v) {}",
- "1: 1, get 1() {}", "1: 1, set 1() {}",
+ ",",
+ "foo: 1, get foo() {}",
+ "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
// mode). Note that we can have "foo" and foo as properties in classic
// mode,
// 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, set foo(v) {}",
- "1: 1, get \"1\"() {}", "1: 1, set \"1\"() {}",
+ "foo: 1, get \"foo\"() {}",
+ "foo: 1, set \"foo\"(v) {}",
+ "\"foo\": 1, get foo() {}",
+ "\"foo\": 1, set foo(v) {}",
+ "1: 1, get \"1\"() {}",
+ "1: 1, set \"1\"() {}",
"\"1\": 1, get 1() {}"
"\"1\": 1, set 1(v) {}"
// Wrong number of parameters
"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
- "get foo( +", "get foo() \"error\"", NULL};
+ "get foo( +",
+ "get foo() \"error\"",
+ NULL};
RunParserSyncTest(context_data, statement_data, kError);
}
"\"foo\": 1, set \"bar\"(v) {}",
"1: 1, get 2() {}",
"1: 1, set 2(v) {}",
+ "get: 1, get foo() {}",
+ "set: 1, set foo(_) {}",
// Keywords, future reserved and strict future reserved are also allowed as
// property names.
"if: 4",
RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
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));
+}
--- /dev/null
+// 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'));
+})();
--- /dev/null
+// 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);