Port ProxyHasProperty to Torque
Refactor CheckHasTrapResult as well. Spec: https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p Bug: v8:6664 Change-Id: Ic9bacbd21bb329e354ebd08b61d9e60a94534d0d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1601895 Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com> Reviewed-by: Maya Lekova <mslekova@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#61389}
This commit is contained in:
parent
ea13f20b84
commit
f117f9a2ee
3
BUILD.gn
3
BUILD.gn
@ -948,9 +948,10 @@ torque_files = [
|
||||
"src/builtins/object-fromentries.tq",
|
||||
"src/builtins/proxy-constructor.tq",
|
||||
"src/builtins/proxy-get-property.tq",
|
||||
"src/builtins/proxy-set-property.tq",
|
||||
"src/builtins/proxy-has-property.tq",
|
||||
"src/builtins/proxy-revocable.tq",
|
||||
"src/builtins/proxy-revoke.tq",
|
||||
"src/builtins/proxy-set-property.tq",
|
||||
"src/builtins/proxy.tq",
|
||||
"src/builtins/regexp-replace.tq",
|
||||
"src/builtins/regexp.tq",
|
||||
|
@ -1190,7 +1190,7 @@ extern transitioning builtin SetPropertyInLiteral(implicit context: Context)(
|
||||
extern transitioning builtin DeleteProperty(implicit context: Context)(
|
||||
Object, Object, LanguageMode);
|
||||
extern transitioning builtin HasProperty(implicit context: Context)(
|
||||
JSReceiver, Object): Boolean;
|
||||
Object, Object): Boolean;
|
||||
extern transitioning macro HasProperty_Inline(implicit context: Context)(
|
||||
JSReceiver, Object): Boolean;
|
||||
|
||||
@ -2442,6 +2442,7 @@ macro NewFastJSArrayWitness(array: FastJSArray): FastJSArrayWitness {
|
||||
extern macro TransitionElementsKind(
|
||||
JSObject, Map, constexpr ElementsKind,
|
||||
constexpr ElementsKind): void labels Bailout;
|
||||
extern macro PerformStackCheck(implicit context: Context)(): void;
|
||||
|
||||
extern macro IsCallable(HeapObject): bool;
|
||||
extern macro IsConstructor(HeapObject): bool;
|
||||
|
@ -824,9 +824,6 @@ namespace internal {
|
||||
/* V8 Extras: v8.resolvePromise(promise, resolution) */ \
|
||||
TFJ(PromiseInternalResolve, 2, kReceiver, kPromise, kResolution) \
|
||||
\
|
||||
/* Proxy */ \
|
||||
TFS(ProxyHasProperty, kProxy, kName) \
|
||||
\
|
||||
/* Reflect */ \
|
||||
ASM(ReflectApply, Dummy) \
|
||||
ASM(ReflectConstruct, Dummy) \
|
||||
|
@ -262,82 +262,6 @@ TF_BUILTIN(ConstructProxy, ProxiesCodeStubAssembler) {
|
||||
{ ThrowTypeError(context, MessageTemplate::kProxyRevoked, "construct"); }
|
||||
}
|
||||
|
||||
TF_BUILTIN(ProxyHasProperty, ProxiesCodeStubAssembler) {
|
||||
Node* context = Parameter(Descriptor::kContext);
|
||||
Node* proxy = Parameter(Descriptor::kProxy);
|
||||
Node* name = Parameter(Descriptor::kName);
|
||||
|
||||
CSA_ASSERT(this, IsJSProxy(proxy));
|
||||
|
||||
PerformStackCheck(CAST(context));
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
CSA_ASSERT(this, IsName(name));
|
||||
CSA_ASSERT(this, Word32Equal(IsPrivateSymbol(name), Int32Constant(0)));
|
||||
|
||||
Label throw_proxy_handler_revoked(this, Label::kDeferred),
|
||||
trap_undefined(this),
|
||||
if_try_get_own_property_bailout(this, Label::kDeferred),
|
||||
trap_not_callable(this, Label::kDeferred), return_true(this),
|
||||
return_false(this), check_target_desc(this);
|
||||
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
|
||||
|
||||
// 3. If handler is null, throw a TypeError exception.
|
||||
// 4. Assert: Type(handler) is Object.
|
||||
GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
|
||||
|
||||
// 5. Let target be O.[[ProxyTarget]].
|
||||
Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
|
||||
|
||||
// 6. Let trap be ? GetMethod(handler, "has").
|
||||
// 7. If trap is undefined, then (see 7.a below).
|
||||
Handle<Name> trap_name = factory()->has_string();
|
||||
Node* trap = GetMethod(context, handler, trap_name, &trap_undefined);
|
||||
|
||||
GotoIf(TaggedIsSmi(trap), &trap_not_callable);
|
||||
GotoIfNot(IsCallable(trap), &trap_not_callable);
|
||||
|
||||
// 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, P
|
||||
// »)).
|
||||
BranchIfToBooleanIsTrue(CallJS(CodeFactory::Call(isolate()), context, trap,
|
||||
handler, target, name),
|
||||
&return_true, &check_target_desc);
|
||||
|
||||
BIND(&check_target_desc);
|
||||
{
|
||||
// 9. If booleanTrapResult is false, then (see 9.a. in CheckHasTrapResult).
|
||||
CheckHasTrapResult(context, target, proxy, name, &return_false,
|
||||
&if_try_get_own_property_bailout);
|
||||
}
|
||||
|
||||
BIND(&if_try_get_own_property_bailout);
|
||||
{
|
||||
CallRuntime(Runtime::kCheckProxyHasTrap, context, name, target);
|
||||
Return(FalseConstant());
|
||||
}
|
||||
|
||||
BIND(&trap_undefined);
|
||||
{
|
||||
// 7.a. Return ? target.[[HasProperty]](P).
|
||||
TailCallBuiltin(Builtins::kHasProperty, context, target, name);
|
||||
}
|
||||
|
||||
BIND(&return_false);
|
||||
Return(FalseConstant());
|
||||
|
||||
BIND(&return_true);
|
||||
Return(TrueConstant());
|
||||
|
||||
BIND(&throw_proxy_handler_revoked);
|
||||
ThrowTypeError(context, MessageTemplate::kProxyRevoked, "has");
|
||||
|
||||
BIND(&trap_not_callable);
|
||||
ThrowTypeError(context, MessageTemplate::kPropertyNotFunction, trap,
|
||||
StringConstant("has"), proxy);
|
||||
}
|
||||
|
||||
Node* ProxiesCodeStubAssembler::CheckGetSetTrapResult(
|
||||
Node* context, Node* target, Node* proxy, Node* name, Node* trap_result,
|
||||
JSProxy::AccessKind access_kind) {
|
||||
@ -446,10 +370,8 @@ Node* ProxiesCodeStubAssembler::CheckGetSetTrapResult(
|
||||
}
|
||||
}
|
||||
|
||||
void ProxiesCodeStubAssembler::CheckHasTrapResult(Node* context, Node* target,
|
||||
Node* proxy, Node* name,
|
||||
Label* check_passed,
|
||||
Label* if_bailout) {
|
||||
Node* ProxiesCodeStubAssembler::CheckHasTrapResult(Node* context, Node* target,
|
||||
Node* proxy, Node* name) {
|
||||
Node* target_map = LoadMap(target);
|
||||
VARIABLE(var_value, MachineRepresentation::kTagged);
|
||||
VARIABLE(var_details, MachineRepresentation::kWord32);
|
||||
@ -457,14 +379,15 @@ void ProxiesCodeStubAssembler::CheckHasTrapResult(Node* context, Node* target,
|
||||
|
||||
Label if_found_value(this, Label::kDeferred),
|
||||
throw_non_configurable(this, Label::kDeferred),
|
||||
throw_non_extensible(this, Label::kDeferred);
|
||||
throw_non_extensible(this, Label::kDeferred), check_passed(this),
|
||||
check_in_runtime(this, Label::kDeferred);
|
||||
|
||||
// 9.a. Let targetDesc be ? target.[[GetOwnProperty]](P).
|
||||
GotoIfNot(IsUniqueNameNoIndex(CAST(name)), if_bailout);
|
||||
GotoIfNot(IsUniqueNameNoIndex(CAST(name)), &check_in_runtime);
|
||||
Node* instance_type = LoadInstanceType(target);
|
||||
TryGetOwnProperty(context, target, target, target_map, instance_type, name,
|
||||
&if_found_value, &var_value, &var_details, &var_raw_value,
|
||||
check_passed, if_bailout, kReturnAccessorPair);
|
||||
&check_passed, &check_in_runtime, kReturnAccessorPair);
|
||||
|
||||
// 9.b. If targetDesc is not undefined, then (see 9.b.i. below).
|
||||
BIND(&if_found_value);
|
||||
@ -480,7 +403,7 @@ void ProxiesCodeStubAssembler::CheckHasTrapResult(Node* context, Node* target,
|
||||
|
||||
// 9.b.iii. If extensibleTarget is false, throw a TypeError exception.
|
||||
GotoIfNot(target_extensible, &throw_non_extensible);
|
||||
Goto(check_passed);
|
||||
Goto(&check_passed);
|
||||
}
|
||||
|
||||
BIND(&throw_non_configurable);
|
||||
@ -488,6 +411,15 @@ void ProxiesCodeStubAssembler::CheckHasTrapResult(Node* context, Node* target,
|
||||
|
||||
BIND(&throw_non_extensible);
|
||||
{ ThrowTypeError(context, MessageTemplate::kProxyHasNonExtensible, name); }
|
||||
|
||||
BIND(&check_in_runtime);
|
||||
{
|
||||
CallRuntime(Runtime::kCheckProxyHasTrapResult, context, name, target);
|
||||
Goto(&check_passed);
|
||||
}
|
||||
|
||||
BIND(&check_passed);
|
||||
return FalseConstant();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -29,6 +29,9 @@ class ProxiesCodeStubAssembler : public CodeStubAssembler {
|
||||
Node* name, Node* trap_result,
|
||||
JSProxy::AccessKind access_kind);
|
||||
|
||||
Node* CheckHasTrapResult(Node* context, Node* target, Node* proxy,
|
||||
Node* name);
|
||||
|
||||
protected:
|
||||
enum ProxyRevokeFunctionContextSlot {
|
||||
kProxySlot = Context::MIN_CONTEXT_SLOTS,
|
||||
@ -38,8 +41,6 @@ class ProxiesCodeStubAssembler : public CodeStubAssembler {
|
||||
Node* AllocateJSArrayForCodeStubArguments(Node* context,
|
||||
CodeStubArguments& args, Node* argc,
|
||||
ParameterMode mode);
|
||||
void CheckHasTrapResult(Node* context, Node* target, Node* proxy, Node* name,
|
||||
Label* check_passed, Label* if_bailout);
|
||||
|
||||
private:
|
||||
Node* CreateProxyRevokeFunctionContext(Node* proxy, Node* native_context);
|
||||
|
55
src/builtins/proxy-has-property.tq
Normal file
55
src/builtins/proxy-has-property.tq
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
#include 'src/builtins/builtins-proxy-gen.h'
|
||||
|
||||
namespace proxy {
|
||||
|
||||
// ES #sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p
|
||||
// https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p
|
||||
transitioning builtin ProxyHasProperty(implicit context: Context)(
|
||||
proxy: JSProxy, name: Name): Object {
|
||||
assert(IsJSProxy(proxy));
|
||||
|
||||
PerformStackCheck();
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
assert(IsName(name));
|
||||
assert(!IsPrivateSymbol(name));
|
||||
|
||||
try {
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
// 3. If handler is null, throw a TypeError exception.
|
||||
// 4. Assert: Type(handler) is Object.
|
||||
const handler =
|
||||
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
|
||||
|
||||
// 5. Let target be O.[[ProxyTarget]].
|
||||
const target = proxy.target;
|
||||
|
||||
// 6. Let trap be ? GetMethod(handler, "has").
|
||||
// 7. If trap is undefined, then (see 7.a below).
|
||||
const trap: Callable = GetMethod(handler, 'has')
|
||||
otherwise goto TrapUndefined(target);
|
||||
|
||||
// 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «
|
||||
// target»)).
|
||||
// 9. If booleanTrapResult is false, then (see 9.a. in
|
||||
// CheckHasTrapResult).
|
||||
// 10. Return booleanTrapResult.
|
||||
const trapResult = Call(context, trap, handler, target, name);
|
||||
if (BranchIfToBooleanIsTrue(trapResult)) {
|
||||
return True;
|
||||
}
|
||||
return CheckHasTrapResult(target, proxy, name);
|
||||
}
|
||||
label TrapUndefined(target: Object) {
|
||||
// 7.a. Return ? target.[[HasProperty]](P).
|
||||
tail HasProperty(target, name);
|
||||
}
|
||||
label ThrowProxyHandlerRevoked deferred {
|
||||
ThrowTypeError(kProxyRevoked, 'has');
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,9 @@ namespace proxy {
|
||||
implicit context:
|
||||
Context)(Object, JSProxy, Name, Object, constexpr int31): Object;
|
||||
|
||||
extern transitioning macro ProxiesCodeStubAssembler::CheckHasTrapResult(
|
||||
implicit context: Context)(Object, JSProxy, Name): Object;
|
||||
|
||||
const kProxyNonObject: constexpr MessageTemplate
|
||||
generates 'MessageTemplate::kProxyNonObject';
|
||||
const kProxyHandlerOrTargetRevoked: constexpr MessageTemplate
|
||||
|
@ -98,7 +98,7 @@ RUNTIME_FUNCTION(Runtime_CheckProxyGetSetTrapResult) {
|
||||
JSProxy::AccessKind(access_kind)));
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_CheckProxyHasTrap) {
|
||||
RUNTIME_FUNCTION(Runtime_CheckProxyHasTrapResult) {
|
||||
HandleScope scope(isolate);
|
||||
|
||||
DCHECK_EQ(2, args.length());
|
||||
|
@ -360,7 +360,7 @@ namespace internal {
|
||||
|
||||
#define FOR_EACH_INTRINSIC_PROXY(F, I) \
|
||||
F(CheckProxyGetSetTrapResult, 2, 1) \
|
||||
F(CheckProxyHasTrap, 2, 1) \
|
||||
F(CheckProxyHasTrapResult, 2, 1) \
|
||||
F(GetPropertyWithReceiver, 3, 1) \
|
||||
F(IsJSProxy, 1, 1) \
|
||||
F(JSProxyGetHandler, 1, 1) \
|
||||
|
Loading…
Reference in New Issue
Block a user