[runtime] [proxy] Implementing [[Call]]
BUG=v8:1543 LOG=N Review URL: https://codereview.chromium.org/1499593003 Cr-Commit-Position: refs/heads/master@{#32675}
This commit is contained in:
parent
cd96d74124
commit
7299412473
@ -1685,8 +1685,14 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
__ cmp(r5, Operand(JS_PROXY_TYPE));
|
||||
__ b(ne, &non_function);
|
||||
|
||||
// 1. Call to Proxy.
|
||||
// TODO(neis): Implement [[Call]] on proxies.
|
||||
// 1. Runtime fallback for Proxy [[Call]].
|
||||
__ Push(r1);
|
||||
// Increase the arguments size to include the pushed function and the
|
||||
// existing receiver on the stack.
|
||||
__ add(r0, r0, Operand(2));
|
||||
// Tail-call to the runtime.
|
||||
__ JumpToExternalReference(
|
||||
ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
|
||||
|
||||
// 2. Call to something else, which might have a [[Call]] internal method (if
|
||||
// not we raise an exception).
|
||||
|
@ -1677,8 +1677,14 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
__ Cmp(x5, JS_PROXY_TYPE);
|
||||
__ B(ne, &non_function);
|
||||
|
||||
// 1. Call to proxy.
|
||||
// TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies.
|
||||
// 1. Runtime fallback for Proxy [[Call]].
|
||||
__ Push(x1);
|
||||
// Increase the arguments size to include the pushed function and the
|
||||
// existing receiver on the stack.
|
||||
__ Add(x0, x0, Operand(2));
|
||||
// Tail-call to the runtime.
|
||||
__ JumpToExternalReference(
|
||||
ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
|
||||
|
||||
// 2. Call to something else, which might have a [[Call]] internal method (if
|
||||
// not we raise an exception).
|
||||
|
@ -218,6 +218,7 @@ class Genesis BASE_EMBEDDED {
|
||||
void InstallBuiltinFunctionIds();
|
||||
void InstallExperimentalBuiltinFunctionIds();
|
||||
void InitializeNormalizedMapCaches();
|
||||
void InstallJSProxyMaps();
|
||||
|
||||
enum ExtensionTraversalState {
|
||||
UNVISITED, VISITED, INSTALLED
|
||||
@ -362,6 +363,20 @@ void Bootstrapper::DetachGlobal(Handle<Context> env) {
|
||||
|
||||
namespace {
|
||||
|
||||
Handle<JSFunction> InstallFunction(Handle<JSObject> target,
|
||||
Handle<Name> property_name,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> function_name,
|
||||
PropertyAttributes attributes = DONT_ENUM) {
|
||||
JSObject::AddProperty(target, property_name, function, attributes);
|
||||
if (target->IsJSGlobalObject()) {
|
||||
function->shared()->set_instance_class_name(*function_name);
|
||||
}
|
||||
function->shared()->set_native(true);
|
||||
return function;
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> InstallFunction(Handle<JSObject> target, Handle<Name> name,
|
||||
InstanceType type, int instance_size,
|
||||
MaybeHandle<JSObject> maybe_prototype,
|
||||
@ -382,12 +397,7 @@ Handle<JSFunction> InstallFunction(Handle<JSObject> target, Handle<Name> name,
|
||||
kInstallConstructor, strict_function_map)
|
||||
: factory->NewFunctionWithoutPrototype(name_string, call_code,
|
||||
strict_function_map);
|
||||
JSObject::AddProperty(target, name, function, attributes);
|
||||
if (target->IsJSGlobalObject()) {
|
||||
function->shared()->set_instance_class_name(*name_string);
|
||||
}
|
||||
function->shared()->set_native(true);
|
||||
return function;
|
||||
return InstallFunction(target, name, function, name_string, attributes);
|
||||
}
|
||||
|
||||
|
||||
@ -2144,21 +2154,58 @@ void Genesis::InitializeGlobal_harmony_simd() {
|
||||
}
|
||||
|
||||
|
||||
void Genesis::InstallJSProxyMaps() {
|
||||
// Allocate the different maps for all Proxy types.
|
||||
// Next to the default proxy, we need maps indicating callable and
|
||||
// constructable proxies.
|
||||
|
||||
Handle<Map> proxy_function_map =
|
||||
Map::Copy(isolate()->sloppy_function_without_prototype_map(), "Proxy");
|
||||
proxy_function_map->set_is_constructor(true);
|
||||
native_context()->set_proxy_function_map(*proxy_function_map);
|
||||
|
||||
Handle<Map> proxy_map =
|
||||
factory()->NewMap(JS_PROXY_TYPE, JSProxy::kSize, FAST_ELEMENTS);
|
||||
native_context()->set_proxy_map(*proxy_map);
|
||||
|
||||
Handle<Map> proxy_callable_map = Map::Copy(proxy_map, "callable Proxy");
|
||||
proxy_callable_map->set_is_callable();
|
||||
native_context()->set_proxy_callable_map(*proxy_callable_map);
|
||||
|
||||
Handle<Map> proxy_constructor_map =
|
||||
Map::Copy(proxy_callable_map, "constructor Proxy");
|
||||
proxy_constructor_map->set_is_constructor(true);
|
||||
native_context()->set_proxy_constructor_map(*proxy_constructor_map);
|
||||
}
|
||||
|
||||
|
||||
void Genesis::InitializeGlobal_harmony_proxies() {
|
||||
if (!FLAG_harmony_proxies) return;
|
||||
Handle<JSGlobalObject> global(
|
||||
JSGlobalObject::cast(native_context()->global_object()));
|
||||
Isolate* isolate = global->GetIsolate();
|
||||
Handle<JSFunction> proxy_fun = InstallFunction(
|
||||
global, "Proxy", JS_PROXY_TYPE, JSProxy::kSize,
|
||||
isolate->initial_object_prototype(), Builtins::kProxyConstructor);
|
||||
// TODO(verwaest): Set to null in InstallFunction.
|
||||
proxy_fun->initial_map()->set_prototype(isolate->heap()->null_value());
|
||||
proxy_fun->shared()->set_construct_stub(
|
||||
Factory* factory = isolate->factory();
|
||||
|
||||
InstallJSProxyMaps();
|
||||
|
||||
// Create the Proxy object.
|
||||
Handle<String> name = factory->Proxy_string();
|
||||
Handle<Code> code(isolate->builtins()->ProxyConstructor());
|
||||
|
||||
Handle<JSFunction> proxy_function =
|
||||
factory->NewFunction(isolate->proxy_function_map(), name, code);
|
||||
|
||||
JSFunction::SetInitialMap(proxy_function,
|
||||
Handle<Map>(native_context()->proxy_map(), isolate),
|
||||
factory->null_value());
|
||||
|
||||
proxy_function->shared()->set_construct_stub(
|
||||
*isolate->builtins()->ProxyConstructor_ConstructStub());
|
||||
proxy_fun->shared()->set_internal_formal_parameter_count(2);
|
||||
proxy_fun->shared()->set_length(2);
|
||||
native_context()->set_proxy_function(*proxy_fun);
|
||||
proxy_function->shared()->set_internal_formal_parameter_count(2);
|
||||
proxy_function->shared()->set_length(2);
|
||||
|
||||
native_context()->set_proxy_function(*proxy_function);
|
||||
InstallFunction(global, name, proxy_function, name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1799,6 +1799,7 @@ BUILTIN(ProxyConstructor) {
|
||||
// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
|
||||
BUILTIN(ProxyConstructor_ConstructStub) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(isolate->proxy_function()->IsConstructor());
|
||||
DCHECK_EQ(3, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> handler = args.at<Object>(2);
|
||||
|
@ -220,7 +220,11 @@ enum BindingFlags {
|
||||
V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
|
||||
V(OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX, Map, object_function_prototype_map) \
|
||||
V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \
|
||||
V(PROXY_CALLABLE_MAP_INDEX, Map, proxy_callable_map) \
|
||||
V(PROXY_CONSTRUCTOR_MAP_INDEX, Map, proxy_constructor_map) \
|
||||
V(PROXY_FUNCTION_INDEX, JSFunction, proxy_function) \
|
||||
V(PROXY_FUNCTION_MAP_INDEX, Map, proxy_function_map) \
|
||||
V(PROXY_MAP_INDEX, Map, proxy_map) \
|
||||
V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
|
||||
V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map) \
|
||||
V(SCRIPT_CONTEXT_TABLE_INDEX, ScriptContextTable, script_context_table) \
|
||||
|
@ -1206,13 +1206,14 @@ Handle<JSFunction> Factory::NewFunction(Handle<Map> map,
|
||||
Handle<Context> context(isolate()->native_context());
|
||||
Handle<SharedFunctionInfo> info =
|
||||
NewSharedFunctionInfo(name, code, map->is_constructor());
|
||||
DCHECK(is_sloppy(info->language_mode()) &&
|
||||
(map.is_identical_to(isolate()->sloppy_function_map()) ||
|
||||
map.is_identical_to(
|
||||
isolate()->sloppy_function_without_prototype_map()) ||
|
||||
map.is_identical_to(
|
||||
isolate()->sloppy_function_with_readonly_prototype_map()) ||
|
||||
map.is_identical_to(isolate()->strict_function_map())));
|
||||
DCHECK(is_sloppy(info->language_mode()));
|
||||
DCHECK(
|
||||
map.is_identical_to(isolate()->sloppy_function_map()) ||
|
||||
map.is_identical_to(isolate()->sloppy_function_without_prototype_map()) ||
|
||||
map.is_identical_to(
|
||||
isolate()->sloppy_function_with_readonly_prototype_map()) ||
|
||||
map.is_identical_to(isolate()->strict_function_map()) ||
|
||||
map.is_identical_to(isolate()->proxy_function_map()));
|
||||
return NewFunction(map, info, context);
|
||||
}
|
||||
|
||||
@ -1941,7 +1942,16 @@ Handle<JSDataView> Factory::NewJSDataView(Handle<JSArrayBuffer> buffer,
|
||||
Handle<JSProxy> Factory::NewJSProxy(Handle<JSReceiver> target,
|
||||
Handle<JSReceiver> handler) {
|
||||
// Allocate the proxy object.
|
||||
Handle<Map> map(isolate()->proxy_function()->initial_map());
|
||||
Handle<Map> map;
|
||||
if (target->IsCallable()) {
|
||||
if (target->IsConstructor()) {
|
||||
map = Handle<Map>(isolate()->proxy_constructor_map());
|
||||
} else {
|
||||
map = Handle<Map>(isolate()->proxy_callable_map());
|
||||
}
|
||||
} else {
|
||||
map = Handle<Map>(isolate()->proxy_map());
|
||||
}
|
||||
DCHECK(map->prototype()->IsNull());
|
||||
Handle<JSProxy> result = New<JSProxy>(map, NEW_SPACE);
|
||||
result->set_target(*target);
|
||||
|
@ -517,6 +517,8 @@ class Factory final {
|
||||
Handle<Code> code,
|
||||
InstanceType type,
|
||||
int instance_size);
|
||||
Handle<JSFunction> NewFunction(Handle<Map> map, Handle<String> name,
|
||||
MaybeHandle<Code> maybe_code);
|
||||
|
||||
// Create a serialized scope info.
|
||||
Handle<ScopeInfo> NewScopeInfo(int length);
|
||||
@ -695,10 +697,6 @@ class Factory final {
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<Context> context,
|
||||
PretenureFlag pretenure = TENURED);
|
||||
|
||||
Handle<JSFunction> NewFunction(Handle<Map> map,
|
||||
Handle<String> name,
|
||||
MaybeHandle<Code> maybe_code);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -291,6 +291,7 @@ namespace internal {
|
||||
V(Promise_string, "Promise") \
|
||||
V(proto_string, "__proto__") \
|
||||
V(prototype_string, "prototype") \
|
||||
V(Proxy_string, "Proxy") \
|
||||
V(query_colon_string, "(?:)") \
|
||||
V(RegExp_string, "RegExp") \
|
||||
V(setPrototypeOf_string, "setPrototypeOf") \
|
||||
|
@ -1542,8 +1542,16 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
__ CmpInstanceType(ecx, JS_PROXY_TYPE);
|
||||
__ j(not_equal, &non_function);
|
||||
|
||||
// 1. Call to Proxy.
|
||||
// TODO(neis): Implement [[Call]] on proxies.
|
||||
// 1. Runtime fallback for Proxy [[Call]].
|
||||
__ PopReturnAddressTo(ecx);
|
||||
__ Push(edi);
|
||||
__ PushReturnAddressFrom(ecx);
|
||||
// Increase the arguments size to include the pushed function and the
|
||||
// existing receiver on the stack.
|
||||
__ add(eax, Immediate(2));
|
||||
// Tail-call to the runtime.
|
||||
__ JumpToExternalReference(
|
||||
ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
|
||||
|
||||
// 2. Call to something else, which might have a [[Call]] internal method (if
|
||||
// not we raise an exception).
|
||||
|
@ -1694,8 +1694,14 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));
|
||||
__ Branch(&non_function, ne, t2, Operand(JS_PROXY_TYPE));
|
||||
|
||||
// 1. Call Proxy.
|
||||
// TODO(neis): implement call on Proxy
|
||||
// 1. Runtime fallback for Proxy [[Call]].
|
||||
__ Push(a1);
|
||||
// Increase the arguments size to include the pushed function and the
|
||||
// existing receiver on the stack.
|
||||
__ Addu(a0, a0, 2);
|
||||
// Tail-call to the runtime.
|
||||
__ JumpToExternalReference(
|
||||
ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
|
||||
|
||||
// 2. Call to something else, which might have a [[Call]] internal method (if
|
||||
// not we raise an exception).
|
||||
|
@ -1686,8 +1686,14 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE));
|
||||
__ Branch(&non_function, ne, t2, Operand(JS_PROXY_TYPE));
|
||||
|
||||
// 1. Call to function proxy.
|
||||
// TODO(neis): Implement [[Call]] on proxies.
|
||||
// 1. Runtime fallback for Proxy [[Call]].
|
||||
__ Push(a1);
|
||||
// Increase the arguments size to include the pushed function and the
|
||||
// existing receiver on the stack.
|
||||
__ Daddu(a0, a0, 2);
|
||||
// Tail-call to the runtime.
|
||||
__ JumpToExternalReference(
|
||||
ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
|
||||
|
||||
// 2. Call to something else, which might have a [[Call]] internal method (if
|
||||
// not we raise an exception).
|
||||
|
@ -997,7 +997,7 @@ MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
|
||||
if (is_extensible.FromJust()) return handler_proto;
|
||||
// 11. Let targetProto be ? target.[[GetPrototypeOf]]().
|
||||
Handle<Object> target_proto;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, handler_proto,
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
|
||||
Object::GetPrototype(isolate, target), Object);
|
||||
// 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
|
||||
if (!handler_proto->SameValue(*target_proto)) {
|
||||
|
@ -1698,8 +1698,14 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
__ cmpi(r8, Operand(JS_PROXY_TYPE));
|
||||
__ bne(&non_function);
|
||||
|
||||
// 1. Call to proxy.
|
||||
// TODO(neis): Implement [[Call]] on proxies.
|
||||
// 1. Runtime fallback for Proxy [[Call]].
|
||||
__ Push(r4);
|
||||
// Increase the arguments size to include the pushed function and the
|
||||
// existing receiver on the stack.
|
||||
__ addi(r3, r3, Operand(2));
|
||||
// Tail-call to the runtime.
|
||||
__ JumpToExternalReference(
|
||||
ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
|
||||
|
||||
// 2. Call to something else, which might have a [[Call]] internal method (if
|
||||
// not we raise an exception).
|
||||
|
@ -5,13 +5,73 @@
|
||||
#include "src/runtime/runtime-utils.h"
|
||||
|
||||
#include "src/arguments.h"
|
||||
#include "src/elements.h"
|
||||
#include "src/factory.h"
|
||||
#include "src/isolate-inl.h"
|
||||
#include "src/objects-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
|
||||
// ES6 9.5.13 [[Call]] (thisArgument, argumentsList)
|
||||
RUNTIME_FUNCTION(Runtime_JSProxyCall) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_LE(2, args.length());
|
||||
// thisArgument == receiver
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, args.length() - 1);
|
||||
Handle<String> trap_name = isolate->factory()->apply_string();
|
||||
// 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
|
||||
Handle<Object> handler(proxy->handler(), isolate);
|
||||
// 2. If handler is null, throw a TypeError exception.
|
||||
if (proxy->IsRevoked()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
|
||||
}
|
||||
// 3. Assert: Type(handler) is Object.
|
||||
DCHECK(handler->IsJSReceiver());
|
||||
// 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
|
||||
Handle<JSReceiver> target(proxy->target(), isolate);
|
||||
// 5. Let trap be ? GetMethod(handler, "apply").
|
||||
Handle<Object> trap;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, trap,
|
||||
Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name));
|
||||
// 6. If trap is undefined, then
|
||||
int const arguments_length = args.length() - 2;
|
||||
if (trap->IsUndefined()) {
|
||||
// 6.a. Return Call(target, thisArgument, argumentsList).
|
||||
ScopedVector<Handle<Object>> argv(arguments_length);
|
||||
for (int i = 0; i < arguments_length; ++i) {
|
||||
argv[i] = args.at<Object>(i + 1);
|
||||
}
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, result, Execution::Call(isolate, target, receiver,
|
||||
arguments_length, argv.start()));
|
||||
return *result;
|
||||
}
|
||||
// 7. Let argArray be CreateArrayFromList(argumentsList).
|
||||
Handle<JSArray> arg_array = isolate->factory()->NewJSArray(
|
||||
FAST_ELEMENTS, arguments_length, arguments_length);
|
||||
ElementsAccessor* accessor = arg_array->GetElementsAccessor();
|
||||
{
|
||||
DisallowHeapAllocation no_gc;
|
||||
FixedArrayBase* elements = arg_array->elements();
|
||||
for (int i = 0; i < arguments_length; i++) {
|
||||
accessor->Set(elements, i, args[i + 1]);
|
||||
}
|
||||
}
|
||||
// 8. Return Call(trap, handler, «target, thisArgument, argArray»).
|
||||
Handle<Object> trap_result;
|
||||
Handle<Object> trap_args[] = {target, receiver, arg_array};
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, trap_result,
|
||||
Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args));
|
||||
return *trap_result;
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_IsJSProxy) {
|
||||
SealHandleScope shs(isolate);
|
||||
|
@ -541,6 +541,7 @@ namespace internal {
|
||||
|
||||
#define FOR_EACH_INTRINSIC_PROXY(F) \
|
||||
F(IsJSProxy, 1, 1) \
|
||||
F(JSProxyCall, -1 /* >= 2 */, 1) \
|
||||
F(GetHandler, 1, 1) \
|
||||
F(RevokeProxy, 1, 1)
|
||||
|
||||
|
@ -1745,8 +1745,16 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
__ CmpInstanceType(rcx, JS_PROXY_TYPE);
|
||||
__ j(not_equal, &non_function);
|
||||
|
||||
// 1. Call to function proxy.
|
||||
// TODO(neis): Implement [[Call]] on proxies.
|
||||
// 1. Runtime fallback for Proxy [[Call]].
|
||||
__ PopReturnAddressTo(kScratchRegister);
|
||||
__ Push(rdi);
|
||||
__ PushReturnAddressFrom(kScratchRegister);
|
||||
// Increase the arguments size to include the pushed function and the
|
||||
// existing receiver on the stack.
|
||||
__ addp(rax, Immediate(2));
|
||||
// Tail-call to the runtime.
|
||||
__ JumpToExternalReference(
|
||||
ExternalReference(Runtime::kJSProxyCall, masm->isolate()), 1);
|
||||
|
||||
// 2. Call to something else, which might have a [[Call]] internal method (if
|
||||
// not we raise an exception).
|
||||
|
@ -1542,8 +1542,16 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
__ CmpInstanceType(ecx, JS_PROXY_TYPE);
|
||||
__ j(not_equal, &non_function);
|
||||
|
||||
// 1. Call to function proxy.
|
||||
// TODO(neis): Implement [[Call]] on proxies.
|
||||
// 1. Runtime fallback for Proxy [[Call]].
|
||||
__ PopReturnAddressTo(ecx);
|
||||
__ Push(edi);
|
||||
__ PushReturnAddressFrom(ecx);
|
||||
// Increase the arguments size to include the pushed function and the
|
||||
// existing receiver on the stack.
|
||||
__ addp(eax, Immediate(2));
|
||||
// Tail-call to the runtime.
|
||||
__ JumpToExternalReference(
|
||||
ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
|
||||
|
||||
// 2. Call to something else, which might have a [[Call]] internal method (if
|
||||
// not we raise an exception).
|
||||
|
89
test/mjsunit/harmony/proxies-apply.js
Normal file
89
test/mjsunit/harmony/proxies-apply.js
Normal file
@ -0,0 +1,89 @@
|
||||
// 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: --harmony-proxies --harmony-reflect
|
||||
|
||||
(function testNonCallable() {
|
||||
var proxy = new Proxy({},{});
|
||||
assertThrows(function(){ proxy() }, TypeError);
|
||||
|
||||
var proxy2 = new Proxy(proxy, {});
|
||||
assertThrows(function(){ proxy2() }, TypeError);
|
||||
})();
|
||||
|
||||
(function testCallProxyFallbackNoArguments() {
|
||||
var called = false;
|
||||
var target = function() {
|
||||
called = true;
|
||||
}
|
||||
var proxy = new Proxy(target, {});
|
||||
assertFalse(called);
|
||||
proxy();
|
||||
assertTrue(called);
|
||||
|
||||
called = false;
|
||||
var proxy2 = new Proxy(proxy, {});
|
||||
assertFalse(called);
|
||||
proxy2();
|
||||
assertTrue(called);
|
||||
})();
|
||||
|
||||
(function testCallProxyFallback1Argument() {
|
||||
var called = false;
|
||||
var target = function(a) {
|
||||
called = true;
|
||||
assertEquals('1', a);
|
||||
}
|
||||
var proxy = new Proxy(target, {});
|
||||
assertFalse(called);
|
||||
proxy('1');
|
||||
assertTrue(called);
|
||||
})();
|
||||
|
||||
(function testCallProxyFallback2Arguments() {
|
||||
var called = false;
|
||||
var target = function(a, b) {
|
||||
called = true;
|
||||
assertEquals('1', a);
|
||||
assertEquals('2', b);
|
||||
}
|
||||
var proxy = new Proxy(target, {});
|
||||
assertFalse(called);
|
||||
proxy('1', '2');
|
||||
assertTrue(called);
|
||||
})();
|
||||
|
||||
(function testCallProxyFallbackChangedReceiver() {
|
||||
var apply_receiver = {receiver:true};
|
||||
var seen_receiver = undefined;
|
||||
var target = function() {
|
||||
seen_receiver = this;
|
||||
}
|
||||
var proxy = new Proxy(target, {});
|
||||
assertEquals(undefined, seen_receiver);
|
||||
Reflect.apply(proxy, apply_receiver, [1,2,3,4]);
|
||||
assertSame(apply_receiver, seen_receiver);
|
||||
})();
|
||||
|
||||
(function testCallProxyTrap() {
|
||||
var called_target = false;
|
||||
var called_handler = false;
|
||||
var target = function(a, b) {
|
||||
called_target = true;
|
||||
assertEquals(1, a);
|
||||
assertEquals(2, b);
|
||||
}
|
||||
var handler = {
|
||||
apply: function(target, this_arg, args) {
|
||||
target.apply(this_arg, args);
|
||||
called_handler = true;
|
||||
}
|
||||
}
|
||||
var proxy = new Proxy(target, handler);
|
||||
assertFalse(called_target);
|
||||
assertFalse(called_handler);
|
||||
Reflect.apply(proxy, {rec:1}, [1,2]);
|
||||
assertTrue(called_target);
|
||||
assertTrue(called_handler);
|
||||
})();
|
Loading…
Reference in New Issue
Block a user