Implement symbol @@hasInstance for ES6 instanceof support.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#33870}
This commit is contained in:
mvstanton 2016-02-10 06:34:39 -08:00 committed by Commit bot
parent 24b40f35f4
commit 5833e8e8a4
9 changed files with 73 additions and 8 deletions

View File

@ -1148,6 +1148,19 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(prototype, factory->toString_string(),
Builtins::kFunctionPrototypeToString, 0, false);
// Install the @@hasInstance function.
Handle<JSFunction> has_instance = InstallFunction(
prototype, factory->has_instance_symbol(), JS_OBJECT_TYPE,
JSObject::kHeaderSize, MaybeHandle<JSObject>(),
Builtins::kFunctionHasInstance,
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY));
// Set the expected parameters for @@hasInstance to 1; required by builtin.
has_instance->shared()->set_internal_formal_parameter_count(1);
// Set the length for the function to satisfy ECMA-262.
has_instance->shared()->set_length(1);
// Install the "constructor" property on the %FunctionPrototype%.
JSObject::AddProperty(prototype, factory->constructor_string(),
function_fun, DONT_ENUM);
@ -2515,8 +2528,9 @@ void Genesis::InitializeGlobal_harmony_proxies() {
Handle<String> name = factory->Proxy_string();
Handle<Code> code(isolate->builtins()->ProxyConstructor());
Handle<JSFunction> proxy_function = factory->NewFunction(
isolate->proxy_function_map(), factory->Proxy_string(), code);
Handle<JSFunction> proxy_function =
factory->NewFunction(isolate->proxy_function_map(),
factory->Proxy_string(), MaybeHandle<Code>(code));
JSFunction::SetInitialMap(proxy_function,
Handle<Map>(native_context()->proxy_map(), isolate),

View File

@ -3467,6 +3467,45 @@ BUILTIN(GeneratorFunctionConstructor) {
return *result;
}
// ES6 section 19.2.3.6 Function.prototype[@@hasInstance](V)
BUILTIN(FunctionHasInstance) {
HandleScope scope(isolate);
Handle<Object> callable = args.receiver();
Handle<Object> object = args.atOrUndefined(isolate, 1);
// {callable} must have a [[Call]] internal method.
if (!callable->IsCallable()) {
return isolate->heap()->false_value();
}
// If {object} is not a receiver, return false.
if (!object->IsJSReceiver()) {
return isolate->heap()->false_value();
}
// Check if {callable} is bound, if so, get [[BoundTargetFunction]] from it
// and use that instead of {callable}.
while (callable->IsJSBoundFunction()) {
callable =
handle(Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
isolate);
}
DCHECK(callable->IsCallable());
// Get the "prototype" of {callable}; raise an error if it's not a receiver.
Handle<Object> prototype;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, prototype,
Object::GetProperty(callable, isolate->factory()->prototype_string()));
if (!prototype->IsJSReceiver()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype));
}
// Return whether or not {prototype} is in the prototype chain of {object}.
Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
Maybe<bool> result =
JSReceiver::HasInPrototypeChain(isolate, receiver, prototype);
MAYBE_RETURN(result, isolate->heap()->exception());
return isolate->heap()->ToBoolean(result.FromJust());
}
// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
BUILTIN(SymbolConstructor) {

View File

@ -102,6 +102,7 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
V(FunctionConstructor, kTargetAndNewTarget) \
V(FunctionPrototypeBind, kNone) \
V(FunctionPrototypeToString, kNone) \
V(FunctionHasInstance, kNone) \
\
V(GeneratorFunctionConstructor, kTargetAndNewTarget) \
\

View File

@ -181,7 +181,6 @@
V(uninitialized_symbol)
#define PUBLIC_SYMBOL_LIST(V) \
V(has_instance_symbol, Symbol.hasInstance) \
V(iterator_symbol, Symbol.iterator) \
V(match_symbol, Symbol.match) \
V(replace_symbol, Symbol.replace) \
@ -196,6 +195,7 @@
// check. Because this behaviour is not specified properly as of yet, it only
// applies to a subset of spec-defined Well-Known Symbols.
#define WELL_KNOWN_SYMBOL_LIST(V) \
V(has_instance_symbol, Symbol.hasInstance) \
V(is_concat_spreadable_symbol, Symbol.isConcatSpreadable) \
V(to_string_tag_symbol, Symbol.toStringTag)

View File

@ -75,8 +75,7 @@ function SymbolKeyFor(symbol) {
// -------------------------------------------------------------------
utils.InstallConstants(GlobalSymbol, [
// TODO(rossberg): expose when implemented.
// "hasInstance", hasInstanceSymbol,
"hasInstance", hasInstanceSymbol,
"isConcatSpreadable", isConcatSpreadableSymbol,
"iterator", iteratorSymbol,
// TODO(yangguo): expose when implemented.

View File

@ -695,6 +695,7 @@
'test-serialize/SerializeInternalReference': [PASS, FAIL],
'test-spaces/SizeOfFirstPageIsLargeEnough': [PASS, FAIL],
'test-api/InitializeDefaultIsolateOnSecondaryThread1': [PASS, FAIL],
'test-api/FastReturnValuesWithProfiler': [PASS, FAIL],
'test-heap/Regress538257': [PASS, FAIL],
'test-heap/AddInstructionChangesNewSpacePromotion': [PASS, FAIL],
'test-decls/CrossScriptReferencesHarmony': [PASS, FAIL],

View File

@ -0,0 +1,12 @@
// 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.
// Verify that the hasInstance symbol is installed on function prototype.
// Test262 makes deeper tests.
(function TestHasInstance() {
var a = Array();
assertTrue(Array[Symbol.hasInstance](a));
assertFalse(Function.prototype[Symbol.hasInstance].call());
})();

View File

@ -441,8 +441,9 @@ TestGetOwnPropertySymbolsWithProto()
function TestWellKnown() {
var symbols = [
"hasInstance",
// TODO(rossberg): reactivate once implemented.
// "hasInstance", "isConcatSpreadable", "isRegExp",
// "isConcatSpreadable", "isRegExp",
"iterator", /* "toStringTag", */ "unscopables"
]

View File

@ -256,8 +256,6 @@
'intl402/Collator/10.1.1_a': [FAIL],
# https://code.google.com/p/v8/issues/detail?id=4447
'built-ins/Function/prototype/Symbol.hasInstance/*': [SKIP],
'built-ins/Symbol/hasInstance/prop-desc': [FAIL],
'language/expressions/instanceof/prototype-getter-with-object-throws': [FAIL],
'language/expressions/instanceof/prototype-getter-with-object': [FAIL],
'language/expressions/instanceof/primitive-prototype-with-object': [FAIL],