typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker,
bool in_class, bool is_static, bool* ok) {
- // TODO(arv): Add support for concise generator methods.
ExpressionT value = this->EmptyExpression();
bool is_get = false;
bool is_set = false;
bool name_is_static = false;
+ bool is_generator = allow_harmony_object_literals_ && Check(Token::MUL);
+
Token::Value name_token = peek();
int next_pos = peek_position();
IdentifierT name =
if (fni_ != NULL) this->PushLiteralName(fni_, name);
- if (!in_class && peek() == Token::COLON) {
+ if (!in_class && !is_generator && peek() == Token::COLON) {
// PropertyDefinition : PropertyName ':' AssignmentExpression
checker->CheckProperty(name_token, kValueProperty,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
value = this->ParseAssignmentExpression(
true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- } else if (allow_harmony_object_literals_ && peek() == Token::LPAREN) {
+ } else if (is_generator ||
+ (allow_harmony_object_literals_ && peek() == Token::LPAREN)) {
// Concise Method
if (is_static && this->IsPrototype(name)) {
*ok = false;
return this->EmptyObjectLiteralProperty();
}
+ if (is_generator && in_class && !is_static && this->IsConstructor(name)) {
+ ReportMessageAt(scanner()->location(), "constructor_special_method");
+ *ok = false;
+ return this->EmptyObjectLiteralProperty();
+ }
checker->CheckProperty(name_token, kValueProperty,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod
+ : FunctionKind::kConciseMethod;
+
value = this->ParseFunctionLiteral(
name, scanner()->location(),
false, // reserved words are allowed here
- FunctionKind::kConciseMethod, RelocInfo::kNoPosition,
- FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::NORMAL_ARITY,
+ kind, RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION,
+ FunctionLiteral::NORMAL_ARITY,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
} else if (in_class && name_is_static && !is_static) {
TEST(NoErrorsMethodDefinition) {
const char* context_data[][2] = {{"({", "});"},
{"'use strict'; ({", "});"},
+ {"({*", "});"},
+ {"'use strict'; ({*", "});"},
{NULL, NULL}};
const char* object_literal_body_data[] = {
TEST(MethodDefinitionNames) {
const char* context_data[][2] = {{"({", "(x, y) {}});"},
{"'use strict'; ({", "(x, y) {}});"},
+ {"({*", "(x, y) {}});"},
+ {"'use strict'; ({*", "(x, y) {}});"},
{NULL, NULL}};
const char* name_data[] = {
TEST(MethodDefinitionStrictFormalParamereters) {
const char* context_data[][2] = {{"({method(", "){}});"},
{"'use strict'; ({method(", "){}});"},
+ {"({*method(", "){}});"},
+ {"'use strict'; ({*method(", "){}});"},
{NULL, NULL}};
const char* params_data[] = {
"x() {}, 'x'() {}",
"0() {}, '0'() {}",
"1.0() {}, 1: 1",
+
+ "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
};
}
-TEST(NoErrorsClassExpression) {
+TEST(ClassExpressionNoErrors) {
const char* context_data[][2] = {{"(", ");"},
{"var C = ", ";"},
{"bar, ", ";"},
}
-TEST(NoErrorsClassDeclaration) {
+TEST(ClassDeclarationNoErrors) {
const char* context_data[][2] = {{"", ""},
{"{", "}"},
{"if (true) {", "}"},
}
-TEST(NoErrorsClassBody) {
+TEST(ClassBodyNoErrors) {
// Tests that parser and preparser accept valid class syntax.
const char* context_data[][2] = {{"(class {", "});"},
{"(class extends Base {", "});"},
";;",
"m() {}",
"m() {};",
- ";m() {}",
+ "; m() {}",
"m() {}; n(x) {}",
"get x() {}",
"set x(v) {}",
"get() {}",
"set() {}",
+ "*g() {}",
+ "*g() {};",
+ "; *g() {}",
+ "*g() {}; *h(x) {}",
"static() {}",
"static m() {}",
"static get x() {}",
"static static() {}",
"static get static() {}",
"static set static(v) {}",
+ "*static() {}",
+ "*get() {}",
+ "*set() {}",
+ "static *g() {}",
NULL};
static const ParserFlag always_flags[] = {
}
-TEST(MethodDefinitionstrictFormalParamereters) {
- const char* context_data[][2] = {{"({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(NoErrorsClassPropertyName) {
+TEST(ClassPropertyNameNoErrors) {
const char* context_data[][2] = {{"(class {", "() {}});"},
{"(class { get ", "() {}});"},
{"(class { set ", "(v) {}});"},
{"(class { static ", "() {}});"},
{"(class { static get ", "() {}});"},
{"(class { static set ", "(v) {}});"},
+ {"(class { *", "() {}});"},
+ {"(class { static *", "() {}});"},
{"class C {", "() {}}"},
{"class C { get ", "() {}}"},
{"class C { set ", "(v) {}}"},
{"class C { static ", "() {}}"},
{"class C { static get ", "() {}}"},
{"class C { static set ", "(v) {}}"},
+ {"class C { *", "() {}}"},
+ {"class C { static *", "() {}}"},
{NULL, NULL}};
const char* name_data[] = {
"42",
}
-TEST(ErrorsClassExpression) {
+TEST(ClassExpressionErrors) {
const char* context_data[][2] = {{"(", ");"},
{"var C = ", ";"},
{"bar, ", ";"},
}
-TEST(ErrorsClassDeclaration) {
+TEST(ClassDeclarationErrors) {
const char* context_data[][2] = {{"", ""},
{"{", "}"},
{"if (true) {", "}"},
"class name { m; n }",
"class name { m: 1 }",
"class name { m(); n() }",
- "class name { get m }",
- "class name { get m() }",
- "class name { set m() {) }", // missing required param
+ "class name { get x }",
+ "class name { get x() }",
+ "class name { set x() {) }", // missing required param
"class {}", // Name is required for declaration
"class extends base {}",
+ "class name { *",
+ "class name { * }",
+ "class name { *; }",
+ "class name { *get x() {} }",
+ "class name { *set x(_) {} }",
+ "class name { *static m() {} }",
NULL};
static const ParserFlag always_flags[] = {
}
-TEST(ErrorsClassName) {
+TEST(ClassNameErrors) {
const char* context_data[][2] = {{"class ", "{}"},
{"(class ", "{});"},
{"'use strict'; class ", "{}"},
}
-TEST(ErrorsClassGetterParamName) {
+TEST(ClassGetterParamNameErrors) {
const char* context_data[][2] = {
{"class C { get name(", ") {} }"},
{"(class { get name(", ") {} });"},
}
-TEST(ErrorsClassStaticPrototype) {
+TEST(ClassStaticPrototypeErrors) {
const char* context_data[][2] = {{"class C {", "}"},
{"(class {", "});"},
{NULL, NULL}};
"static prototype() {}",
"static get prototype() {}",
"static set prototype(_) {}",
+ "static *prototype() {}",
NULL};
static const ParserFlag always_flags[] = {
}
-TEST(ErrorsClassSpecialConstructor) {
+TEST(ClassSpecialConstructorErrors) {
const char* context_data[][2] = {{"class C {", "}"},
{"(class {", "});"},
{NULL, NULL}};
const char* class_body_data[] = {
"get constructor() {}",
"get constructor(_) {}",
+ "*constructor() {}",
NULL};
static const ParserFlag always_flags[] = {
}
-TEST(NoErrorsClassConstructor) {
+TEST(ClassConstructorNoErrors) {
const char* context_data[][2] = {{"class C {", "}"},
{"(class {", "});"},
{NULL, NULL}};
"static constructor() {}",
"static get constructor() {}",
"static set constructor(_) {}",
+ "static *constructor() {}",
NULL};
static const ParserFlag always_flags[] = {
}
-TEST(ErrorsClassMultipleConstructor) {
+TEST(ClassMultipleConstructorErrors) {
// We currently do not allow any duplicate properties in class bodies. This
// test ensures that when we change that we still throw on duplicate
// constructors.
// TODO(arv): We should allow duplicate property names.
// https://code.google.com/p/v8/issues/detail?id=3570
-DISABLED_TEST(NoErrorsClassMultiplePropertyNames) {
+DISABLED_TEST(ClassMultiplePropertyNamesNoErrors) {
const char* context_data[][2] = {{"class C {", "}"},
{"(class {", "});"},
{NULL, NULL}};
}
-TEST(ErrorsClassesAreStrict) {
+TEST(ClassesAreStrictErrors) {
const char* context_data[][2] = {{"", ""},
{"(", ");"},
{NULL, NULL}};
const char* class_body_data[] = {
"class C { method() { with ({}) {} } }",
"class C extends function() { with ({}) {} } {}",
+ "class C { *method() { with ({}) {} } }",
NULL};
static const ParserFlag always_flags[] = {
// Flags: --harmony-object-literals --allow-natives-syntax
-(function TestDescriptor() {
+(function TestBasics() {
var object = {
method() {
return 42;
})();
+(function TestThis() {
+ var object = {
+ method() {
+ assertEquals(object, this);
+ }
+ };
+ object.method();
+})();
+
+
(function TestDescriptor() {
var object = {
method() {
(function TestProto() {
var object = {
- method() {
- return 42;
- }
+ method() {}
};
assertEquals(Function.prototype, Object.getPrototypeOf(object.method));
(function TestNotConstructable() {
var object = {
- method() {
- return 42;
- }
+ method() {}
};
assertThrows(function() {
(function TestFunctionName() {
var object = {
- method() {
- return 42;
- },
+ method() {},
1() {},
2.0() {}
};
assertEquals('method', f.name);
var g = object[1];
assertEquals('1', g.name);
-
var h = object[2];
assertEquals('2', h.name);
})();
(function TestNoPrototype() {
var object = {
- method() {
- return 42;
- }
+ method() {}
};
var f = object.method;
assertFalse(f.hasOwnProperty('prototype'));
assertEquals(42, object.method());
assertFalse(object.method.hasOwnProperty('prototype'));
})();
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+var GeneratorFunction = function*() {}.__proto__.constructor;
+
+
+function assertIteratorResult(value, done, result) {
+ assertEquals({value: value, done: done}, result);
+}
+
+
+(function TestGeneratorBasics() {
+ var object = {
+ *method() {
+ yield 1;
+ }
+ };
+ var g = object.method();
+ assertIteratorResult(1, false, g.next());
+ assertIteratorResult(undefined, true, g.next());
+})();
+
+
+(function TestGeneratorThis() {
+ var object = {
+ *method() {
+ yield this;
+ }
+ };
+ var g = object.method();
+ assertIteratorResult(object, false, g.next());
+ assertIteratorResult(undefined, true, g.next());
+})();
+
+
+(function TestGeneratorSymbolIterator() {
+ var object = {
+ *method() {}
+ };
+ var g = object.method();
+ assertEquals(g, g[Symbol.iterator]());
+})();
+
+
+(function TestGeneratorDescriptor() {
+ var object = {
+ *method() {
+ yield 1;
+ }
+ };
+
+ var desc = Object.getOwnPropertyDescriptor(object, 'method');
+ assertTrue(desc.enumerable);
+ assertTrue(desc.configurable);
+ assertTrue(desc.writable);
+ assertEquals('function', typeof desc.value);
+
+ var g = desc.value();
+ assertIteratorResult(1, false, g.next());
+ assertIteratorResult(undefined, true, g.next());
+})();
+
+
+(function TestGeneratorProto() {
+ var object = {
+ *method() {}
+ };
+
+ assertEquals(GeneratorFunction.prototype,
+ Object.getPrototypeOf(object.method));
+})();
+
+
+(function TestGeneratorConstructable() {
+ var object = {
+ *method() {
+ yield 1;
+ }
+ };
+
+ var g = new object.method();
+ assertIteratorResult(1, false, g.next());
+ assertIteratorResult(undefined, true, g.next());
+})();
+
+
+(function TestGeneratorName() {
+ var object = {
+ *method() {},
+ *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 TestGeneratorNoBinding() {
+ var method = 'local';
+ var calls = 0;
+ var object = {
+ *method() {
+ calls++;
+ assertEquals('local', method);
+ }
+ };
+ var g = object.method();
+ assertIteratorResult(undefined, true, g.next());
+ assertEquals(1, calls);
+})();
+
+
+(function TestGeneratorToString() {
+ var object = {
+ *method() { yield 1; }
+ };
+ assertEquals('*method() { yield 1; }', object.method.toString());
+})();