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