Skip to content

Commit

Permalink
Implement Object.hasOwn
Browse files Browse the repository at this point in the history
Summary: Implement `hasOwn` according to the language specs [here](https://tc39.es/proposal-accessible-object-hasownproperty/).

Reviewed By: avp

Differential Revision: D32287266

fbshipit-source-id: 22a8520adfa09a193696a68459c475005a29b752
  • Loading branch information
fbmal7 authored and facebook-github-bot committed Nov 12, 2021
1 parent a725c6e commit 9261a72
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 18 deletions.
1 change: 1 addition & 0 deletions include/hermes/VM/NativeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ NATIVE_FUNCTION(objectGetOwnPropertyDescriptors)
NATIVE_FUNCTION(objectGetOwnPropertyNames)
NATIVE_FUNCTION(objectGetOwnPropertySymbols)
NATIVE_FUNCTION(objectGetPrototypeOf)
NATIVE_FUNCTION(objectHasOwn)
NATIVE_FUNCTION(objectIs)
NATIVE_FUNCTION(objectIsExtensible)
NATIVE_FUNCTION(objectIsFrozen)
Expand Down
1 change: 1 addition & 0 deletions include/hermes/VM/PredefinedStrings.def
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ STR(toString, "toString")
STR(description, "description")
STR(toLocaleString, "toLocaleString")
STR(hasOwnProperty, "hasOwnProperty")
STR(hasOwn, "hasOwn")
STR(isPrototypeOf, "isPrototypeOf")
STR(propertyIsEnumerable, "propertyIsEnumerable")
STR(valueOf, "valueOf")
Expand Down
64 changes: 46 additions & 18 deletions lib/VM/JSLib/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ Handle<JSObject> createObjectConstructor(Runtime *runtime) {
ctx,
objectGetOwnPropertySymbols,
1);
defineMethod(
runtime,
cons,
Predefined::getSymbolID(Predefined::hasOwn),
ctx,
objectHasOwn,
1);
defineMethod(
runtime,
cons,
Expand Down Expand Up @@ -1262,24 +1269,8 @@ objectPrototypeValueOf(void *, Runtime *runtime, NativeArgs args) {
return res;
}

/// ES11.0 19.1.3.2
CallResult<HermesValue>
objectPrototypeHasOwnProperty(void *, Runtime *runtime, NativeArgs args) {
/// 1. Let P be ? ToPropertyKey(V).
auto PRes = toPropertyKey(runtime, args.getArgHandle(0));
if (LLVM_UNLIKELY(PRes == ExecutionStatus::EXCEPTION)) {
return ExecutionStatus::EXCEPTION;
}
Handle<> P = *PRes;

/// 2. Let O be ? ToObject(this value).
auto ORes = toObject(runtime, args.getThisHandle());
if (LLVM_UNLIKELY(ORes == ExecutionStatus::EXCEPTION)) {
return ExecutionStatus::EXCEPTION;
}
Handle<JSObject> O = runtime->makeHandle<JSObject>(ORes.getValue());

/// 3. Return ? HasOwnProperty(O, P).
static CallResult<HermesValue>
objectHasOwnHelper(Runtime *runtime, Handle<JSObject> O, Handle<> P) {
ComputedPropertyDescriptor desc;
MutableHandle<SymbolID> tmpPropNameStorage{runtime};
CallResult<bool> hasProp = JSObject::getOwnComputedDescriptor(
Expand All @@ -1306,6 +1297,43 @@ objectPrototypeHasOwnProperty(void *, Runtime *runtime, NativeArgs args) {
return HermesValue::encodeBoolValue(false);
}

/// ES11.0 19.1.3.2
CallResult<HermesValue>
objectPrototypeHasOwnProperty(void *, Runtime *runtime, NativeArgs args) {
/// 1. Let P be ? ToPropertyKey(V).
auto PRes = toPropertyKey(runtime, args.getArgHandle(0));
if (LLVM_UNLIKELY(PRes == ExecutionStatus::EXCEPTION)) {
return ExecutionStatus::EXCEPTION;
}

/// 2. Let O be ? ToObject(this value).
auto ORes = toObject(runtime, args.getThisHandle());
if (LLVM_UNLIKELY(ORes == ExecutionStatus::EXCEPTION)) {
return ExecutionStatus::EXCEPTION;
}
/// 3. Return ? HasOwnProperty(O, P).
Handle<JSObject> O = runtime->makeHandle<JSObject>(ORes.getValue());
return objectHasOwnHelper(runtime, O, *PRes);
}

CallResult<HermesValue>
objectHasOwn(void *, Runtime *runtime, NativeArgs args) {
/// 1. Let O be ? ToObject(O).
auto ORes = toObject(runtime, args.getArgHandle(0));
if (LLVM_UNLIKELY(ORes == ExecutionStatus::EXCEPTION)) {
return ExecutionStatus::EXCEPTION;
}
Handle<JSObject> O = runtime->makeHandle<JSObject>(ORes.getValue());

/// 2. Let P be ? ToPropertyKey(P).
auto PRes = toPropertyKey(runtime, args.getArgHandle(1));
if (LLVM_UNLIKELY(PRes == ExecutionStatus::EXCEPTION)) {
return ExecutionStatus::EXCEPTION;
}
/// 3. Return ? HasOwnProperty(O, P).
return objectHasOwnHelper(runtime, O, *PRes);
}

CallResult<HermesValue>
objectPrototypeIsPrototypeOf(void *, Runtime *runtime, NativeArgs args) {
if (LLVM_UNLIKELY(!args.getArg(0).isObject())) {
Expand Down
33 changes: 33 additions & 0 deletions test/hermes/object-functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,39 @@ try {
}
//CHECK: to_prim

print('hasOwn');
// CHECK-LABEL: hasOwn
var obj = new Object();
obj.prop = 'exists';

function changeO() {
obj.newprop = obj.prop;
delete obj.prop;
}

print(Object.hasOwn(obj, 'prop'));
//CHECK: true
changeO();
print(Object.hasOwn(obj, 'prop'));
//CHECK: false
print(Object.hasOwn(obj, 'newprop'));
//CHECK: true
print(Object.hasOwn(obj, 'new' + 'prop'));
//CHECK: true
obj[5] = 'exists';
print(Object.hasOwn(obj, 5));
//CHECK: true
print(Object.hasOwn([1, 2], 0));
//CHECK: true
print(Object.hasOwn([1, 2], 2));
//CHECK: false

var child = Object.create(obj);
print(Object.hasOwn(child, 'newprop'));
//CHECK: false
print(Object.hasOwn(child, 5));
//CHECK: false

print('defineProperties');
// CHECK-LABEL: defineProperties
var a = [];
Expand Down

0 comments on commit 9261a72

Please sign in to comment.