[esnext] Fix various callsites to use is_resumable, not is_generator
Async functions are built out of generators, but the SharedFunctionInfo returns false for is_generator. is_resumable is the broader query. This patch fixes many parts of V8 to refer to is_resumable as appropriate. One incidental change is to remove a check for generators extending classes. This is part of a general check for constructors being the only thing which can extend classes, so it is removed here and the error message for the general case is made more accurate. BUG=v8:4483 Review-Url: https://codereview.chromium.org/1996943002 Cr-Commit-Position: refs/heads/master@{#36621}
This commit is contained in:
parent
0ac67d74c6
commit
46253e743d
@ -874,10 +874,11 @@ MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
|
|||||||
return MaybeHandle<Code>();
|
return MaybeHandle<Code>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(4280): For now we do not switch generators to baseline code because
|
// TODO(4280): For now we do not switch generators or async functions to
|
||||||
// there might be suspended activations stored in generator objects on the
|
// baseline code because there might be suspended activations stored in
|
||||||
// heap. We could eventually go directly to TurboFan in this case.
|
// generator objects on the heap. We could eventually go directly to
|
||||||
if (function->shared()->is_generator()) {
|
// TurboFan in this case.
|
||||||
|
if (function->shared()->is_resumable()) {
|
||||||
return MaybeHandle<Code>();
|
return MaybeHandle<Code>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1308,10 +1309,11 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
|
|||||||
CompilationInfo unoptimized(info->parse_info(), info->closure());
|
CompilationInfo unoptimized(info->parse_info(), info->closure());
|
||||||
unoptimized.EnableDeoptimizationSupport();
|
unoptimized.EnableDeoptimizationSupport();
|
||||||
|
|
||||||
// TODO(4280): For now we do not switch generators to baseline code because
|
// TODO(4280): For now we do not switch generators or async functions to
|
||||||
// there might be suspended activations stored in generator objects on the
|
// baseline code because there might be suspended activations stored in
|
||||||
// heap. We could eventually go directly to TurboFan in this case.
|
// generator objects on the heap. We could eventually go directly to
|
||||||
if (shared->is_generator()) return false;
|
// TurboFan in this case.
|
||||||
|
if (shared->is_resumable()) return false;
|
||||||
|
|
||||||
// TODO(4280): For now we disable switching to baseline code in the presence
|
// TODO(4280): For now we disable switching to baseline code in the presence
|
||||||
// of interpreter activations of the given function. The reasons are:
|
// of interpreter activations of the given function. The reasons are:
|
||||||
|
@ -1325,7 +1325,7 @@ bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
|
|||||||
// smarter here and avoid the heap walk.
|
// smarter here and avoid the heap walk.
|
||||||
HeapIterator iterator(isolate_->heap());
|
HeapIterator iterator(isolate_->heap());
|
||||||
HeapObject* obj;
|
HeapObject* obj;
|
||||||
bool include_generators = !is_interpreted && shared->is_generator();
|
bool find_resumables = !is_interpreted && shared->is_resumable();
|
||||||
|
|
||||||
while ((obj = iterator.next())) {
|
while ((obj = iterator.next())) {
|
||||||
if (obj->IsJSFunction()) {
|
if (obj->IsJSFunction()) {
|
||||||
@ -1336,7 +1336,9 @@ bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
|
|||||||
}
|
}
|
||||||
if (is_interpreted) continue;
|
if (is_interpreted) continue;
|
||||||
if (function->shared() == *shared) functions.Add(handle(function));
|
if (function->shared() == *shared) functions.Add(handle(function));
|
||||||
} else if (include_generators && obj->IsJSGeneratorObject()) {
|
} else if (find_resumables && obj->IsJSGeneratorObject()) {
|
||||||
|
// This case handles async functions as well, as they use generator
|
||||||
|
// objects for in-progress async function execution.
|
||||||
JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
|
JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
|
||||||
if (!generator_obj->is_suspended()) continue;
|
if (!generator_obj->is_suspended()) continue;
|
||||||
JSFunction* function = generator_obj->function();
|
JSFunction* function = generator_obj->function();
|
||||||
|
@ -1680,7 +1680,7 @@ static const char* DropActivationsInActiveThreadImpl(Isolate* isolate,
|
|||||||
if (frame->is_java_script()) {
|
if (frame->is_java_script()) {
|
||||||
SharedFunctionInfo* shared =
|
SharedFunctionInfo* shared =
|
||||||
JavaScriptFrame::cast(frame)->function()->shared();
|
JavaScriptFrame::cast(frame)->function()->shared();
|
||||||
if (shared->is_generator()) {
|
if (shared->is_resumable()) {
|
||||||
non_droppable_frame_found = true;
|
non_droppable_frame_found = true;
|
||||||
non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
|
non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
|
||||||
break;
|
break;
|
||||||
|
@ -1298,7 +1298,10 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code,
|
|||||||
ElementsKind elements_kind =
|
ElementsKind elements_kind =
|
||||||
type == JS_ARRAY_TYPE ? FAST_SMI_ELEMENTS : FAST_HOLEY_SMI_ELEMENTS;
|
type == JS_ARRAY_TYPE ? FAST_SMI_ELEMENTS : FAST_HOLEY_SMI_ELEMENTS;
|
||||||
Handle<Map> initial_map = NewMap(type, instance_size, elements_kind);
|
Handle<Map> initial_map = NewMap(type, instance_size, elements_kind);
|
||||||
if (!function->shared()->is_generator()) {
|
// TODO(littledan): Why do we have this is_generator test when
|
||||||
|
// NewFunctionPrototype already handles finding an appropriately
|
||||||
|
// shared prototype?
|
||||||
|
if (!function->shared()->is_resumable()) {
|
||||||
if (prototype->IsTheHole()) {
|
if (prototype->IsTheHole()) {
|
||||||
prototype = NewFunctionPrototype(function);
|
prototype = NewFunctionPrototype(function);
|
||||||
} else if (install_constructor) {
|
} else if (install_constructor) {
|
||||||
@ -1327,11 +1330,12 @@ Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
|
|||||||
// can be from a different context.
|
// can be from a different context.
|
||||||
Handle<Context> native_context(function->context()->native_context());
|
Handle<Context> native_context(function->context()->native_context());
|
||||||
Handle<Map> new_map;
|
Handle<Map> new_map;
|
||||||
if (function->shared()->is_generator()) {
|
if (function->shared()->is_resumable()) {
|
||||||
// Generator prototypes can share maps since they don't have "constructor"
|
// Generator and async function prototypes can share maps since they
|
||||||
// properties.
|
// don't have "constructor" properties.
|
||||||
new_map = handle(native_context->generator_object_prototype_map());
|
new_map = handle(native_context->generator_object_prototype_map());
|
||||||
} else {
|
} else {
|
||||||
|
CHECK(!function->shared()->is_async());
|
||||||
// Each function prototype gets a fresh map to avoid unwanted sharing of
|
// Each function prototype gets a fresh map to avoid unwanted sharing of
|
||||||
// maps between prototypes of different constructors.
|
// maps between prototypes of different constructors.
|
||||||
Handle<JSFunction> object_function(native_context->object_function());
|
Handle<JSFunction> object_function(native_context->object_function());
|
||||||
@ -1342,7 +1346,7 @@ Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
|
|||||||
DCHECK(!new_map->is_prototype_map());
|
DCHECK(!new_map->is_prototype_map());
|
||||||
Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
|
Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
|
||||||
|
|
||||||
if (!function->shared()->is_generator()) {
|
if (!function->shared()->is_resumable()) {
|
||||||
JSObject::AddProperty(prototype, constructor_string(), function, DONT_ENUM);
|
JSObject::AddProperty(prototype, constructor_string(), function, DONT_ENUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,10 +121,8 @@ class CallSite {
|
|||||||
T(DefineDisallowed, "Cannot define property:%, object is not extensible.") \
|
T(DefineDisallowed, "Cannot define property:%, object is not extensible.") \
|
||||||
T(DetachedOperation, "Cannot perform % on a detached ArrayBuffer") \
|
T(DetachedOperation, "Cannot perform % on a detached ArrayBuffer") \
|
||||||
T(DuplicateTemplateProperty, "Object template has duplicate property '%'") \
|
T(DuplicateTemplateProperty, "Object template has duplicate property '%'") \
|
||||||
T(ExtendsValueGenerator, \
|
T(ExtendsValueNotConstructor, \
|
||||||
"Class extends value % may not be a generator function") \
|
"Class extends value % is not a constructor or null") \
|
||||||
T(ExtendsValueNotFunction, \
|
|
||||||
"Class extends value % is not a function or null") \
|
|
||||||
T(FirstArgumentNotRegExp, \
|
T(FirstArgumentNotRegExp, \
|
||||||
"First argument to % must not be a regular expression") \
|
"First argument to % must not be a regular expression") \
|
||||||
T(FunctionBind, "Bind must be called on a function") \
|
T(FunctionBind, "Bind must be called on a function") \
|
||||||
|
@ -876,6 +876,8 @@ void JSFunction::JSFunctionPrint(std::ostream& os) { // NOLINT
|
|||||||
<< shared()->internal_formal_parameter_count();
|
<< shared()->internal_formal_parameter_count();
|
||||||
if (shared()->is_generator()) {
|
if (shared()->is_generator()) {
|
||||||
os << "\n - generator";
|
os << "\n - generator";
|
||||||
|
} else if (shared()->is_async()) {
|
||||||
|
os << "\n - async";
|
||||||
}
|
}
|
||||||
os << "\n - context = " << Brief(context());
|
os << "\n - context = " << Brief(context());
|
||||||
os << "\n - literals = " << Brief(literals());
|
os << "\n - literals = " << Brief(literals());
|
||||||
|
@ -94,13 +94,8 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate,
|
|||||||
if (super_class->IsNull()) {
|
if (super_class->IsNull()) {
|
||||||
prototype_parent = isolate->factory()->null_value();
|
prototype_parent = isolate->factory()->null_value();
|
||||||
} else if (super_class->IsConstructor()) {
|
} else if (super_class->IsConstructor()) {
|
||||||
if (super_class->IsJSFunction() &&
|
DCHECK(!super_class->IsJSFunction() ||
|
||||||
Handle<JSFunction>::cast(super_class)->shared()->is_generator()) {
|
!Handle<JSFunction>::cast(super_class)->shared()->is_resumable());
|
||||||
THROW_NEW_ERROR(
|
|
||||||
isolate,
|
|
||||||
NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class),
|
|
||||||
Object);
|
|
||||||
}
|
|
||||||
ASSIGN_RETURN_ON_EXCEPTION(
|
ASSIGN_RETURN_ON_EXCEPTION(
|
||||||
isolate, prototype_parent,
|
isolate, prototype_parent,
|
||||||
Runtime::GetObjectProperty(isolate, super_class,
|
Runtime::GetObjectProperty(isolate, super_class,
|
||||||
@ -114,9 +109,9 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate,
|
|||||||
}
|
}
|
||||||
constructor_parent = super_class;
|
constructor_parent = super_class;
|
||||||
} else {
|
} else {
|
||||||
THROW_NEW_ERROR(
|
THROW_NEW_ERROR(isolate,
|
||||||
isolate,
|
NewTypeError(MessageTemplate::kExtendsValueNotConstructor,
|
||||||
NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class),
|
super_class),
|
||||||
Object);
|
Object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ bytecodes: [
|
|||||||
B(TestEqualStrict), R(12),
|
B(TestEqualStrict), R(12),
|
||||||
B(JumpIfFalse), U8(4),
|
B(JumpIfFalse), U8(4),
|
||||||
B(Jump), U8(18),
|
B(Jump), U8(18),
|
||||||
B(Wide), B(LdaSmi), U16(129),
|
B(Wide), B(LdaSmi), U16(128),
|
||||||
B(Star), R(12),
|
B(Star), R(12),
|
||||||
B(LdaConstant), U8(8),
|
B(LdaConstant), U8(8),
|
||||||
B(Star), R(13),
|
B(Star), R(13),
|
||||||
@ -236,7 +236,7 @@ bytecodes: [
|
|||||||
B(TestEqualStrict), R(13),
|
B(TestEqualStrict), R(13),
|
||||||
B(JumpIfFalse), U8(4),
|
B(JumpIfFalse), U8(4),
|
||||||
B(Jump), U8(18),
|
B(Jump), U8(18),
|
||||||
B(Wide), B(LdaSmi), U16(129),
|
B(Wide), B(LdaSmi), U16(128),
|
||||||
B(Star), R(13),
|
B(Star), R(13),
|
||||||
B(LdaConstant), U8(8),
|
B(LdaConstant), U8(8),
|
||||||
B(Star), R(14),
|
B(Star), R(14),
|
||||||
@ -393,7 +393,7 @@ bytecodes: [
|
|||||||
B(TestEqualStrict), R(12),
|
B(TestEqualStrict), R(12),
|
||||||
B(JumpIfFalse), U8(4),
|
B(JumpIfFalse), U8(4),
|
||||||
B(Jump), U8(18),
|
B(Jump), U8(18),
|
||||||
B(Wide), B(LdaSmi), U16(129),
|
B(Wide), B(LdaSmi), U16(128),
|
||||||
B(Star), R(12),
|
B(Star), R(12),
|
||||||
B(LdaConstant), U8(8),
|
B(LdaConstant), U8(8),
|
||||||
B(Star), R(13),
|
B(Star), R(13),
|
||||||
@ -540,7 +540,7 @@ bytecodes: [
|
|||||||
B(TestEqualStrict), R(11),
|
B(TestEqualStrict), R(11),
|
||||||
B(JumpIfFalse), U8(4),
|
B(JumpIfFalse), U8(4),
|
||||||
B(Jump), U8(18),
|
B(Jump), U8(18),
|
||||||
B(Wide), B(LdaSmi), U16(129),
|
B(Wide), B(LdaSmi), U16(128),
|
||||||
B(Star), R(11),
|
B(Star), R(11),
|
||||||
B(LdaConstant), U8(10),
|
B(LdaConstant), U8(10),
|
||||||
B(Star), R(12),
|
B(Star), R(12),
|
||||||
|
@ -480,7 +480,7 @@ bytecodes: [
|
|||||||
B(TestEqualStrict), R(10),
|
B(TestEqualStrict), R(10),
|
||||||
B(JumpIfFalse), U8(4),
|
B(JumpIfFalse), U8(4),
|
||||||
B(Jump), U8(18),
|
B(Jump), U8(18),
|
||||||
B(Wide), B(LdaSmi), U16(129),
|
B(Wide), B(LdaSmi), U16(128),
|
||||||
B(Star), R(10),
|
B(Star), R(10),
|
||||||
B(LdaConstant), U8(14),
|
B(LdaConstant), U8(14),
|
||||||
B(Star), R(11),
|
B(Star), R(11),
|
||||||
|
46
test/mjsunit/debug-generator-break-on-stack.js
Normal file
46
test/mjsunit/debug-generator-break-on-stack.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2016 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: --expose-debug-as debug
|
||||||
|
|
||||||
|
var Debug = debug.Debug;
|
||||||
|
|
||||||
|
var break_count = 0;
|
||||||
|
var exception = null;
|
||||||
|
|
||||||
|
function listener(event, exec_state, event_data, data) {
|
||||||
|
if (event != Debug.DebugEvent.Break) return;
|
||||||
|
try {
|
||||||
|
break_count++;
|
||||||
|
var line = exec_state.frame(0).sourceLineText();
|
||||||
|
print(line);
|
||||||
|
assertTrue(line.indexOf(`B${break_count}`) > 0);
|
||||||
|
} catch (e) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function* g() {
|
||||||
|
setbreaks();
|
||||||
|
yield 1; // B1
|
||||||
|
}
|
||||||
|
|
||||||
|
function* f() {
|
||||||
|
yield* g();
|
||||||
|
return 2; // B2
|
||||||
|
}
|
||||||
|
|
||||||
|
function setbreaks() {
|
||||||
|
Debug.setListener(listener);
|
||||||
|
Debug.setBreakPoint(g, 2);
|
||||||
|
Debug.setBreakPoint(f, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let _ of f()) { }
|
||||||
|
|
||||||
|
assertEquals(2, break_count);
|
||||||
|
assertNull(exception);
|
||||||
|
|
||||||
|
Debug.setListener(null);
|
44
test/mjsunit/debug-generator-break.js
Normal file
44
test/mjsunit/debug-generator-break.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2016 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: --expose-debug-as debug
|
||||||
|
|
||||||
|
var Debug = debug.Debug;
|
||||||
|
|
||||||
|
var break_count = 0;
|
||||||
|
var exception = null;
|
||||||
|
|
||||||
|
function listener(event, exec_state, event_data, data) {
|
||||||
|
if (event != Debug.DebugEvent.Break) return;
|
||||||
|
try {
|
||||||
|
break_count++;
|
||||||
|
var line = exec_state.frame(0).sourceLineText();
|
||||||
|
assertTrue(line.indexOf(`B${break_count}`) > 0);
|
||||||
|
} catch (e) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.setListener(listener);
|
||||||
|
|
||||||
|
function* g() {
|
||||||
|
yield 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function* f() {
|
||||||
|
yield* g(); // B1
|
||||||
|
assertEquals(2, break_count); // B2
|
||||||
|
return 1; // B3
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.setBreakPoint(f, 1);
|
||||||
|
Debug.setBreakPoint(f, 2);
|
||||||
|
Debug.setBreakPoint(f, 3);
|
||||||
|
|
||||||
|
for (let _ of f()) { }
|
||||||
|
|
||||||
|
assertEquals(3, break_count);
|
||||||
|
assertNull(exception);
|
||||||
|
|
||||||
|
Debug.setListener(null);
|
@ -345,3 +345,6 @@ assertEquals("async x => { return x }", (async x => { return x }).toString());
|
|||||||
class AsyncMethod { async foo() { } }
|
class AsyncMethod { async foo() { } }
|
||||||
assertEquals("async foo() { }", Function.prototype.toString.call(AsyncMethod.prototype.foo));
|
assertEquals("async foo() { }", Function.prototype.toString.call(AsyncMethod.prototype.foo));
|
||||||
assertEquals("async foo() { }", Function.prototype.toString.call({async foo() { }}.foo));
|
assertEquals("async foo() { }", Function.prototype.toString.call({async foo() { }}.foo));
|
||||||
|
|
||||||
|
// Async functions are not constructible
|
||||||
|
assertThrows(() => class extends (async function() {}) {}, TypeError);
|
||||||
|
78
test/mjsunit/harmony/debug-async-break-on-stack.js
Normal file
78
test/mjsunit/harmony/debug-async-break-on-stack.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2016 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: --expose-debug-as debug
|
||||||
|
// Flags: --harmony-async-await --allow-natives-syntax
|
||||||
|
|
||||||
|
var Debug = debug.Debug;
|
||||||
|
|
||||||
|
function assertEqualsAsync(expected, run, msg) {
|
||||||
|
var actual;
|
||||||
|
var hadValue = false;
|
||||||
|
var hadError = false;
|
||||||
|
var promise = run();
|
||||||
|
|
||||||
|
if (typeof promise !== "object" || typeof promise.then !== "function") {
|
||||||
|
throw new MjsUnitAssertionError(
|
||||||
|
"Expected " + run.toString() +
|
||||||
|
" to return a Promise, but it returned " + promise);
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.then(function(value) { hadValue = true; actual = value; },
|
||||||
|
function(error) { hadError = true; actual = error; });
|
||||||
|
|
||||||
|
assertFalse(hadValue || hadError);
|
||||||
|
|
||||||
|
%RunMicrotasks();
|
||||||
|
|
||||||
|
if (hadError) throw actual;
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
hadValue, "Expected '" + run.toString() + "' to produce a value");
|
||||||
|
|
||||||
|
assertEquals(expected, actual, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
var break_count = 0;
|
||||||
|
var exception = null;
|
||||||
|
|
||||||
|
function listener(event, exec_state, event_data, data) {
|
||||||
|
if (event != Debug.DebugEvent.Break) return;
|
||||||
|
try {
|
||||||
|
break_count++;
|
||||||
|
var line = exec_state.frame(0).sourceLineText();
|
||||||
|
print(line);
|
||||||
|
assertTrue(line.indexOf(`B${break_count}`) > 0);
|
||||||
|
} catch (e) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function g() {
|
||||||
|
setbreaks();
|
||||||
|
throw 1; // B1
|
||||||
|
}
|
||||||
|
|
||||||
|
async function f() {
|
||||||
|
try {
|
||||||
|
await g();
|
||||||
|
} catch (e) {}
|
||||||
|
return 2; // B2
|
||||||
|
}
|
||||||
|
|
||||||
|
function setbreaks() {
|
||||||
|
Debug.setListener(listener);
|
||||||
|
Debug.setBreakPoint(g, 2);
|
||||||
|
Debug.setBreakPoint(f, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
f();
|
||||||
|
|
||||||
|
%RunMicrotasks();
|
||||||
|
|
||||||
|
assertEqualsAsync(2, async () => break_count);
|
||||||
|
assertEqualsAsync(null, async () => exception);
|
||||||
|
|
||||||
|
Debug.setListener(null);
|
76
test/mjsunit/harmony/debug-async-break.js
Normal file
76
test/mjsunit/harmony/debug-async-break.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2016 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: --expose-debug-as debug
|
||||||
|
// Flags: --harmony-async-await --allow-natives-syntax
|
||||||
|
|
||||||
|
var Debug = debug.Debug;
|
||||||
|
|
||||||
|
function assertEqualsAsync(expected, run, msg) {
|
||||||
|
var actual;
|
||||||
|
var hadValue = false;
|
||||||
|
var hadError = false;
|
||||||
|
var promise = run();
|
||||||
|
|
||||||
|
if (typeof promise !== "object" || typeof promise.then !== "function") {
|
||||||
|
throw new MjsUnitAssertionError(
|
||||||
|
"Expected " + run.toString() +
|
||||||
|
" to return a Promise, but it returned " + promise);
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.then(function(value) { hadValue = true; actual = value; },
|
||||||
|
function(error) { hadError = true; actual = error; });
|
||||||
|
|
||||||
|
assertFalse(hadValue || hadError);
|
||||||
|
|
||||||
|
%RunMicrotasks();
|
||||||
|
|
||||||
|
if (hadError) throw actual;
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
hadValue, "Expected '" + run.toString() + "' to produce a value");
|
||||||
|
|
||||||
|
assertEquals(expected, actual, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
var break_count = 0;
|
||||||
|
var exception = null;
|
||||||
|
|
||||||
|
function listener(event, exec_state, event_data, data) {
|
||||||
|
if (event != Debug.DebugEvent.Break) return;
|
||||||
|
try {
|
||||||
|
break_count++;
|
||||||
|
var line = exec_state.frame(0).sourceLineText();
|
||||||
|
assertTrue(line.indexOf(`B${break_count}`) > 0);
|
||||||
|
} catch (e) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.setListener(listener);
|
||||||
|
|
||||||
|
async function g() {
|
||||||
|
throw 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function f() {
|
||||||
|
try {
|
||||||
|
await g(); // B1
|
||||||
|
} catch (e) {}
|
||||||
|
assertEquals(2, break_count); // B2
|
||||||
|
return 1; // B3
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.setBreakPoint(f, 2);
|
||||||
|
Debug.setBreakPoint(f, 4);
|
||||||
|
Debug.setBreakPoint(f, 5);
|
||||||
|
|
||||||
|
f();
|
||||||
|
|
||||||
|
%RunMicrotasks();
|
||||||
|
|
||||||
|
assertEqualsAsync(3, async () => break_count);
|
||||||
|
assertEqualsAsync(null, async () => exception);
|
||||||
|
|
||||||
|
Debug.setListener(null);
|
@ -23,8 +23,8 @@ PASS x.prototype.__proto__ is Base.prototype
|
|||||||
PASS Object.getPrototypeOf(x.prototype) is Base.prototype
|
PASS Object.getPrototypeOf(x.prototype) is Base.prototype
|
||||||
PASS x = class extends null { constructor() { } }; x.__proto__ is Function.prototype
|
PASS x = class extends null { constructor() { } }; x.__proto__ is Function.prototype
|
||||||
PASS x.__proto__ is Function.prototype
|
PASS x.__proto__ is Function.prototype
|
||||||
PASS x = class extends 3 { constructor() { } }; x.__proto__ threw exception TypeError: Class extends value 3 is not a function or null.
|
PASS x = class extends 3 { constructor() { } }; x.__proto__ threw exception TypeError: Class extends value 3 is not a constructor or null.
|
||||||
PASS x = class extends "abc" { constructor() { } }; x.__proto__ threw exception TypeError: Class extends value abc is not a function or null.
|
PASS x = class extends "abc" { constructor() { } }; x.__proto__ threw exception TypeError: Class extends value abc is not a constructor or null.
|
||||||
PASS baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype did not throw exception.
|
PASS baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype did not throw exception.
|
||||||
PASS x = class extends baseWithBadPrototype { constructor() { } } threw exception TypeError: Class extends value does not have valid prototype property 3.
|
PASS x = class extends baseWithBadPrototype { constructor() { } } threw exception TypeError: Class extends value does not have valid prototype property 3.
|
||||||
PASS baseWithBadPrototype.prototype = "abc" did not throw exception.
|
PASS baseWithBadPrototype.prototype = "abc" did not throw exception.
|
||||||
@ -32,8 +32,8 @@ PASS x = class extends baseWithBadPrototype { constructor() { } } threw exceptio
|
|||||||
PASS baseWithBadPrototype.prototype = null; x = class extends baseWithBadPrototype { constructor() { } } did not throw exception.
|
PASS baseWithBadPrototype.prototype = null; x = class extends baseWithBadPrototype { constructor() { } } did not throw exception.
|
||||||
PASS x = 1; c = class extends ++x { constructor() { } }; threw exception SyntaxError: Unexpected token ++.
|
PASS x = 1; c = class extends ++x { constructor() { } }; threw exception SyntaxError: Unexpected token ++.
|
||||||
PASS x = 1; c = class extends x++ { constructor() { } }; threw exception SyntaxError: Unexpected token ++.
|
PASS x = 1; c = class extends x++ { constructor() { } }; threw exception SyntaxError: Unexpected token ++.
|
||||||
PASS x = 1; c = class extends (++x) { constructor() { } }; threw exception TypeError: Class extends value 2 is not a function or null.
|
PASS x = 1; c = class extends (++x) { constructor() { } }; threw exception TypeError: Class extends value 2 is not a constructor or null.
|
||||||
PASS x = 1; c = class extends (x++) { constructor() { } }; threw exception TypeError: Class extends value 1 is not a function or null.
|
PASS x = 1; c = class extends (x++) { constructor() { } }; threw exception TypeError: Class extends value 1 is not a constructor or null.
|
||||||
PASS x = 1; try { c = class extends (++x) { constructor() { } } } catch (e) { }; x is 2
|
PASS x = 1; try { c = class extends (++x) { constructor() { } } } catch (e) { }; x is 2
|
||||||
PASS x = 1; try { c = class extends (x++) { constructor() { } } } catch (e) { }; x is 2
|
PASS x = 1; try { c = class extends (x++) { constructor() { } } } catch (e) { }; x is 2
|
||||||
PASS namespace = {}; namespace.A = class { }; namespace.B = class extends namespace.A { } did not throw exception.
|
PASS namespace = {}; namespace.A = class { }; namespace.B = class extends namespace.A { } did not throw exception.
|
||||||
@ -47,17 +47,17 @@ PASS namespace = {}; namespace.A = class { constructor() { } }; function getClas
|
|||||||
PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (false||null||namespace.A) { constructor() { } } did not throw exception.
|
PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (false||null||namespace.A) { constructor() { } } did not throw exception.
|
||||||
PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends false||null||namespace.A { constructor() { } } threw exception SyntaxError: Unexpected token ||.
|
PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends false||null||namespace.A { constructor() { } } threw exception SyntaxError: Unexpected token ||.
|
||||||
PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (x++, namespace.A) { constructor() { } }; did not throw exception.
|
PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (x++, namespace.A) { constructor() { } }; did not throw exception.
|
||||||
PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (namespace.A, x++) { constructor() { } }; threw exception TypeError: Class extends value 1 is not a function or null.
|
PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (namespace.A, x++) { constructor() { } }; threw exception TypeError: Class extends value 1 is not a constructor or null.
|
||||||
PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A { constructor() { } } threw exception TypeError: Class extends value [object Object] is not a function or null.
|
PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A { constructor() { } } threw exception TypeError: Class extends value [object Object] is not a constructor or null.
|
||||||
PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A() { constructor() { } } threw exception TypeError: Class extends value [object Object] is not a function or null.
|
PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A() { constructor() { } } threw exception TypeError: Class extends value [object Object] is not a constructor or null.
|
||||||
PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (x++, namespace.A) { constructor() { } } } catch (e) { } x is 2
|
PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (x++, namespace.A) { constructor() { } } } catch (e) { } x is 2
|
||||||
PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (namespace.A, x++) { constructor() { } } } catch (e) { } x is 2
|
PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (namespace.A, x++) { constructor() { } } } catch (e) { } x is 2
|
||||||
PASS Object.getPrototypeOf((class { constructor () { } }).prototype) is Object.prototype
|
PASS Object.getPrototypeOf((class { constructor () { } }).prototype) is Object.prototype
|
||||||
PASS Object.getPrototypeOf((class extends null { constructor () { super(); } }).prototype) is null
|
PASS Object.getPrototypeOf((class extends null { constructor () { super(); } }).prototype) is null
|
||||||
PASS new (class extends undefined { constructor () { this } }) threw exception TypeError: Class extends value undefined is not a function or null.
|
PASS new (class extends undefined { constructor () { this } }) threw exception TypeError: Class extends value undefined is not a constructor or null.
|
||||||
PASS new (class extends undefined { constructor () { super(); } }) threw exception TypeError: Class extends value undefined is not a function or null.
|
PASS new (class extends undefined { constructor () { super(); } }) threw exception TypeError: Class extends value undefined is not a constructor or null.
|
||||||
PASS x = {}; new (class extends undefined { constructor () { return x; } }) threw exception TypeError: Class extends value undefined is not a function or null.
|
PASS x = {}; new (class extends undefined { constructor () { return x; } }) threw exception TypeError: Class extends value undefined is not a constructor or null.
|
||||||
PASS y = 12; new (class extends undefined { constructor () { return y; } }) threw exception TypeError: Class extends value undefined is not a function or null.
|
PASS y = 12; new (class extends undefined { constructor () { return y; } }) threw exception TypeError: Class extends value undefined is not a constructor or null.
|
||||||
PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true
|
PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true
|
||||||
PASS new (class extends null { constructor () { this; } }) threw exception ReferenceError: this is not defined.
|
PASS new (class extends null { constructor () { this; } }) threw exception ReferenceError: this is not defined.
|
||||||
PASS new (class extends null { constructor () { super(); } }) threw exception TypeError: super is not a constructor.
|
PASS new (class extends null { constructor () { super(); } }) threw exception TypeError: super is not a constructor.
|
||||||
|
@ -58,8 +58,8 @@ shouldBe('x.prototype.__proto__', 'Base.prototype');
|
|||||||
shouldBe('Object.getPrototypeOf(x.prototype)', 'Base.prototype');
|
shouldBe('Object.getPrototypeOf(x.prototype)', 'Base.prototype');
|
||||||
shouldBe('x = class extends null { constructor() { } }; x.__proto__', 'Function.prototype');
|
shouldBe('x = class extends null { constructor() { } }; x.__proto__', 'Function.prototype');
|
||||||
shouldBe('x.__proto__', 'Function.prototype');
|
shouldBe('x.__proto__', 'Function.prototype');
|
||||||
shouldThrow('x = class extends 3 { constructor() { } }; x.__proto__', '"TypeError: Class extends value 3 is not a function or null"');
|
shouldThrow('x = class extends 3 { constructor() { } }; x.__proto__', '"TypeError: Class extends value 3 is not a constructor or null"');
|
||||||
shouldThrow('x = class extends "abc" { constructor() { } }; x.__proto__', '"TypeError: Class extends value abc is not a function or null"');
|
shouldThrow('x = class extends "abc" { constructor() { } }; x.__proto__', '"TypeError: Class extends value abc is not a constructor or null"');
|
||||||
shouldNotThrow('baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype');
|
shouldNotThrow('baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype');
|
||||||
shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '"TypeError: Class extends value does not have valid prototype property 3"');
|
shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '"TypeError: Class extends value does not have valid prototype property 3"');
|
||||||
shouldNotThrow('baseWithBadPrototype.prototype = "abc"');
|
shouldNotThrow('baseWithBadPrototype.prototype = "abc"');
|
||||||
@ -92,10 +92,10 @@ shouldBe('x = 1; namespace = {}; namespace.A = class { constructor() { } }; try
|
|||||||
|
|
||||||
shouldBe('Object.getPrototypeOf((class { constructor () { } }).prototype)', 'Object.prototype');
|
shouldBe('Object.getPrototypeOf((class { constructor () { } }).prototype)', 'Object.prototype');
|
||||||
shouldBe('Object.getPrototypeOf((class extends null { constructor () { super(); } }).prototype)', 'null');
|
shouldBe('Object.getPrototypeOf((class extends null { constructor () { super(); } }).prototype)', 'null');
|
||||||
shouldThrow('new (class extends undefined { constructor () { this } })', '"TypeError: Class extends value undefined is not a function or null"');
|
shouldThrow('new (class extends undefined { constructor () { this } })', '"TypeError: Class extends value undefined is not a constructor or null"');
|
||||||
shouldThrow('new (class extends undefined { constructor () { super(); } })', '"TypeError: Class extends value undefined is not a function or null"');
|
shouldThrow('new (class extends undefined { constructor () { super(); } })', '"TypeError: Class extends value undefined is not a constructor or null"');
|
||||||
shouldThrow('x = {}; new (class extends undefined { constructor () { return x; } })', '"TypeError: Class extends value undefined is not a function or null"');
|
shouldThrow('x = {}; new (class extends undefined { constructor () { return x; } })', '"TypeError: Class extends value undefined is not a constructor or null"');
|
||||||
shouldThrow('y = 12; new (class extends undefined { constructor () { return y; } })', '"TypeError: Class extends value undefined is not a function or null"');
|
shouldThrow('y = 12; new (class extends undefined { constructor () { return y; } })', '"TypeError: Class extends value undefined is not a constructor or null"');
|
||||||
shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');
|
shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');
|
||||||
shouldThrow('new (class extends null { constructor () { this; } })', '"ReferenceError: this is not defined"');
|
shouldThrow('new (class extends null { constructor () { this; } })', '"ReferenceError: this is not defined"');
|
||||||
shouldThrow('new (class extends null { constructor () { super(); } })', '"TypeError: super is not a constructor"');
|
shouldThrow('new (class extends null { constructor () { super(); } })', '"TypeError: super is not a constructor"');
|
||||||
|
Loading…
Reference in New Issue
Block a user