Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
* vim: set ts=8 sts=2 et sw=2 tw=80:
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
11
#include "vm/JSFunction.h" // XXXefaust Bug 1064662
12
#include "vm/ProxyObject.h"
13
14
using namespace js;
15
16
const DeadObjectProxy DeadObjectProxy::singleton;
17
const char DeadObjectProxy::family = 0;
18
19
static void ReportDead(JSContext* cx) {
20
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
21
}
22
23
bool DeadObjectProxy::getOwnPropertyDescriptor(
24
JSContext* cx, HandleObject wrapper, HandleId id,
25
MutableHandle<PropertyDescriptor> desc) const {
26
ReportDead(cx);
27
return false;
28
}
29
30
bool DeadObjectProxy::defineProperty(JSContext* cx, HandleObject wrapper,
31
HandleId id,
32
Handle<PropertyDescriptor> desc,
33
ObjectOpResult& result) const {
34
ReportDead(cx);
35
return false;
36
}
37
38
bool DeadObjectProxy::ownPropertyKeys(JSContext* cx, HandleObject wrapper,
39
MutableHandleIdVector props) const {
40
ReportDead(cx);
41
return false;
42
}
43
44
bool DeadObjectProxy::delete_(JSContext* cx, HandleObject wrapper, HandleId id,
45
ObjectOpResult& result) const {
46
ReportDead(cx);
47
return false;
48
}
49
50
bool DeadObjectProxy::getPrototype(JSContext* cx, HandleObject proxy,
51
MutableHandleObject protop) const {
52
protop.set(nullptr);
53
return true;
54
}
55
56
bool DeadObjectProxy::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy,
57
bool* isOrdinary,
58
MutableHandleObject protop) const {
59
*isOrdinary = false;
60
return true;
61
}
62
63
bool DeadObjectProxy::preventExtensions(JSContext* cx, HandleObject proxy,
64
ObjectOpResult& result) const {
65
ReportDead(cx);
66
return false;
67
}
68
69
bool DeadObjectProxy::isExtensible(JSContext* cx, HandleObject proxy,
70
bool* extensible) const {
71
// This is kind of meaningless, but dead-object semantics aside,
72
// [[Extensible]] always being true is consistent with other proxy types.
73
*extensible = true;
74
return true;
75
}
76
77
bool DeadObjectProxy::call(JSContext* cx, HandleObject wrapper,
78
const CallArgs& args) const {
79
ReportDead(cx);
80
return false;
81
}
82
83
bool DeadObjectProxy::construct(JSContext* cx, HandleObject wrapper,
84
const CallArgs& args) const {
85
ReportDead(cx);
86
return false;
87
}
88
89
bool DeadObjectProxy::nativeCall(JSContext* cx, IsAcceptableThis test,
90
NativeImpl impl, const CallArgs& args) const {
91
ReportDead(cx);
92
return false;
93
}
94
95
bool DeadObjectProxy::hasInstance(JSContext* cx, HandleObject proxy,
96
MutableHandleValue v, bool* bp) const {
97
ReportDead(cx);
98
return false;
99
}
100
101
bool DeadObjectProxy::getBuiltinClass(JSContext* cx, HandleObject proxy,
102
ESClass* cls) const {
103
ReportDead(cx);
104
return false;
105
}
106
107
bool DeadObjectProxy::isArray(JSContext* cx, HandleObject obj,
108
JS::IsArrayAnswer* answer) const {
109
ReportDead(cx);
110
return false;
111
}
112
113
const char* DeadObjectProxy::className(JSContext* cx,
114
HandleObject wrapper) const {
115
return "DeadObject";
116
}
117
118
JSString* DeadObjectProxy::fun_toString(JSContext* cx, HandleObject proxy,
119
bool isToSource) const {
120
ReportDead(cx);
121
return nullptr;
122
}
123
124
RegExpShared* DeadObjectProxy::regexp_toShared(JSContext* cx,
125
HandleObject proxy) const {
126
ReportDead(cx);
127
return nullptr;
128
}
129
130
bool js::IsDeadProxyObject(JSObject* obj) {
131
return IsDerivedProxyObject(obj, &DeadObjectProxy::singleton);
132
}
133
134
Value js::DeadProxyTargetValue(ProxyObject* obj) {
135
// When nuking scripted proxies, isCallable and isConstructor values for
136
// the proxy needs to be preserved. So does background-finalization status.
137
int32_t flags = 0;
138
if (obj->handler()->isCallable(obj)) {
139
flags |= DeadObjectProxyIsCallable;
140
}
141
if (obj->handler()->isConstructor(obj)) {
142
flags |= DeadObjectProxyIsConstructor;
143
}
144
if (obj->handler()->finalizeInBackground(obj->private_())) {
145
flags |= DeadObjectProxyIsBackgroundFinalized;
146
}
147
return Int32Value(flags);
148
}
149
150
JSObject* js::NewDeadProxyObject(JSContext* cx, JSObject* origObj) {
151
MOZ_ASSERT_IF(origObj, origObj->is<ProxyObject>());
152
153
RootedValue target(cx);
154
if (origObj && origObj->is<ProxyObject>()) {
155
target = DeadProxyTargetValue(&origObj->as<ProxyObject>());
156
} else {
157
target = Int32Value(DeadObjectProxyIsBackgroundFinalized);
158
}
159
160
return NewProxyObject(cx, &DeadObjectProxy::singleton, target, nullptr,
161
ProxyOptions());
162
}
163
164
JSObject* js::NewDeadProxyObject(JSContext* cx, IsCallableFlag isCallable,
165
IsConstructorFlag isConstructor) {
166
int32_t flags = 0;
167
if (isCallable == IsCallableFlag::True) {
168
flags |= DeadObjectProxyIsCallable;
169
}
170
if (isConstructor == IsConstructorFlag::True) {
171
flags |= DeadObjectProxyIsConstructor;
172
}
173
174
RootedValue target(cx, Int32Value(flags));
175
return NewProxyObject(cx, &DeadObjectProxy::singleton, target, nullptr,
176
ProxyOptions());
177
}