[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:
conradw 2015-09-02 04:36:02 -07:00 committed by Commit bot
parent 59cb9c1834
commit db440dfe8d
8 changed files with 43 additions and 52 deletions

View File

@ -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());

View File

@ -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;

View File

@ -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") \

View File

@ -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);

View File

@ -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) \

View File

@ -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);
})();

View 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);

View File

@ -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 {} {});
})();