Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "proxy/DeadObjectProxy.h"
8 :
9 : #include "jsapi.h"
10 : #include "jsfun.h" // XXXefaust Bug 1064662
11 :
12 : #include "vm/ProxyObject.h"
13 :
14 : using namespace js;
15 : using namespace js::gc;
16 :
17 : static void
18 0 : ReportDead(JSContext *cx)
19 : {
20 0 : JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
21 0 : }
22 :
23 : template <DeadProxyIsCallableIsConstructorOption CC>
24 : bool
25 0 : DeadObjectProxy<CC>::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
26 : MutableHandle<PropertyDescriptor> desc) const
27 : {
28 0 : ReportDead(cx);
29 0 : return false;
30 : }
31 :
32 : template <DeadProxyIsCallableIsConstructorOption CC>
33 : bool
34 0 : DeadObjectProxy<CC>::defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
35 : Handle<PropertyDescriptor> desc,
36 : ObjectOpResult& result) const
37 : {
38 0 : ReportDead(cx);
39 0 : return false;
40 : }
41 :
42 : template <DeadProxyIsCallableIsConstructorOption CC>
43 : bool
44 0 : DeadObjectProxy<CC>::ownPropertyKeys(JSContext* cx, HandleObject wrapper,
45 : AutoIdVector& props) const
46 : {
47 0 : ReportDead(cx);
48 0 : return false;
49 : }
50 :
51 : template <DeadProxyIsCallableIsConstructorOption CC>
52 : bool
53 0 : DeadObjectProxy<CC>::delete_(JSContext* cx, HandleObject wrapper, HandleId id,
54 : ObjectOpResult& result) const
55 : {
56 0 : ReportDead(cx);
57 0 : return false;
58 : }
59 :
60 : template <DeadProxyIsCallableIsConstructorOption CC>
61 : bool
62 0 : DeadObjectProxy<CC>::getPrototype(JSContext* cx, HandleObject proxy,
63 : MutableHandleObject protop) const
64 : {
65 0 : protop.set(nullptr);
66 0 : return true;
67 : }
68 :
69 : template <DeadProxyIsCallableIsConstructorOption CC>
70 : bool
71 0 : DeadObjectProxy<CC>::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
72 : MutableHandleObject protop) const
73 : {
74 0 : *isOrdinary = false;
75 0 : return true;
76 : }
77 :
78 : template <DeadProxyIsCallableIsConstructorOption CC>
79 : bool
80 0 : DeadObjectProxy<CC>::preventExtensions(JSContext* cx, HandleObject proxy,
81 : ObjectOpResult& result) const
82 : {
83 0 : ReportDead(cx);
84 0 : return false;
85 : }
86 :
87 : template <DeadProxyIsCallableIsConstructorOption CC>
88 : bool
89 0 : DeadObjectProxy<CC>::isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const
90 : {
91 : // This is kind of meaningless, but dead-object semantics aside,
92 : // [[Extensible]] always being true is consistent with other proxy types.
93 0 : *extensible = true;
94 0 : return true;
95 : }
96 :
97 : template <DeadProxyIsCallableIsConstructorOption CC>
98 : bool
99 0 : DeadObjectProxy<CC>::call(JSContext* cx, HandleObject wrapper, const CallArgs& args) const
100 : {
101 0 : ReportDead(cx);
102 0 : return false;
103 : }
104 :
105 : template <DeadProxyIsCallableIsConstructorOption CC>
106 : bool
107 0 : DeadObjectProxy<CC>::construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const
108 : {
109 0 : ReportDead(cx);
110 0 : return false;
111 : }
112 :
113 : template <DeadProxyIsCallableIsConstructorOption CC>
114 : bool
115 0 : DeadObjectProxy<CC>::nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
116 : const CallArgs& args) const
117 : {
118 0 : ReportDead(cx);
119 0 : return false;
120 : }
121 :
122 : template <DeadProxyIsCallableIsConstructorOption CC>
123 : bool
124 0 : DeadObjectProxy<CC>::hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
125 : bool* bp) const
126 : {
127 0 : ReportDead(cx);
128 0 : return false;
129 : }
130 :
131 : template <DeadProxyIsCallableIsConstructorOption CC>
132 : bool
133 0 : DeadObjectProxy<CC>::getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls) const
134 : {
135 0 : ReportDead(cx);
136 0 : return false;
137 : }
138 :
139 : template <DeadProxyIsCallableIsConstructorOption CC>
140 : bool
141 0 : DeadObjectProxy<CC>::isArray(JSContext* cx, HandleObject obj, JS::IsArrayAnswer* answer) const
142 : {
143 0 : ReportDead(cx);
144 0 : return false;
145 : }
146 :
147 : template <DeadProxyIsCallableIsConstructorOption CC>
148 : const char*
149 0 : DeadObjectProxy<CC>::className(JSContext* cx, HandleObject wrapper) const
150 : {
151 0 : return "DeadObject";
152 : }
153 :
154 : template <DeadProxyIsCallableIsConstructorOption CC>
155 : JSString*
156 0 : DeadObjectProxy<CC>::fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const
157 : {
158 0 : ReportDead(cx);
159 0 : return nullptr;
160 : }
161 :
162 : template <DeadProxyIsCallableIsConstructorOption CC>
163 : RegExpShared*
164 0 : DeadObjectProxy<CC>::regexp_toShared(JSContext* cx, HandleObject proxy) const
165 : {
166 0 : ReportDead(cx);
167 0 : return nullptr;
168 : }
169 :
170 : template <>
171 : const char DeadObjectProxy<DeadProxyNotCallableNotConstructor>::family = 0;
172 : template <>
173 : const char DeadObjectProxy<DeadProxyNotCallableIsConstructor>::family = 0;
174 : template <>
175 : const char DeadObjectProxy<DeadProxyIsCallableNotConstructor>::family = 0;
176 : template <>
177 : const char DeadObjectProxy<DeadProxyIsCallableIsConstructor>::family = 0;
178 :
179 : bool
180 26268 : js::IsDeadProxyObject(JSObject* obj)
181 : {
182 52482 : return IsDerivedProxyObject(obj, DeadObjectProxy<DeadProxyNotCallableNotConstructor>::singleton()) ||
183 52428 : IsDerivedProxyObject(obj, DeadObjectProxy<DeadProxyIsCallableIsConstructor>::singleton()) ||
184 78696 : IsDerivedProxyObject(obj, DeadObjectProxy<DeadProxyIsCallableNotConstructor>::singleton()) ||
185 52482 : IsDerivedProxyObject(obj, DeadObjectProxy<DeadProxyNotCallableIsConstructor>::singleton());
186 : }
187 :
188 :
189 : const BaseProxyHandler*
190 44 : js::SelectDeadProxyHandler(ProxyObject* obj)
191 : {
192 : // When nuking scripted proxies, isCallable and isConstructor values for
193 : // the proxy needs to be preserved.
194 44 : uint32_t callable = obj->handler()->isCallable(obj);
195 44 : uint32_t constructor = obj->handler()->isConstructor(obj);
196 :
197 44 : if (callable) {
198 0 : if (constructor)
199 0 : return DeadObjectProxy<DeadProxyIsCallableIsConstructor>::singleton();
200 0 : return DeadObjectProxy<DeadProxyIsCallableNotConstructor>::singleton();
201 : }
202 :
203 44 : if (constructor)
204 0 : return DeadObjectProxy<DeadProxyNotCallableIsConstructor>::singleton();
205 44 : return DeadObjectProxy<DeadProxyNotCallableNotConstructor>::singleton();
206 : }
207 :
208 : JSObject*
209 0 : js::NewDeadProxyObject(JSContext* cx, JSObject* origObj)
210 : {
211 0 : MOZ_ASSERT_IF(origObj, origObj->is<ProxyObject>());
212 :
213 : const BaseProxyHandler* handler;
214 0 : if (origObj && origObj->is<ProxyObject>())
215 0 : handler = SelectDeadProxyHandler(&origObj->as<ProxyObject>());
216 : else
217 0 : handler = DeadObjectProxy<DeadProxyNotCallableNotConstructor>::singleton();
218 :
219 0 : return NewProxyObject(cx, handler, NullHandleValue, nullptr, ProxyOptions());
220 : }
|