proxy.js revision 589d6979ff2ef66fca2d8fa51404c369ca5e9250
1// 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
32$Proxy.create = function(handler, proto) {
33  if (!IS_SPEC_OBJECT(handler))
34    throw MakeTypeError("handler_non_object", ["create"])
35  if (!IS_SPEC_OBJECT(proto)) proto = null  // Mozilla does this...
36  return %CreateJSProxy(handler, proto)
37}
38
39$Proxy.createFunction = function(handler, callTrap, constructTrap) {
40  if (!IS_SPEC_OBJECT(handler))
41    throw MakeTypeError("handler_non_object", ["create"])
42  if (!IS_SPEC_FUNCTION(callTrap))
43    throw MakeTypeError("trap_function_expected", ["createFunction", "call"])
44  if (IS_UNDEFINED(constructTrap)) {
45    constructTrap = callTrap
46  } else if (!IS_SPEC_FUNCTION(constructTrap)) {
47    throw MakeTypeError("trap_function_expected",
48                        ["createFunction", "construct"])
49  }
50  return %CreateJSFunctionProxy(
51    handler, callTrap, constructTrap, $Function.prototype)
52}
53
54
55
56////////////////////////////////////////////////////////////////////////////////
57// Builtins
58////////////////////////////////////////////////////////////////////////////////
59
60function DelegateCallAndConstruct(callTrap, constructTrap) {
61  return function() {
62    return %Apply(%_IsConstructCall() ? constructTrap : callTrap,
63                  this, arguments, 0, %_ArgumentsLength())
64  }
65}
66
67function DerivedGetTrap(receiver, name) {
68  var desc = this.getPropertyDescriptor(name)
69  if (IS_UNDEFINED(desc)) { return desc }
70  if ('value' in desc) {
71    return desc.value
72  } else {
73    if (IS_UNDEFINED(desc.get)) { return desc.get }
74    // The proposal says: desc.get.call(receiver)
75    return %_CallFunction(receiver, desc.get)
76  }
77}
78
79function DerivedSetTrap(receiver, name, val) {
80  var desc = this.getOwnPropertyDescriptor(name)
81  if (desc) {
82    if ('writable' in desc) {
83      if (desc.writable) {
84        desc.value = val
85        this.defineProperty(name, desc)
86        return true
87      } else {
88        return false
89      }
90    } else { // accessor
91      if (desc.set) {
92        // The proposal says: desc.set.call(receiver, val)
93        %_CallFunction(receiver, val, desc.set)
94        return true
95      } else {
96        return false
97      }
98    }
99  }
100  desc = this.getPropertyDescriptor(name)
101  if (desc) {
102    if ('writable' in desc) {
103      if (desc.writable) {
104        // fall through
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  this.defineProperty(name, {
119    value: val,
120    writable: true,
121    enumerable: true,
122    configurable: true});
123  return true;
124}
125
126function DerivedHasTrap(name) {
127  return !!this.getPropertyDescriptor(name)
128}
129
130function DerivedHasOwnTrap(name) {
131  return !!this.getOwnPropertyDescriptor(name)
132}
133
134function DerivedKeysTrap() {
135  var names = this.getOwnPropertyNames()
136  var enumerableNames = []
137  for (var i = 0, count = 0; i < names.length; ++i) {
138    var name = names[i]
139    if (this.getOwnPropertyDescriptor(TO_STRING_INLINE(name)).enumerable) {
140      enumerableNames[count++] = names[i]
141    }
142  }
143  return enumerableNames
144}
145