Diff
Modified: trunk/JSTests/ChangeLog (233854 => 233855)
--- trunk/JSTests/ChangeLog 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/JSTests/ChangeLog 2018-07-16 18:49:22 UTC (rev 233855)
@@ -1,3 +1,23 @@
+2018-07-12 Yusuke Suzuki <[email protected]>
+
+ [JSC] Generator and AsyncGeneratorMethod's prototype is incorrect
+ https://bugs.webkit.org/show_bug.cgi?id=187585
+
+ Reviewed by Darin Adler.
+
+ * stress/default-proto-for-async-generator.js: Added.
+ (shouldBe):
+ (async.asyncGenerator):
+ * stress/default-proto-for-generator.js: Added.
+ (shouldBe):
+ (generator):
+ * stress/prototype-for-async-generator.js: Added.
+ (shouldBe):
+ (async.asyncGenerator):
+ (A.prototype.async.asyncGenerator):
+ (A):
+ * test262/expectations.yaml:
+
2018-07-11 Ryan Haddad <[email protected]>
Skip JSC test stress/keep-checks-when-converting-to-lazy-js-constant-in-strength-reduction.js
Added: trunk/JSTests/stress/default-proto-for-async-generator.js (0 => 233855)
--- trunk/JSTests/stress/default-proto-for-async-generator.js (rev 0)
+++ trunk/JSTests/stress/default-proto-for-async-generator.js 2018-07-16 18:49:22 UTC (rev 233855)
@@ -0,0 +1,11 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+async function* asyncGenerator() { }
+
+var AsyncGeneratorPrototype = Object.getPrototypeOf(asyncGenerator).prototype;
+asyncGenerator.prototype = null;
+
+shouldBe(Object.getPrototypeOf(asyncGenerator()), AsyncGeneratorPrototype);
Added: trunk/JSTests/stress/default-proto-for-generator.js (0 => 233855)
--- trunk/JSTests/stress/default-proto-for-generator.js (rev 0)
+++ trunk/JSTests/stress/default-proto-for-generator.js 2018-07-16 18:49:22 UTC (rev 233855)
@@ -0,0 +1,11 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function* generator() { }
+
+var GeneratorPrototype = Object.getPrototypeOf(generator).prototype;
+generator.prototype = null;
+
+shouldBe(Object.getPrototypeOf(generator()), GeneratorPrototype);
Added: trunk/JSTests/stress/prototype-for-async-generator.js (0 => 233855)
--- trunk/JSTests/stress/prototype-for-async-generator.js (rev 0)
+++ trunk/JSTests/stress/prototype-for-async-generator.js 2018-07-16 18:49:22 UTC (rev 233855)
@@ -0,0 +1,19 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+async function* asyncGenerator() { }
+
+var AsyncGeneratorPrototype = Object.getPrototypeOf(asyncGenerator).prototype;
+
+shouldBe(Object.getPrototypeOf(asyncGenerator.prototype), AsyncGeneratorPrototype);
+
+class A {
+ async *asyncGenerator()
+ {
+ }
+}
+
+var a = new A;
+shouldBe(Object.getPrototypeOf(a.asyncGenerator.prototype), AsyncGeneratorPrototype);
Modified: trunk/JSTests/test262/expectations.yaml (233854 => 233855)
--- trunk/JSTests/test262/expectations.yaml 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/JSTests/test262/expectations.yaml 2018-07-16 18:49:22 UTC (rev 233855)
@@ -2686,12 +2686,6 @@
default: 'Test262Error: Expected SameValue(«inside», «outside») to be true'
test/language/expressions/function/scope-param-rest-elem-var-close.js:
default: 'Test262Error: Expected SameValue(«inside», «outside») to be true'
-test/language/expressions/generators/default-proto.js:
- default: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
- strict mode: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
-test/language/expressions/generators/eval-body-proto-realm.js:
- default: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
- strict mode: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
test/language/expressions/generators/generator-created-after-decl-inst.js:
default: 'Test262Error: Expected SameValue(«[object Generator]», «[object Generator]») to be false'
strict mode: 'Test262Error: Expected SameValue(«[object Generator]», «[object Generator]») to be false'
@@ -3742,9 +3736,6 @@
default: 'Test262Error: Expected SameValue(«inside», «outside») to be true'
test/language/statements/function/scope-param-rest-elem-var-close.js:
default: 'Test262Error: Expected SameValue(«inside», «outside») to be true'
-test/language/statements/generators/default-proto.js:
- default: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
- strict mode: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
test/language/statements/generators/generator-created-after-decl-inst.js:
default: 'Test262Error: Expected SameValue(«[object Generator]», «[object Generator]») to be false'
strict mode: 'Test262Error: Expected SameValue(«[object Generator]», «[object Generator]») to be false'
Modified: trunk/Source/_javascript_Core/ChangeLog (233854 => 233855)
--- trunk/Source/_javascript_Core/ChangeLog 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-07-16 18:49:22 UTC (rev 233855)
@@ -1,3 +1,39 @@
+2018-07-12 Yusuke Suzuki <[email protected]>
+
+ [JSC] Generator and AsyncGeneratorMethod's prototype is incorrect
+ https://bugs.webkit.org/show_bug.cgi?id=187585
+
+ Reviewed by Darin Adler.
+
+ This patch fixes Generator and AsyncGenerator's prototype issues.
+
+ 1. Generator's default prototype is incorrect when `generator.prototype = null` is performed.
+ We fix this by changing JSFunction::prototypeForConstruction.
+
+ 2. AsyncGeneratorMethod is not handled. We change the name isAsyncGeneratorFunctionParseMode
+ to isAsyncGeneratorWrapperParseMode since it is aligned to Generator's code. And use it well
+ to fix `prototype` issues for AsyncGeneratorMethod.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitPutAsyncGeneratorFields):
+ (JSC::BytecodeGenerator::emitNewFunction):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::FunctionNode::emitBytecode):
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createFunctionMetadata):
+ * parser/Parser.cpp:
+ (JSC::getAsynFunctionBodyParseMode):
+ (JSC::Parser<LexerType>::parseInner):
+ (JSC::Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements):
+ * parser/ParserModes.h:
+ (JSC::isAsyncGeneratorParseMode):
+ (JSC::isAsyncGeneratorWrapperParseMode):
+ (JSC::isAsyncGeneratorFunctionParseMode): Deleted.
+ * runtime/FunctionExecutable.h:
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::prototypeForConstruction):
+ (JSC::JSFunction::getOwnPropertySlot):
+
2018-07-16 Mark Lam <[email protected]>
jsc shell's noFTL utility test function should be more robust.
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (233854 => 233855)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2018-07-16 18:49:22 UTC (rev 233855)
@@ -2878,7 +2878,7 @@
void BytecodeGenerator::emitPutAsyncGeneratorFields(RegisterID* nextFunction)
{
- ASSERT(isAsyncGeneratorFunctionParseMode(parseMode()));
+ ASSERT(isAsyncGeneratorWrapperParseMode(parseMode()));
emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().generatorNextPrivateName(), nextFunction, PropertyNode::KnownDirect);
@@ -3359,7 +3359,7 @@
emitOpcode(op_new_generator_func);
else if (function->parseMode() == SourceParseMode::AsyncFunctionMode)
emitOpcode(op_new_async_func);
- else if (function->parseMode() == SourceParseMode::AsyncGeneratorWrapperFunctionMode) {
+ else if (isAsyncGeneratorWrapperParseMode(function->parseMode())) {
ASSERT(Options::useAsyncIterator());
emitOpcode(op_new_async_generator_func);
} else
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (233854 => 233855)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2018-07-16 18:49:22 UTC (rev 233855)
@@ -3790,7 +3790,7 @@
if (isGeneratorWrapperParseMode(generator.parseMode()))
generator.emitPutGeneratorFields(next.get());
else {
- ASSERT(isAsyncGeneratorFunctionParseMode(generator.parseMode()));
+ ASSERT(isAsyncGeneratorWrapperParseMode(generator.parseMode()));
generator.emitPutAsyncGeneratorFields(next.get());
}
Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (233854 => 233855)
--- trunk/Source/_javascript_Core/parser/ASTBuilder.h 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h 2018-07-16 18:49:22 UTC (rev 233855)
@@ -446,7 +446,7 @@
unsigned parameterCount,
SourceParseMode mode, bool isArrowFunctionBodyExpression)
{
- ASSERT(Options::useAsyncIterator() || (mode != SourceParseMode::AsyncGeneratorBodyMode && mode != SourceParseMode::AsyncGeneratorWrapperFunctionMode && mode != SourceParseMode::AsyncGeneratorWrapperMethodMode));
+ ASSERT(Options::useAsyncIterator() || !isAsyncGeneratorParseMode(mode));
return new (m_parserArena) FunctionMetadataNode(
m_parserArena, startLocation, endLocation, startColumn, endColumn,
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (233854 => 233855)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2018-07-16 18:49:22 UTC (rev 233855)
@@ -90,7 +90,7 @@
ALWAYS_INLINE static SourceParseMode getAsynFunctionBodyParseMode(SourceParseMode parseMode)
{
- if (isAsyncGeneratorFunctionParseMode(parseMode))
+ if (isAsyncGeneratorWrapperParseMode(parseMode))
return SourceParseMode::AsyncGeneratorBodyMode;
if (parseMode == SourceParseMode::AsyncArrowFunctionMode)
@@ -237,7 +237,7 @@
sourceElements = parseModuleSourceElements(context, parseMode);
else if (isGeneratorWrapperParseMode(parseMode))
sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
- else if (isAsyncGeneratorFunctionParseMode(parseMode))
+ else if (isAsyncGeneratorWrapperParseMode(parseMode))
sourceElements = parseAsyncGeneratorFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
else
sourceElements = parseSourceElements(context, CheckForStrictMode);
@@ -566,7 +566,7 @@
template <typename LexerType>
template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
{
- ASSERT_UNUSED(parseMode, isAsyncGeneratorFunctionParseMode(parseMode));
+ ASSERT_UNUSED(parseMode, isAsyncGeneratorWrapperParseMode(parseMode));
auto sourceElements = context.createSourceElements();
unsigned functionKeywordStart = tokenStart();
Modified: trunk/Source/_javascript_Core/parser/ParserModes.h (233854 => 233855)
--- trunk/Source/_javascript_Core/parser/ParserModes.h 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/parser/ParserModes.h 2018-07-16 18:49:22 UTC (rev 233855)
@@ -133,10 +133,18 @@
SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
}
-ALWAYS_INLINE bool isAsyncGeneratorFunctionParseMode(SourceParseMode parseMode)
+ALWAYS_INLINE bool isAsyncGeneratorParseMode(SourceParseMode parseMode)
{
return SourceParseModeSet(
SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+ SourceParseMode::AsyncGeneratorWrapperMethodMode,
+ SourceParseMode::AsyncGeneratorBodyMode).contains(parseMode);
+}
+
+ALWAYS_INLINE bool isAsyncGeneratorWrapperParseMode(SourceParseMode parseMode)
+{
+ return SourceParseModeSet(
+ SourceParseMode::AsyncGeneratorWrapperFunctionMode,
SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode);
}
Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.h (233854 => 233855)
--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.h 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.h 2018-07-16 18:49:22 UTC (rev 233855)
@@ -136,7 +136,7 @@
bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; }
bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; }
bool isGenerator() const { return isGeneratorParseMode(parseMode()); }
- bool isAsyncGenerator() const { return SourceParseModeSet(SourceParseMode::AsyncGeneratorWrapperFunctionMode, SourceParseMode::AsyncGeneratorBodyMode).contains(parseMode()); }
+ bool isAsyncGenerator() const { return isAsyncGeneratorParseMode(parseMode()); }
bool isMethod() const { return parseMode() == SourceParseMode::MethodMode; }
bool hasCallerAndArgumentsProperties() const
{
@@ -152,6 +152,7 @@
SourceParseMode::GeneratorWrapperFunctionMode,
SourceParseMode::GeneratorWrapperMethodMode,
SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+ SourceParseMode::AsyncGeneratorWrapperMethodMode,
SourceParseMode::AsyncGeneratorBodyMode
).contains(parseMode()) || isClass();
}
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (233854 => 233855)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2018-07-16 18:49:22 UTC (rev 233855)
@@ -150,10 +150,20 @@
auto scope = DECLARE_CATCH_SCOPE(vm);
JSValue prototype = get(exec, vm.propertyNames->prototype);
scope.releaseAssertNoException();
- if (prototype.isObject())
+ if (LIKELY(prototype.isObject()))
return asObject(prototype);
- return globalObject(vm)->objectPrototype();
+ JSGlobalObject* globalObject = this->globalObject(vm);
+ if (!isHostOrBuiltinFunction()) {
+ // https://tc39.github.io/ecma262/#sec-generator-function-definitions-runtime-semantics-evaluatebody
+ if (isGeneratorWrapperParseMode(jsExecutable()->parseMode()))
+ return globalObject->generatorPrototype();
+
+ // https://tc39.github.io/ecma262/#sec-asyncgenerator-definitions-evaluatebody
+ if (isAsyncGeneratorWrapperParseMode(jsExecutable()->parseMode()))
+ return globalObject->asyncGeneratorPrototype();
+ }
+ return globalObject->objectPrototype();
}
FunctionRareData* JSFunction::allocateAndInitializeRareData(ExecState* exec, size_t inlineCapacity)
@@ -418,7 +428,7 @@
// property does not have a constructor property whose value is the GeneratorFunction instance.
// https://tc39.github.io/ecma262/#sec-generatorfunction-instances-prototype
prototype = constructEmptyObject(exec, thisObject->globalObject(vm)->generatorPrototype());
- } else if (thisObject->jsExecutable()->parseMode() == SourceParseMode::AsyncGeneratorWrapperFunctionMode)
+ } else if (isAsyncGeneratorWrapperParseMode(thisObject->jsExecutable()->parseMode()))
prototype = constructEmptyObject(exec, thisObject->globalObject(vm)->asyncGeneratorPrototype());
else {
prototype = constructEmptyObject(exec);