Commit 456855a4 authored by Victor Gomes's avatar Victor Gomes Committed by V8 LUCI CQ

[Object.hasOwn] Implementation Object.hasOwn tc39 proposal

Bug: chromium:1213927
Change-Id: I11729540d9f20b437411f0b9f8077be2a7f066b3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2922117Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74850}
parent 8a94daf5
...@@ -718,6 +718,7 @@ namespace internal { ...@@ -718,6 +718,7 @@ namespace internal {
CPP(ObjectGetOwnPropertyDescriptors) \ CPP(ObjectGetOwnPropertyDescriptors) \
TFJ(ObjectGetOwnPropertyNames, 1, kReceiver, kObject) \ TFJ(ObjectGetOwnPropertyNames, 1, kReceiver, kObject) \
CPP(ObjectGetOwnPropertySymbols) \ CPP(ObjectGetOwnPropertySymbols) \
TFJ(ObjectHasOwn, 2, kReceiver, kObject, kKey) \
TFJ(ObjectIs, 2, kReceiver, kLeft, kRight) \ TFJ(ObjectIs, 2, kReceiver, kLeft, kRight) \
CPP(ObjectIsFrozen) \ CPP(ObjectIsFrozen) \
CPP(ObjectIsSealed) \ CPP(ObjectIsSealed) \
......
...@@ -543,6 +543,36 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { ...@@ -543,6 +543,36 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) {
} }
} }
// https://github.com/tc39/proposal-accessible-object-hasownproperty
TF_BUILTIN(ObjectHasOwn, ObjectBuiltinsAssembler) {
// Object.prototype.hasOwnProperty()
// 1. Let obj be ? ToObject(O).
// 2. Let key be ? ToPropertyKey(P).
// 3. Return ? HasOwnProperty(obj, key).
//
// ObjectPrototypeHasOwnProperty has similar semantics with steps 1 and 2
// swapped. We check if ToObject can fail and delegate the rest of the
// execution to ObjectPrototypeHasOwnProperty.
auto target = Parameter<Object>(Descriptor::kJSTarget);
auto new_target = Parameter<Object>(Descriptor::kJSNewTarget);
auto object = Parameter<Object>(Descriptor::kObject);
auto key = Parameter<Object>(Descriptor::kKey);
auto context = Parameter<Context>(Descriptor::kContext);
// ToObject can only fail when object is undefined or null.
Label undefined_or_null(this), not_undefined_nor_null(this);
Branch(IsNullOrUndefined(object), &undefined_or_null,
&not_undefined_nor_null);
BIND(&undefined_or_null);
ThrowTypeError(context, MessageTemplate::kUndefinedOrNullToObject);
BIND(&not_undefined_nor_null);
Return(CallBuiltin(Builtins::kObjectPrototypeHasOwnProperty, context, target,
new_target, Int32Constant(2), object, key));
}
// ES #sec-object.getOwnPropertyNames // ES #sec-object.getOwnPropertyNames
TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) { TF_BUILTIN(ObjectGetOwnPropertyNames, ObjectBuiltinsAssembler) {
auto object = Parameter<Object>(Descriptor::kObject); auto object = Parameter<Object>(Descriptor::kObject);
......
...@@ -1716,6 +1716,7 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) { ...@@ -1716,6 +1716,7 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
case Builtins::kObjectCreate: case Builtins::kObjectCreate:
return Type::OtherObject(); return Type::OtherObject();
case Builtins::kObjectIs: case Builtins::kObjectIs:
case Builtins::kObjectHasOwn:
case Builtins::kObjectPrototypeHasOwnProperty: case Builtins::kObjectPrototypeHasOwnProperty:
case Builtins::kObjectPrototypeIsPrototypeOf: case Builtins::kObjectPrototypeIsPrototypeOf:
return Type::Boolean(); return Type::Boolean();
......
...@@ -542,6 +542,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) { ...@@ -542,6 +542,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
case Builtins::kObjectGetOwnPropertyNames: case Builtins::kObjectGetOwnPropertyNames:
case Builtins::kObjectGetOwnPropertySymbols: case Builtins::kObjectGetOwnPropertySymbols:
case Builtins::kObjectGetPrototypeOf: case Builtins::kObjectGetPrototypeOf:
case Builtins::kObjectHasOwn:
case Builtins::kObjectIs: case Builtins::kObjectIs:
case Builtins::kObjectIsExtensible: case Builtins::kObjectIsExtensible:
case Builtins::kObjectIsFrozen: case Builtins::kObjectIsFrozen:
......
...@@ -287,8 +287,9 @@ DEFINE_BOOL(harmony_shipping, true, "enable all shipped harmony features") ...@@ -287,8 +287,9 @@ DEFINE_BOOL(harmony_shipping, true, "enable all shipped harmony features")
#endif #endif
// Features that are complete (but still behind --harmony/es-staging flag). // Features that are complete (but still behind --harmony/es-staging flag).
#define HARMONY_STAGED_BASE(V) \ #define HARMONY_STAGED_BASE(V) \
V(harmony_class_static_blocks, "harmony static initializer blocks") V(harmony_class_static_blocks, "harmony static initializer blocks") \
V(harmony_object_has_own, "Object.hasOwn")
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#define HARMONY_STAGED(V) \ #define HARMONY_STAGED(V) \
......
...@@ -4439,6 +4439,14 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_more_timezone) ...@@ -4439,6 +4439,14 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_more_timezone)
#undef EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE #undef EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE
void Genesis::InitializeGlobal_harmony_object_has_own() {
if (!FLAG_harmony_object_has_own) return;
Handle<JSFunction> object_function = isolate_->object_function();
SimpleInstallFunction(isolate_, object_function, "hasOwn",
Builtins::kObjectHasOwn, 2, true);
}
void Genesis::InitializeGlobal_harmony_sharedarraybuffer() { void Genesis::InitializeGlobal_harmony_sharedarraybuffer() {
if (!FLAG_harmony_sharedarraybuffer || if (!FLAG_harmony_sharedarraybuffer ||
FLAG_enable_sharedarraybuffer_per_context) { FLAG_enable_sharedarraybuffer_per_context) {
......
// Copyright 2021 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: --harmony-object-has-own
let object = { foo: false };
assertTrue((Object.hasOwn(object, "foo")));
let object2 = Object.create({ foo: true });
assertFalse(Object.hasOwn(object2, "foo"));
let object3 = Object.create(null);
assertFalse(Object.hasOwn(object3, "foo"));
let O = function() {
this.foo = 42;
};
let object8 = new O;
assertTrue((Object.hasOwn(object8, "foo")));
// Object is undefined or null
assertThrows(() => Object.hasOwn(undefined). TypeError);
assertThrows(() => Object.hasOwn(null). TypeError);
// Using defineProperty
let object4 = {};
Object.defineProperty(object4, "foo", {
value: 42
});
assertTrue((Object.hasOwn(object4, "foo")));
// Object.defineProperty with base
let base = {};
Object.defineProperty(base, "foo", {
value: 42,
configurable: true
});
let object5 = Object.create(base);
assertTrue((Object.hasOwn(base, "foo")));
assertFalse((Object.hasOwn(object5, "foo")));
// Prototype with getter and/or setter
let object6 = {
get foo() {}
};
let object7 = {
set foo(x) {}
};
assertTrue((Object.hasOwn(object6, "foo")));
assertTrue((Object.hasOwn(object7, "foo")));
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