[strong] weak classes can't inherit from strong ones
Prerequisite for sealing strong class instances. Depends on https://codereview.chromium.org/1314203002/ BUG=v8:3956 LOG=N Review URL: https://codereview.chromium.org/1316333002 Cr-Commit-Position: refs/heads/master@{#30541}
This commit is contained in:
parent
59cb9c1834
commit
db440dfe8d
@ -1564,10 +1564,7 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
|
||||
Node* name = environment()->Pop();
|
||||
Node* start = jsgraph()->Constant(expr->start_position());
|
||||
Node* end = jsgraph()->Constant(expr->end_position());
|
||||
const Operator* opc = javascript()->CallRuntime(
|
||||
is_strong(language_mode()) ? Runtime::kDefineClassStrong
|
||||
: Runtime::kDefineClass,
|
||||
5);
|
||||
const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass, 5);
|
||||
Node* literal = NewNode(opc, name, extends, constructor, start, end);
|
||||
PrepareFrameState(literal, expr->CreateLiteralId(),
|
||||
OutputFrameStateCombine::Push());
|
||||
|
@ -1297,9 +1297,7 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
|
||||
__ Push(Smi::FromInt(lit->start_position()));
|
||||
__ Push(Smi::FromInt(lit->end_position()));
|
||||
|
||||
__ CallRuntime(is_strong(language_mode()) ? Runtime::kDefineClassStrong
|
||||
: Runtime::kDefineClass,
|
||||
5);
|
||||
__ CallRuntime(Runtime::kDefineClass, 5);
|
||||
PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG);
|
||||
|
||||
int store_slot_index = 0;
|
||||
|
@ -225,6 +225,7 @@ class CallSite {
|
||||
"to be non-writable is deprecated") \
|
||||
T(StrongSetProto, \
|
||||
"On strong object %, redefining the internal prototype is deprecated") \
|
||||
T(StrongWeakExtend, "Non-strong class % cannot extend a strong object") \
|
||||
T(SymbolKeyFor, "% is not a symbol") \
|
||||
T(SymbolToNumber, "Cannot convert a Symbol value to a number") \
|
||||
T(SymbolToString, "Cannot convert a Symbol value to a string") \
|
||||
|
@ -138,6 +138,18 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name,
|
||||
isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
|
||||
if (constructor->map()->is_strong()) {
|
||||
map->set_is_strong();
|
||||
if (super_class->IsNull()) {
|
||||
// Strong class is not permitted to extend null.
|
||||
THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kStrongExtendNull),
|
||||
Object);
|
||||
}
|
||||
} else {
|
||||
if (Handle<HeapObject>::cast(super_class)->map()->is_strong()) {
|
||||
// Weak class is not permitted to extend strong class.
|
||||
THROW_NEW_ERROR(isolate,
|
||||
NewTypeError(MessageTemplate::kStrongWeakExtend, name),
|
||||
Object);
|
||||
}
|
||||
}
|
||||
Map::SetPrototype(map, prototype_parent);
|
||||
map->SetConstructor(*constructor);
|
||||
@ -212,28 +224,6 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_DefineClassStrong) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 5);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
|
||||
CONVERT_SMI_ARG_CHECKED(start_position, 3);
|
||||
CONVERT_SMI_ARG_CHECKED(end_position, 4);
|
||||
|
||||
if (super_class->IsNull()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kStrongExtendNull));
|
||||
}
|
||||
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result, DefineClass(isolate, name, super_class, constructor,
|
||||
start_position, end_position));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_DefineClassMethod) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
|
@ -84,7 +84,6 @@ namespace internal {
|
||||
F(ToMethod, 2, 1) \
|
||||
F(HomeObjectSymbol, 0, 1) \
|
||||
F(DefineClass, 5, 1) \
|
||||
F(DefineClassStrong, 5, 1) \
|
||||
F(FinalizeClassDefinition, 2, 1) \
|
||||
F(DefineClassMethod, 3, 1) \
|
||||
F(ClassGetSourceCode, 1, 1) \
|
||||
|
@ -79,20 +79,3 @@ testStrongClass(getClassExprStrong);
|
||||
assertDoesNotThrow(function(){addProperty(parent)});
|
||||
assertDoesNotThrow(function(){convertPropertyToData(parent)});
|
||||
})();
|
||||
|
||||
// Check strong classes don't freeze their children.
|
||||
(function() {
|
||||
let parent = getClassStrong();
|
||||
|
||||
let classFunc = function() {
|
||||
class Foo extends parent {
|
||||
static get bar() { return 0 }
|
||||
get bar() { return 0 }
|
||||
}
|
||||
return Foo;
|
||||
}
|
||||
|
||||
assertThrows(function(){addProperty(parent)}, TypeError);
|
||||
assertThrows(function(){convertPropertyToData(parent)}, TypeError);
|
||||
testWeakClass(classFunc);
|
||||
})();
|
||||
|
28
test/mjsunit/strong/class-weak-extend.js
Normal file
28
test/mjsunit/strong/class-weak-extend.js
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2015 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: --strong-mode --allow-natives-syntax
|
||||
|
||||
function getStrongClass() {
|
||||
"use strong";
|
||||
return (class {});
|
||||
}
|
||||
|
||||
function weakClass() {
|
||||
"use strict";
|
||||
class Weak extends getStrongClass() {}
|
||||
}
|
||||
|
||||
function strongClass() {
|
||||
"use strong";
|
||||
class Strong extends getStrongClass() {}
|
||||
}
|
||||
|
||||
assertThrows(weakClass, TypeError);
|
||||
%OptimizeFunctionOnNextCall(weakClass);
|
||||
assertThrows(weakClass, TypeError);
|
||||
|
||||
assertDoesNotThrow(strongClass);
|
||||
%OptimizeFunctionOnNextCall(strongClass);
|
||||
assertDoesNotThrow(strongClass);
|
@ -285,24 +285,19 @@ let GeneratorPrototype = (function*(){}).__proto__;
|
||||
class D extends C {};
|
||||
class E extends Object {};
|
||||
// class F extends null {};
|
||||
const S = (() => {'use strong'; return class {}})();
|
||||
class G extends S {};
|
||||
assertWeakClass(C);
|
||||
assertWeakClass(D);
|
||||
assertWeakClass(E);
|
||||
// assertWeakClass(F);
|
||||
assertWeakClass(G);
|
||||
assertWeakClass(class {});
|
||||
assertWeakClass(class extends Object {});
|
||||
// assertWeakClass(class extends null {});
|
||||
assertWeakClass(class extends C {});
|
||||
assertWeakClass(class extends S {});
|
||||
assertWeakClass(class extends class {} {});
|
||||
assertWeakClass(class C {});
|
||||
assertWeakClass(class D extends Object {});
|
||||
// assertWeakClass(class D extends null {});
|
||||
assertWeakClass(class D extends C {});
|
||||
assertWeakClass(class D extends S {});
|
||||
assertWeakClass(class D extends class {} {});
|
||||
})();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user