blob: 0776eeae8f979302b38630b96374863b98ed9335 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Ben Murdoch257744e2011-11-30 15:57:28 +00004
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005"use strict";
6
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007// This file relies on the fact that the following declaration has been made
8// in runtime.js:
9// var $Object = global.Object;
Ben Murdoch257744e2011-11-30 15:57:28 +000010
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011var $Proxy = new $Object();
Ben Murdoch257744e2011-11-30 15:57:28 +000012
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013// -------------------------------------------------------------------
14
15function ProxyCreate(handler, proto) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016 if (!IS_SPEC_OBJECT(handler))
17 throw MakeTypeError("handler_non_object", ["create"])
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018 if (IS_UNDEFINED(proto))
19 proto = null
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020 else if (!(IS_SPEC_OBJECT(proto) || IS_NULL(proto)))
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021 throw MakeTypeError("proto_non_object", ["create"])
Ben Murdoch257744e2011-11-30 15:57:28 +000022 return %CreateJSProxy(handler, proto)
23}
24
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025function ProxyCreateFunction(handler, callTrap, constructTrap) {
Ben Murdoch589d6972011-11-30 16:04:58 +000026 if (!IS_SPEC_OBJECT(handler))
27 throw MakeTypeError("handler_non_object", ["create"])
28 if (!IS_SPEC_FUNCTION(callTrap))
29 throw MakeTypeError("trap_function_expected", ["createFunction", "call"])
30 if (IS_UNDEFINED(constructTrap)) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010031 constructTrap = DerivedConstructTrap(callTrap)
32 } else if (IS_SPEC_FUNCTION(constructTrap)) {
33 // Make sure the trap receives 'undefined' as this.
34 var construct = constructTrap
35 constructTrap = function() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036 return %Apply(construct, UNDEFINED, arguments, 0, %_ArgumentsLength());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010037 }
38 } else {
Ben Murdoch589d6972011-11-30 16:04:58 +000039 throw MakeTypeError("trap_function_expected",
40 ["createFunction", "construct"])
41 }
42 return %CreateJSFunctionProxy(
43 handler, callTrap, constructTrap, $Function.prototype)
44}
Ben Murdoch257744e2011-11-30 15:57:28 +000045
46
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047// -------------------------------------------------------------------
Ben Murdoch257744e2011-11-30 15:57:28 +000048
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049function SetUpProxy() {
50 %CheckIsBootstrapping()
51
52 var global_proxy = %GlobalProxy(global);
53 global_proxy.Proxy = $Proxy;
54
55 // Set up non-enumerable properties of the Proxy object.
56 InstallFunctions($Proxy, DONT_ENUM, [
57 "create", ProxyCreate,
58 "createFunction", ProxyCreateFunction
59 ])
60}
61
62SetUpProxy();
63
64
65// -------------------------------------------------------------------
66// Proxy Builtins
Ben Murdoch257744e2011-11-30 15:57:28 +000067
Ben Murdoch3ef787d2012-04-12 10:51:47 +010068function DerivedConstructTrap(callTrap) {
69 return function() {
70 var proto = this.prototype
71 if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
Ben Murdochb8a8cc12014-11-26 15:28:44 +000072 var obj = { __proto__: proto };
Ben Murdoch3ef787d2012-04-12 10:51:47 +010073 var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
74 return IS_SPEC_OBJECT(result) ? result : obj
75 }
76}
77
Ben Murdoch589d6972011-11-30 16:04:58 +000078function DelegateCallAndConstruct(callTrap, constructTrap) {
79 return function() {
80 return %Apply(%_IsConstructCall() ? constructTrap : callTrap,
81 this, arguments, 0, %_ArgumentsLength())
82 }
83}
84
Ben Murdoch257744e2011-11-30 15:57:28 +000085function DerivedGetTrap(receiver, name) {
86 var desc = this.getPropertyDescriptor(name)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000087 if (IS_UNDEFINED(desc)) { return desc }
Ben Murdoch257744e2011-11-30 15:57:28 +000088 if ('value' in desc) {
89 return desc.value
90 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000091 if (IS_UNDEFINED(desc.get)) { return desc.get }
92 // The proposal says: desc.get.call(receiver)
93 return %_CallFunction(receiver, desc.get)
Ben Murdoch257744e2011-11-30 15:57:28 +000094 }
95}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000096
97function DerivedSetTrap(receiver, name, val) {
98 var desc = this.getOwnPropertyDescriptor(name)
99 if (desc) {
100 if ('writable' in desc) {
101 if (desc.writable) {
102 desc.value = val
103 this.defineProperty(name, desc)
104 return true
105 } else {
106 return false
107 }
108 } else { // accessor
109 if (desc.set) {
110 // The proposal says: desc.set.call(receiver, val)
111 %_CallFunction(receiver, val, desc.set)
112 return true
113 } else {
114 return false
115 }
116 }
117 }
118 desc = this.getPropertyDescriptor(name)
119 if (desc) {
120 if ('writable' in desc) {
121 if (desc.writable) {
122 // fall through
123 } else {
124 return false
125 }
126 } else { // accessor
127 if (desc.set) {
128 // The proposal says: desc.set.call(receiver, val)
129 %_CallFunction(receiver, val, desc.set)
130 return true
131 } else {
132 return false
133 }
134 }
135 }
136 this.defineProperty(name, {
137 value: val,
138 writable: true,
139 enumerable: true,
140 configurable: true});
141 return true;
142}
143
144function DerivedHasTrap(name) {
145 return !!this.getPropertyDescriptor(name)
146}
147
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000148function DerivedHasOwnTrap(name) {
149 return !!this.getOwnPropertyDescriptor(name)
150}
151
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000152function DerivedKeysTrap() {
153 var names = this.getOwnPropertyNames()
154 var enumerableNames = []
155 for (var i = 0, count = 0; i < names.length; ++i) {
156 var name = names[i]
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 if (IS_SYMBOL(name)) continue
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100158 var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name))
159 if (!IS_UNDEFINED(desc) && desc.enumerable) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000160 enumerableNames[count++] = names[i]
161 }
162 }
163 return enumerableNames
164}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100165
166function DerivedEnumerateTrap() {
167 var names = this.getPropertyNames()
168 var enumerableNames = []
169 for (var i = 0, count = 0; i < names.length; ++i) {
170 var name = names[i]
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171 if (IS_SYMBOL(name)) continue
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100172 var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name))
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 if (!IS_UNDEFINED(desc)) {
174 if (!desc.configurable) {
175 throw MakeTypeError("proxy_prop_not_configurable",
176 [this, "getPropertyDescriptor", name])
177 }
178 if (desc.enumerable) enumerableNames[count++] = names[i]
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100179 }
180 }
181 return enumerableNames
182}
183
184function ProxyEnumerate(proxy) {
185 var handler = %GetHandler(proxy)
186 if (IS_UNDEFINED(handler.enumerate)) {
187 return %Apply(DerivedEnumerateTrap, handler, [], 0, 0)
188 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 return ToNameArray(handler.enumerate(), "enumerate", false)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100190 }
191}