blob: 3cd467faf2d379c34ed43ff9256fbfcb219c4d63 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28global.Proxy = new $Object();
29
30var $Proxy = global.Proxy
31
Ben Murdoch257744e2011-11-30 15:57:28 +000032$Proxy.create = function(handler, proto) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000033 if (!IS_SPEC_OBJECT(handler))
34 throw MakeTypeError("handler_non_object", ["create"])
Ben Murdoch592a9fc2012-03-05 11:04:45 +000035 if (IS_UNDEFINED(proto))
36 proto = null
37 else if (!(IS_SPEC_OBJECT(proto) || proto === null))
38 throw MakeTypeError("proto_non_object", ["create"])
Ben Murdoch257744e2011-11-30 15:57:28 +000039 return %CreateJSProxy(handler, proto)
40}
41
Ben Murdoch589d6972011-11-30 16:04:58 +000042$Proxy.createFunction = function(handler, callTrap, constructTrap) {
43 if (!IS_SPEC_OBJECT(handler))
44 throw MakeTypeError("handler_non_object", ["create"])
45 if (!IS_SPEC_FUNCTION(callTrap))
46 throw MakeTypeError("trap_function_expected", ["createFunction", "call"])
47 if (IS_UNDEFINED(constructTrap)) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +000048 constructTrap = DerivedConstructTrap(callTrap)
49 } else if (IS_SPEC_FUNCTION(constructTrap)) {
50 // Make sure the trap receives 'undefined' as this.
51 var construct = constructTrap
52 constructTrap = function() {
53 return %Apply(construct, void 0, arguments, 0, %_ArgumentsLength());
54 }
55 } else {
Ben Murdoch589d6972011-11-30 16:04:58 +000056 throw MakeTypeError("trap_function_expected",
57 ["createFunction", "construct"])
58 }
59 return %CreateJSFunctionProxy(
60 handler, callTrap, constructTrap, $Function.prototype)
61}
Ben Murdoch257744e2011-11-30 15:57:28 +000062
63
64
65////////////////////////////////////////////////////////////////////////////////
66// Builtins
67////////////////////////////////////////////////////////////////////////////////
68
Ben Murdoch592a9fc2012-03-05 11:04:45 +000069function DerivedConstructTrap(callTrap) {
70 return function() {
71 var proto = this.prototype
72 if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
73 var obj = new $Object()
74 obj.__proto__ = proto
75 var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
76 return IS_SPEC_OBJECT(result) ? result : obj
77 }
78}
79
Ben Murdoch589d6972011-11-30 16:04:58 +000080function DelegateCallAndConstruct(callTrap, constructTrap) {
81 return function() {
82 return %Apply(%_IsConstructCall() ? constructTrap : callTrap,
83 this, arguments, 0, %_ArgumentsLength())
84 }
85}
86
Ben Murdoch257744e2011-11-30 15:57:28 +000087function DerivedGetTrap(receiver, name) {
88 var desc = this.getPropertyDescriptor(name)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000089 if (IS_UNDEFINED(desc)) { return desc }
Ben Murdoch257744e2011-11-30 15:57:28 +000090 if ('value' in desc) {
91 return desc.value
92 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000093 if (IS_UNDEFINED(desc.get)) { return desc.get }
94 // The proposal says: desc.get.call(receiver)
95 return %_CallFunction(receiver, desc.get)
Ben Murdoch257744e2011-11-30 15:57:28 +000096 }
97}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000098
99function DerivedSetTrap(receiver, name, val) {
100 var desc = this.getOwnPropertyDescriptor(name)
101 if (desc) {
102 if ('writable' in desc) {
103 if (desc.writable) {
104 desc.value = val
105 this.defineProperty(name, desc)
106 return true
107 } else {
108 return false
109 }
110 } else { // accessor
111 if (desc.set) {
112 // The proposal says: desc.set.call(receiver, val)
113 %_CallFunction(receiver, val, desc.set)
114 return true
115 } else {
116 return false
117 }
118 }
119 }
120 desc = this.getPropertyDescriptor(name)
121 if (desc) {
122 if ('writable' in desc) {
123 if (desc.writable) {
124 // fall through
125 } else {
126 return false
127 }
128 } else { // accessor
129 if (desc.set) {
130 // The proposal says: desc.set.call(receiver, val)
131 %_CallFunction(receiver, val, desc.set)
132 return true
133 } else {
134 return false
135 }
136 }
137 }
138 this.defineProperty(name, {
139 value: val,
140 writable: true,
141 enumerable: true,
142 configurable: true});
143 return true;
144}
145
146function DerivedHasTrap(name) {
147 return !!this.getPropertyDescriptor(name)
148}
149
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000150function DerivedHasOwnTrap(name) {
151 return !!this.getOwnPropertyDescriptor(name)
152}
153
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000154function DerivedKeysTrap() {
155 var names = this.getOwnPropertyNames()
156 var enumerableNames = []
157 for (var i = 0, count = 0; i < names.length; ++i) {
158 var name = names[i]
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000159 var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name))
160 if (!IS_UNDEFINED(desc) && desc.enumerable) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000161 enumerableNames[count++] = names[i]
162 }
163 }
164 return enumerableNames
165}
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000166
167function DerivedEnumerateTrap() {
168 var names = this.getPropertyNames()
169 var enumerableNames = []
170 for (var i = 0, count = 0; i < names.length; ++i) {
171 var name = names[i]
172 var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name))
173 if (!IS_UNDEFINED(desc) && desc.enumerable) {
174 enumerableNames[count++] = names[i]
175 }
176 }
177 return enumerableNames
178}
179
180function ProxyEnumerate(proxy) {
181 var handler = %GetHandler(proxy)
182 if (IS_UNDEFINED(handler.enumerate)) {
183 return %Apply(DerivedEnumerateTrap, handler, [], 0, 0)
184 } else {
185 return ToStringArray(handler.enumerate(), "enumerate")
186 }
187}