[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>();
|
||||
}
|
||||
|
||||
// TODO(4280): For now we do not switch generators to baseline code because
|
||||
// there might be suspended activations stored in generator objects on the
|
||||
// heap. We could eventually go directly to TurboFan in this case.
|
||||
if (function->shared()->is_generator()) {
|
||||
// TODO(4280): For now we do not switch generators or async functions to
|
||||
// baseline code because there might be suspended activations stored in
|
||||
// generator objects on the heap. We could eventually go directly to
|
||||
// TurboFan in this case.
|
||||
if (function->shared()->is_resumable()) {
|
||||
return MaybeHandle<Code>();
|
||||
}
|
||||
|
||||
@ -1308,10 +1309,11 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
|
||||
CompilationInfo unoptimized(info->parse_info(), info->closure());
|
||||
unoptimized.EnableDeoptimizationSupport();
|
||||
|
||||
// TODO(4280): For now we do not switch generators to baseline code because
|
||||
// there might be suspended activations stored in generator objects on the
|
||||
// heap. We could eventually go directly to TurboFan in this case.
|
||||
if (shared->is_generator()) return false;
|
||||
// TODO(4280): For now we do not switch generators or async functions to
|
||||
// baseline code because there might be suspended activations stored in
|
||||
// generator objects on the heap. We could eventually go directly to
|
||||
// TurboFan in this case.
|
||||
if (shared->is_resumable()) return false;
|
||||
|
||||
// TODO(4280): For now we disable switching to baseline code in the presence
|
||||
// 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.
|
||||
HeapIterator iterator(isolate_->heap());
|
||||
HeapObject* obj;
|
||||
bool include_generators = !is_interpreted && shared->is_generator();
|
||||
bool find_resumables = !is_interpreted && shared->is_resumable();
|
||||
|
||||
while ((obj = iterator.next())) {
|
||||
if (obj->IsJSFunction()) {
|
||||
@ -1336,7 +1336,9 @@ bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
|
||||
}
|
||||
if (is_interpreted) continue;
|
||||
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);
|
||||
if (!generator_obj->is_suspended()) continue;
|
||||
JSFunction* function = generator_obj->function();
|
||||
|
@ -1680,7 +1680,7 @@ static const char* DropActivationsInActiveThreadImpl(Isolate* isolate,
|
||||
if (frame->is_java_script()) {
|
||||
SharedFunctionInfo* shared =
|
||||
JavaScriptFrame::cast(frame)->function()->shared();
|
||||
if (shared->is_generator()) {
|
||||
if (shared->is_resumable()) {
|
||||
non_droppable_frame_found = true;
|
||||
non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
|
||||
break;
|
||||
|
@ -1298,7 +1298,10 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code,
|
||||
ElementsKind elements_kind =
|
||||
type == JS_ARRAY_TYPE ? FAST_SMI_ELEMENTS : FAST_HOLEY_SMI_ELEMENTS;
|
||||
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()) {
|
||||
prototype = NewFunctionPrototype(function);
|
||||
} else if (install_constructor) {
|
||||
@ -1327,11 +1330,12 @@ Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
|
||||
// can be from a different context.
|
||||
Handle<Context> native_context(function->context()->native_context());
|
||||
Handle<Map> new_map;
|
||||
if (function->shared()->is_generator()) {
|
||||
// Generator prototypes can share maps since they don't have "constructor"
|
||||
// properties.
|
||||
if (function->shared()->is_resumable()) {
|
||||
// Generator and async function prototypes can share maps since they
|
||||
// don't have "constructor" properties.
|
||||
new_map = handle(native_context->generator_object_prototype_map());
|
||||
} else {
|
||||
CHECK(!function->shared()->is_async());
|
||||
// Each function prototype gets a fresh map to avoid unwanted sharing of
|
||||
// maps between prototypes of different constructors.
|
||||
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());
|
||||
Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
|
||||
|
||||
if (!function->shared()->is_generator()) {
|
||||
if (!function->shared()->is_resumable()) {
|
||||
JSObject::AddProperty(prototype, constructor_string(), function, DONT_ENUM);
|
||||
}
|
||||
|
||||
|
@ -121,10 +121,8 @@ class CallSite {
|
||||
T(DefineDisallowed, "Cannot define property:%, object is not extensible.") \
|
||||
T(DetachedOperation, "Cannot perform % on a detached ArrayBuffer") \
|
||||
T(DuplicateTemplateProperty, "Object template has duplicate property '%'") \
|
||||
T(ExtendsValueGenerator, \
|
||||
"Class extends value % may not be a generator function") \
|
||||
T(ExtendsValueNotFunction, \
|
||||
"Class extends value % is not a function or null") \
|
||||
T(ExtendsValueNotConstructor, \
|
||||
"Class extends value % is not a constructor or null") \
|
||||
T(FirstArgumentNotRegExp, \
|
||||
"First argument to % must not be a regular expression") \
|
||||
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();
|
||||
if (shared()->is_generator()) {
|
||||
os << "\n - generator";
|
||||
} else if (shared()->is_async()) {
|
||||
os << "\n - async";
|
||||
}
|
||||
os << "\n - context = " << Brief(context());
|
||||
os << "\n - literals = " << Brief(literals());
|
||||
|
@ -94,13 +94,8 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate,
|
||||
if (super_class->IsNull()) {
|
||||
prototype_parent = isolate->factory()->null_value();
|
||||
} else if (super_class->IsConstructor()) {
|
||||
if (super_class->IsJSFunction() &&
|
||||
Handle<JSFunction>::cast(super_class)->shared()->is_generator()) {
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class),
|
||||
Object);
|
||||
}
|
||||
DCHECK(!super_class->IsJSFunction() ||
|
||||
!Handle<JSFunction>::cast(super_class)->shared()->is_resumable());
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, prototype_parent,
|
||||
Runtime::GetObjectProperty(isolate, super_class,
|
||||
@ -114,9 +109,9 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate,
|
||||
}
|
||||
constructor_parent = super_class;
|
||||
} else {
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class),
|
||||
THROW_NEW_ERROR(isolate,
|
||||
NewTypeError(MessageTemplate::kExtendsValueNotConstructor,
|
||||
super_class),
|
||||
Object);
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(12),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(128),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(13),
|
||||
@ -236,7 +236,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(13),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(128),
|
||||
B(Star), R(13),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(14),
|
||||
@ -393,7 +393,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(12),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(128),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(13),
|
||||
@ -540,7 +540,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(11),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(128),
|
||||
B(Star), R(11),
|
||||
B(LdaConstant), U8(10),
|
||||
B(Star), R(12),
|
||||
|
@ -480,7 +480,7 @@ bytecodes: [
|
||||
B(TestEqualStrict), R(10),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), U16(129),
|
||||
B(Wide), B(LdaSmi), U16(128),
|
||||
B(Star), R(10),
|
||||
B(LdaConstant), U8(14),
|
||||
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() { } }
|
||||
assertEquals("async foo() { }", Function.prototype.toString.call(AsyncMethod.prototype.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 x = class extends null { constructor() { } }; 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 "abc" { constructor() { } }; x.__proto__ threw exception TypeError: Class extends value abc 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 constructor or null.
|
||||
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 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 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 1 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 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 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() { } } 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 (namespace.A, x++) { constructor() { } }; threw exception TypeError: Class extends value 1 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 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 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 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 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 (namespace.A, x++) { constructor() { } } } catch (e) { } x is 2
|
||||
PASS Object.getPrototypeOf((class { constructor () { } }).prototype) is Object.prototype
|
||||
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 () { super(); } }) 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 function 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 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 constructor 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 constructor or null.
|
||||
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 () { 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('x = class extends null { constructor() { } }; 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 "abc" { constructor() { } }; x.__proto__', '"TypeError: Class extends value abc 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 constructor or null"');
|
||||
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"');
|
||||
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 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 () { super(); } })', '"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 function or null"');
|
||||
shouldThrow('y = 12; new (class extends undefined { constructor () { return y; } })', '"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 constructor 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 constructor or null"');
|
||||
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 () { super(); } })', '"TypeError: super is not a constructor"');
|
||||
|
Loading…
Reference in New Issue
Block a user