Commit 2f981db0 authored by conradw's avatar conradw Committed by Commit bot

[strong] Strong classes can't extend null

BUG=v8:3956
LOG=N

Review URL: https://codereview.chromium.org/1235883002

Cr-Commit-Position: refs/heads/master@{#29606}
parent 0a3b7739
...@@ -1562,7 +1562,10 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) { ...@@ -1562,7 +1562,10 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
Node* script = jsgraph()->Constant(info()->script()); Node* script = jsgraph()->Constant(info()->script());
Node* start = jsgraph()->Constant(expr->start_position()); Node* start = jsgraph()->Constant(expr->start_position());
Node* end = jsgraph()->Constant(expr->end_position()); Node* end = jsgraph()->Constant(expr->end_position());
const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass, 6); const Operator* opc = javascript()->CallRuntime(
is_strong(language_mode()) ? Runtime::kDefineClassStrong
: Runtime::kDefineClass,
6);
Node* literal = NewNode(opc, name, extends, constructor, script, start, end); Node* literal = NewNode(opc, name, extends, constructor, script, start, end);
PrepareFrameState(literal, expr->CreateLiteralId(), PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push()); OutputFrameStateCombine::Push());
......
...@@ -1184,7 +1184,9 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) { ...@@ -1184,7 +1184,9 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
__ Push(Smi::FromInt(lit->start_position())); __ Push(Smi::FromInt(lit->start_position()));
__ Push(Smi::FromInt(lit->end_position())); __ Push(Smi::FromInt(lit->end_position()));
__ CallRuntime(Runtime::kDefineClass, 6); __ CallRuntime(is_strong(language_mode()) ? Runtime::kDefineClassStrong
: Runtime::kDefineClass,
6);
PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG); PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG);
int store_slot_index = 0; int store_slot_index = 0;
......
...@@ -230,6 +230,7 @@ class CallSite { ...@@ -230,6 +230,7 @@ class CallSite {
"In strong mode, calling a function with too few arguments is deprecated") \ "In strong mode, calling a function with too few arguments is deprecated") \
T(StrongDeleteProperty, \ T(StrongDeleteProperty, \
"Deleting property '%' of strong object '%' is deprecated") \ "Deleting property '%' of strong object '%' is deprecated") \
T(StrongExtendNull, "In strong mode, classes extending null are deprecated") \
T(StrongImplicitConversion, \ T(StrongImplicitConversion, \
"In strong mode, implicit conversions are deprecated") \ "In strong mode, implicit conversions are deprecated") \
T(StrongRedefineDisallowed, \ T(StrongRedefineDisallowed, \
......
...@@ -93,16 +93,11 @@ RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) { ...@@ -93,16 +93,11 @@ RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
} }
RUNTIME_FUNCTION(Runtime_DefineClass) { static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name,
HandleScope scope(isolate); Handle<Object> super_class,
DCHECK(args.length() == 6); Handle<JSFunction> constructor,
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0); Handle<Script> script,
CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1); int start_position, int end_position) {
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
CONVERT_ARG_HANDLE_CHECKED(Script, script, 3);
CONVERT_SMI_ARG_CHECKED(start_position, 4);
CONVERT_SMI_ARG_CHECKED(end_position, 5);
Handle<Object> prototype_parent; Handle<Object> prototype_parent;
Handle<Object> constructor_parent; Handle<Object> constructor_parent;
...@@ -113,26 +108,30 @@ RUNTIME_FUNCTION(Runtime_DefineClass) { ...@@ -113,26 +108,30 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
prototype_parent = isolate->factory()->null_value(); prototype_parent = isolate->factory()->null_value();
} else if (super_class->IsSpecFunction()) { } else if (super_class->IsSpecFunction()) {
if (Handle<JSFunction>::cast(super_class)->shared()->is_generator()) { if (Handle<JSFunction>::cast(super_class)->shared()->is_generator()) {
THROW_NEW_ERROR_RETURN_FAILURE( THROW_NEW_ERROR(
isolate, isolate,
NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class)); NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class),
Object);
} }
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( ASSIGN_RETURN_ON_EXCEPTION(
isolate, prototype_parent, isolate, prototype_parent,
Runtime::GetObjectProperty(isolate, super_class, Runtime::GetObjectProperty(isolate, super_class,
isolate->factory()->prototype_string(), isolate->factory()->prototype_string(),
SLOPPY)); SLOPPY),
Object);
if (!prototype_parent->IsNull() && !prototype_parent->IsSpecObject()) { if (!prototype_parent->IsNull() && !prototype_parent->IsSpecObject()) {
THROW_NEW_ERROR_RETURN_FAILURE( THROW_NEW_ERROR(
isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject, isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
prototype_parent)); prototype_parent),
Object);
} }
constructor_parent = super_class; constructor_parent = super_class;
} else { } else {
// TODO(arv): Should be IsConstructor. // TODO(arv): Should be IsConstructor.
THROW_NEW_ERROR_RETURN_FAILURE( THROW_NEW_ERROR(
isolate, isolate,
NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class)); NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class),
Object);
} }
} }
...@@ -155,42 +154,88 @@ RUNTIME_FUNCTION(Runtime_DefineClass) { ...@@ -155,42 +154,88 @@ RUNTIME_FUNCTION(Runtime_DefineClass) {
JSFunction::SetPrototype(constructor, prototype); JSFunction::SetPrototype(constructor, prototype);
PropertyAttributes attribs = PropertyAttributes attribs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
RETURN_FAILURE_ON_EXCEPTION( RETURN_ON_EXCEPTION(isolate,
isolate, JSObject::SetOwnPropertyIgnoreAttributes( JSObject::SetOwnPropertyIgnoreAttributes(
constructor, isolate->factory()->prototype_string(), constructor, isolate->factory()->prototype_string(),
prototype, attribs)); prototype, attribs),
Object);
// TODO(arv): Only do this conditionally. // TODO(arv): Only do this conditionally.
Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol()); Handle<Symbol> home_object_symbol(isolate->heap()->home_object_symbol());
RETURN_FAILURE_ON_EXCEPTION( RETURN_ON_EXCEPTION(
isolate, JSObject::SetOwnPropertyIgnoreAttributes( isolate, JSObject::SetOwnPropertyIgnoreAttributes(
constructor, home_object_symbol, prototype, DONT_ENUM)); constructor, home_object_symbol, prototype, DONT_ENUM),
Object);
if (!constructor_parent.is_null()) { if (!constructor_parent.is_null()) {
RETURN_FAILURE_ON_EXCEPTION( RETURN_ON_EXCEPTION(
isolate, isolate, JSObject::SetPrototype(constructor, constructor_parent, false),
JSObject::SetPrototype(constructor, constructor_parent, false)); Object);
} }
JSObject::AddProperty(prototype, isolate->factory()->constructor_string(), JSObject::AddProperty(prototype, isolate->factory()->constructor_string(),
constructor, DONT_ENUM); constructor, DONT_ENUM);
// Install private properties that are used to construct the FunctionToString. // Install private properties that are used to construct the FunctionToString.
RETURN_FAILURE_ON_EXCEPTION( RETURN_ON_EXCEPTION(
isolate, Object::SetProperty(constructor, isolate, Object::SetProperty(constructor,
isolate->factory()->class_script_symbol(), isolate->factory()->class_script_symbol(),
script, STRICT)); script, STRICT),
RETURN_FAILURE_ON_EXCEPTION( Object);
RETURN_ON_EXCEPTION(
isolate, isolate,
Object::SetProperty( Object::SetProperty(
constructor, isolate->factory()->class_start_position_symbol(), constructor, isolate->factory()->class_start_position_symbol(),
handle(Smi::FromInt(start_position), isolate), STRICT)); handle(Smi::FromInt(start_position), isolate), STRICT),
RETURN_FAILURE_ON_EXCEPTION( Object);
RETURN_ON_EXCEPTION(
isolate, Object::SetProperty( isolate, Object::SetProperty(
constructor, isolate->factory()->class_end_position_symbol(), constructor, isolate->factory()->class_end_position_symbol(),
handle(Smi::FromInt(end_position), isolate), STRICT)); handle(Smi::FromInt(end_position), isolate), STRICT),
Object);
return constructor;
}
RUNTIME_FUNCTION(Runtime_DefineClass) {
HandleScope scope(isolate);
DCHECK(args.length() == 6);
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
CONVERT_ARG_HANDLE_CHECKED(Script, script, 3);
CONVERT_SMI_ARG_CHECKED(start_position, 4);
CONVERT_SMI_ARG_CHECKED(end_position, 5);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, DefineClass(isolate, name, super_class, constructor,
script, start_position, end_position));
return *result;
}
RUNTIME_FUNCTION(Runtime_DefineClassStrong) {
HandleScope scope(isolate);
DCHECK(args.length() == 6);
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
CONVERT_ARG_HANDLE_CHECKED(Script, script, 3);
CONVERT_SMI_ARG_CHECKED(start_position, 4);
CONVERT_SMI_ARG_CHECKED(end_position, 5);
return *constructor; 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,
script, start_position, end_position));
return *result;
} }
......
...@@ -76,6 +76,7 @@ namespace internal { ...@@ -76,6 +76,7 @@ namespace internal {
F(ToMethod, 2, 1) \ F(ToMethod, 2, 1) \
F(HomeObjectSymbol, 0, 1) \ F(HomeObjectSymbol, 0, 1) \
F(DefineClass, 6, 1) \ F(DefineClass, 6, 1) \
F(DefineClassStrong, 6, 1) \
F(DefineClassMethod, 3, 1) \ F(DefineClassMethod, 3, 1) \
F(ClassGetSourceCode, 1, 1) \ F(ClassGetSourceCode, 1, 1) \
F(LoadFromSuper, 4, 1) \ F(LoadFromSuper, 4, 1) \
......
// 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() {
"use strict";
let foo = null;
function nullLiteral() {
class Class1 extends null {
constructor() {
super();
}
}
}
function nullVariable() {
class Class2 extends foo {
constructor() {
super();
}
}
}
function nullLiteralClassExpr() {
(class extends null {});
}
function nullVariableClassExpr() {
(class extends foo {});
}
assertDoesNotThrow(nullLiteral);
%OptimizeFunctionOnNextCall(nullLiteral);
assertDoesNotThrow(nullLiteral);
assertDoesNotThrow(nullVariable);
%OptimizeFunctionOnNextCall(nullVariable);
assertDoesNotThrow(nullVariable);
assertDoesNotThrow(nullLiteralClassExpr);
%OptimizeFunctionOnNextCall(nullLiteralClassExpr);
assertDoesNotThrow(nullLiteralClassExpr);
assertDoesNotThrow(nullVariableClassExpr);
%OptimizeFunctionOnNextCall(nullVariableClassExpr);
assertDoesNotThrow(nullVariableClassExpr);
})();
(function() {
"use strong";
let foo = null;
function nullLiteral() {
class Class1 extends null {
constructor() {
super();
}
}
}
function nullVariable() {
class Class2 extends foo {
constructor() {
super();
}
}
}
function nullLiteralClassExpr() {
(class extends null {});
}
function nullVariableClassExpr() {
(class extends foo {});
}
assertThrows(nullLiteral, TypeError);
%OptimizeFunctionOnNextCall(nullLiteral);
assertThrows(nullLiteral, TypeError);
assertThrows(nullVariable, TypeError);
%OptimizeFunctionOnNextCall(nullVariable);
assertThrows(nullVariable, TypeError);
assertThrows(nullLiteralClassExpr, TypeError);
%OptimizeFunctionOnNextCall(nullLiteralClassExpr);
assertThrows(nullLiteralClassExpr, TypeError);
assertThrows(nullVariableClassExpr, TypeError);
%OptimizeFunctionOnNextCall(nullVariableClassExpr);
assertThrows(nullVariableClassExpr, TypeError);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment