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