2014-05-17 03:40:36 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
* vim: set ts=4 sw=4 et tw=80:
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "WrapperOwner.h"
|
2014-05-29 05:05:22 +04:00
|
|
|
#include "JavaScriptLogging.h"
|
2016-08-23 07:09:32 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2014-05-17 03:40:36 +04:00
|
|
|
#include "mozilla/dom/BindingUtils.h"
|
|
|
|
#include "jsfriendapi.h"
|
2015-03-11 00:36:01 +03:00
|
|
|
#include "js/CharacterEncoding.h"
|
2014-05-17 03:40:36 +04:00
|
|
|
#include "xpcprivate.h"
|
2014-11-20 02:54:34 +03:00
|
|
|
#include "CPOWTimer.h"
|
2014-09-25 15:13:29 +04:00
|
|
|
#include "WrapperFactory.h"
|
2014-05-17 03:40:36 +04:00
|
|
|
|
2016-04-22 07:51:16 +03:00
|
|
|
#include "nsIDocShellTreeItem.h"
|
|
|
|
#include "nsIDOMDocument.h"
|
2014-11-05 04:40:08 +03:00
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
using namespace js;
|
|
|
|
using namespace JS;
|
|
|
|
using namespace mozilla;
|
|
|
|
using namespace mozilla::jsipc;
|
|
|
|
|
2014-11-05 04:39:34 +03:00
|
|
|
struct AuxCPOWData
|
|
|
|
{
|
|
|
|
ObjectId id;
|
|
|
|
bool isCallable;
|
|
|
|
bool isConstructor;
|
2015-03-11 00:36:01 +03:00
|
|
|
bool isDOMObject;
|
2014-11-05 04:39:34 +03:00
|
|
|
|
2014-11-05 04:40:08 +03:00
|
|
|
// The object tag is just some auxilliary information that clients can use
|
|
|
|
// however they see fit.
|
|
|
|
nsCString objectTag;
|
|
|
|
|
2015-03-27 23:12:37 +03:00
|
|
|
// The class name for WrapperOwner::className, below.
|
|
|
|
nsCString className;
|
|
|
|
|
2015-03-11 00:36:01 +03:00
|
|
|
AuxCPOWData(ObjectId id,
|
|
|
|
bool isCallable,
|
|
|
|
bool isConstructor,
|
|
|
|
bool isDOMObject,
|
2015-03-29 01:22:11 +03:00
|
|
|
const nsACString& objectTag)
|
2014-11-05 04:39:34 +03:00
|
|
|
: id(id),
|
|
|
|
isCallable(isCallable),
|
2014-11-05 04:40:08 +03:00
|
|
|
isConstructor(isConstructor),
|
2015-03-11 00:36:01 +03:00
|
|
|
isDOMObject(isDOMObject),
|
2014-11-05 04:40:08 +03:00
|
|
|
objectTag(objectTag)
|
2014-11-05 04:39:34 +03:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2016-08-11 15:39:23 +03:00
|
|
|
WrapperOwner::WrapperOwner()
|
|
|
|
: inactive_(false)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
static inline AuxCPOWData*
|
|
|
|
AuxCPOWDataOf(JSObject* obj)
|
2014-11-05 04:39:34 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsCPOW(obj));
|
2017-04-28 15:12:28 +03:00
|
|
|
return static_cast<AuxCPOWData*>(GetProxyReservedSlot(obj, 1).toPrivate());
|
2014-11-05 04:39:34 +03:00
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
static inline WrapperOwner*
|
|
|
|
OwnerOf(JSObject* obj)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsCPOW(obj));
|
2017-04-28 15:12:28 +03:00
|
|
|
return reinterpret_cast<WrapperOwner*>(GetProxyReservedSlot(obj, 0).toPrivate());
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectId
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::idOfUnchecked(JSObject* obj)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsCPOW(obj));
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
AuxCPOWData* aux = AuxCPOWDataOf(obj);
|
2014-11-05 04:39:34 +03:00
|
|
|
MOZ_ASSERT(!aux->id.isNull());
|
|
|
|
return aux->id;
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
2014-09-24 15:54:11 +04:00
|
|
|
ObjectId
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::idOf(JSObject* obj)
|
2014-09-24 15:54:11 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOfUnchecked(obj);
|
2016-02-07 20:08:55 +03:00
|
|
|
MOZ_ASSERT(hasCPOW(objId, obj));
|
2014-09-24 15:54:11 +04:00
|
|
|
return objId;
|
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
class CPOWProxyHandler : public BaseProxyHandler
|
|
|
|
{
|
|
|
|
public:
|
2016-07-09 00:39:53 +03:00
|
|
|
constexpr CPOWProxyHandler()
|
2014-08-28 04:09:06 +04:00
|
|
|
: BaseProxyHandler(&family) {}
|
2014-05-17 03:40:36 +04:00
|
|
|
|
2016-09-11 12:15:23 +03:00
|
|
|
virtual bool finalizeInBackground(const Value& priv) const override {
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
2016-01-28 13:28:04 +03:00
|
|
|
MutableHandle<PropertyDescriptor> desc) const override;
|
2015-03-29 01:22:11 +03:00
|
|
|
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
2016-01-28 13:28:04 +03:00
|
|
|
Handle<PropertyDescriptor> desc,
|
2015-03-29 01:22:11 +03:00
|
|
|
ObjectOpResult& result) const override;
|
|
|
|
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
|
|
|
|
AutoIdVector& props) const override;
|
|
|
|
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
|
|
|
ObjectOpResult& result) const override;
|
2017-06-29 07:00:43 +03:00
|
|
|
virtual JSObject* enumerate(JSContext* cx, HandleObject proxy) const override;
|
2015-03-29 01:22:11 +03:00
|
|
|
virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
|
|
|
|
ObjectOpResult& result) const override;
|
|
|
|
virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
|
|
|
|
virtual bool has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
|
2015-09-18 01:14:41 +03:00
|
|
|
virtual bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
2015-03-21 19:28:04 +03:00
|
|
|
HandleId id, MutableHandleValue vp) const override;
|
2015-03-29 01:22:11 +03:00
|
|
|
virtual bool set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
|
|
|
|
JS::HandleValue receiver, JS::ObjectOpResult& result) const override;
|
|
|
|
virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
|
|
|
|
virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
|
2014-10-08 21:09:08 +04:00
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
2016-01-28 13:28:04 +03:00
|
|
|
MutableHandle<PropertyDescriptor> desc) const override;
|
2015-03-29 01:22:11 +03:00
|
|
|
virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
|
|
|
|
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
|
|
|
|
AutoIdVector& props) const override;
|
|
|
|
virtual bool hasInstance(JSContext* cx, HandleObject proxy,
|
|
|
|
MutableHandleValue v, bool* bp) const override;
|
2016-06-30 01:04:56 +03:00
|
|
|
virtual bool getBuiltinClass(JSContext* cx, HandleObject obj, js::ESClass* cls) const override;
|
2015-08-23 11:10:24 +03:00
|
|
|
virtual bool isArray(JSContext* cx, HandleObject obj,
|
|
|
|
IsArrayAnswer* answer) const override;
|
2015-03-29 01:22:11 +03:00
|
|
|
virtual const char* className(JSContext* cx, HandleObject proxy) const override;
|
2017-07-11 13:59:09 +03:00
|
|
|
virtual bool regexp_toShared(JSContext* cx, HandleObject proxy,
|
|
|
|
MutableHandle<RegExpShared*> shared) const override;
|
2015-03-29 01:22:11 +03:00
|
|
|
virtual void finalize(JSFreeOp* fop, JSObject* proxy) const override;
|
|
|
|
virtual void objectMoved(JSObject* proxy, const JSObject* old) const override;
|
|
|
|
virtual bool isCallable(JSObject* obj) const override;
|
|
|
|
virtual bool isConstructor(JSObject* obj) const override;
|
|
|
|
virtual bool getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject protop) const override;
|
2016-02-24 00:42:30 +03:00
|
|
|
virtual bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
|
|
|
|
MutableHandleObject protop) const override;
|
2014-05-17 03:40:36 +04:00
|
|
|
|
2014-08-28 04:09:06 +04:00
|
|
|
static const char family;
|
2014-06-27 15:44:04 +04:00
|
|
|
static const CPOWProxyHandler singleton;
|
2014-05-17 03:40:36 +04:00
|
|
|
};
|
|
|
|
|
2014-08-28 04:09:06 +04:00
|
|
|
const char CPOWProxyHandler::family = 0;
|
2014-06-27 15:44:04 +04:00
|
|
|
const CPOWProxyHandler CPOWProxyHandler::singleton;
|
2014-05-17 03:40:36 +04:00
|
|
|
|
2017-07-11 13:59:09 +03:00
|
|
|
#define FORWARD(call, args) \
|
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
|
|
|
AUTO_PROFILER_LABEL(__func__, JS); \
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner* owner = OwnerOf(proxy); \
|
2014-05-17 03:40:36 +04:00
|
|
|
if (!owner->active()) { \
|
2016-08-14 14:39:28 +03:00
|
|
|
JS_ReportErrorASCII(cx, "cannot use a CPOW whose process is gone"); \
|
2017-07-11 13:59:09 +03:00
|
|
|
return false; \
|
2014-05-17 03:40:36 +04:00
|
|
|
} \
|
2015-10-24 02:31:54 +03:00
|
|
|
if (!owner->allowMessage(cx)) { \
|
2017-07-11 13:59:09 +03:00
|
|
|
return false; \
|
2015-10-24 02:31:54 +03:00
|
|
|
} \
|
2014-11-20 02:54:34 +03:00
|
|
|
{ \
|
2015-06-04 14:12:07 +03:00
|
|
|
CPOWTimer timer(cx); \
|
2014-11-20 02:54:34 +03:00
|
|
|
return owner->call args; \
|
|
|
|
}
|
2014-05-17 03:40:36 +04:00
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
2016-01-28 13:28:04 +03:00
|
|
|
MutableHandle<PropertyDescriptor> desc) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(getPropertyDescriptor, (cx, proxy, id, desc));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
2016-01-28 13:28:04 +03:00
|
|
|
MutableHandle<PropertyDescriptor> desc)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
2014-10-07 13:29:02 +04:00
|
|
|
JSIDVariant idVar;
|
|
|
|
if (!toJSIDVariant(cx, id, &idVar))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ReturnStatus status;
|
|
|
|
PPropertyDescriptor result;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendGetPropertyDescriptor(objId, idVar, &status, &result))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
2014-05-29 05:05:22 +04:00
|
|
|
|
|
|
|
LOG_STACK();
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
if (!ok(cx, status))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return toDescriptor(cx, result, desc);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
2016-01-28 13:28:04 +03:00
|
|
|
MutableHandle<PropertyDescriptor> desc) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(getOwnPropertyDescriptor, (cx, proxy, id, desc));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
|
2016-01-28 13:28:04 +03:00
|
|
|
MutableHandle<PropertyDescriptor> desc)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
2014-10-07 13:29:02 +04:00
|
|
|
JSIDVariant idVar;
|
|
|
|
if (!toJSIDVariant(cx, id, &idVar))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ReturnStatus status;
|
|
|
|
PPropertyDescriptor result;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendGetOwnPropertyDescriptor(objId, idVar, &status, &result))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
2014-05-29 05:05:22 +04:00
|
|
|
|
|
|
|
LOG_STACK();
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
if (!ok(cx, status))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return toDescriptor(cx, result, desc);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
2016-01-28 13:28:04 +03:00
|
|
|
Handle<PropertyDescriptor> desc,
|
2015-03-29 01:22:11 +03:00
|
|
|
ObjectOpResult& result) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(defineProperty, (cx, proxy, id, desc, result));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
|
2016-01-28 13:28:04 +03:00
|
|
|
Handle<PropertyDescriptor> desc,
|
2015-03-29 01:22:11 +03:00
|
|
|
ObjectOpResult& result)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
2014-10-07 13:29:02 +04:00
|
|
|
JSIDVariant idVar;
|
|
|
|
if (!toJSIDVariant(cx, id, &idVar))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
PPropertyDescriptor descriptor;
|
|
|
|
if (!fromDescriptor(cx, desc, &descriptor))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendDefineProperty(objId, idVar, descriptor, &status))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
2014-05-29 05:05:22 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
2015-01-30 20:37:07 +03:00
|
|
|
return ok(cx, status, result);
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject proxy,
|
|
|
|
AutoIdVector& props) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(ownPropertyKeys, (cx, proxy, props));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::ownPropertyKeys(JSContext* cx, HandleObject proxy, AutoIdVector& props)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2014-10-16 20:39:38 +04:00
|
|
|
return getPropertyKeys(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, props);
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::delete_(JSContext* cx, HandleObject proxy, HandleId id,
|
|
|
|
ObjectOpResult& result) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(delete_, (cx, proxy, id, result));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::delete_(JSContext* cx, HandleObject proxy, HandleId id, ObjectOpResult& result)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
2014-10-07 13:29:02 +04:00
|
|
|
JSIDVariant idVar;
|
|
|
|
if (!toJSIDVariant(cx, id, &idVar))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2015-02-04 19:20:04 +03:00
|
|
|
if (!SendDelete(objId, idVar, &status))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
2014-05-29 05:05:22 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
2015-02-04 19:20:04 +03:00
|
|
|
return ok(cx, status, result);
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
2017-06-29 07:00:43 +03:00
|
|
|
JSObject*
|
|
|
|
CPOWProxyHandler::enumerate(JSContext* cx, HandleObject proxy) const
|
2014-12-17 02:28:38 +03:00
|
|
|
{
|
|
|
|
// Using a CPOW for the Iterator would slow down for .. in performance, instead
|
2014-12-17 02:28:38 +03:00
|
|
|
// call the base hook, that will use our implementation of getOwnEnumerablePropertyKeys
|
|
|
|
// and follow the proto chain.
|
2017-06-29 07:00:43 +03:00
|
|
|
return BaseProxyHandler::enumerate(cx, proxy);
|
2014-12-17 02:28:38 +03:00
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(has, (cx, proxy, id, bp));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
2014-10-07 13:29:02 +04:00
|
|
|
JSIDVariant idVar;
|
|
|
|
if (!toJSIDVariant(cx, id, &idVar))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendHas(objId, idVar, &status, bp))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
2014-05-29 05:05:22 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
return ok(cx, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(hasOwn, (cx, proxy, id, bp));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
2014-10-07 13:29:02 +04:00
|
|
|
JSIDVariant idVar;
|
|
|
|
if (!toJSIDVariant(cx, id, &idVar))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendHasOwn(objId, idVar, &status, bp))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
2014-05-29 05:05:22 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
return !!ok(cx, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-09-18 01:14:41 +03:00
|
|
|
CPOWProxyHandler::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
2014-06-27 15:44:06 +04:00
|
|
|
HandleId id, MutableHandleValue vp) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(get, (cx, proxy, receiver, id, vp));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
2015-03-11 00:36:01 +03:00
|
|
|
static bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWDOMQI(JSContext* cx, unsigned argc, Value* vp)
|
2015-03-11 00:36:01 +03:00
|
|
|
{
|
|
|
|
CallArgs args = CallArgsFromVp(argc, vp);
|
|
|
|
if (!args.thisv().isObject() || !IsCPOW(&args.thisv().toObject())) {
|
2016-08-14 14:39:28 +03:00
|
|
|
JS_ReportErrorASCII(cx, "bad this object passed to special QI");
|
2015-03-11 00:36:01 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RootedObject proxy(cx, &args.thisv().toObject());
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(DOMQI, (cx, proxy, args));
|
2015-03-11 00:36:01 +03:00
|
|
|
}
|
|
|
|
|
2014-05-29 05:05:23 +04:00
|
|
|
static bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWToString(JSContext* cx, unsigned argc, Value* vp)
|
2014-05-29 05:05:23 +04:00
|
|
|
{
|
|
|
|
CallArgs args = CallArgsFromVp(argc, vp);
|
|
|
|
RootedObject callee(cx, &args.callee());
|
|
|
|
RootedValue cpowValue(cx);
|
2014-12-17 02:28:39 +03:00
|
|
|
if (!JS_GetProperty(cx, callee, "__cpow__", &cpowValue))
|
2014-05-29 05:05:23 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!cpowValue.isObject() || !IsCPOW(&cpowValue.toObject())) {
|
2016-08-14 14:39:28 +03:00
|
|
|
JS_ReportErrorASCII(cx, "CPOWToString called on an incompatible object");
|
2014-05-29 05:05:23 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RootedObject proxy(cx, &cpowValue.toObject());
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(toString, (cx, proxy, args));
|
2014-05-29 05:05:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::toString(JSContext* cx, HandleObject cpow, JS::CallArgs& args)
|
2014-05-29 05:05:23 +04:00
|
|
|
{
|
|
|
|
// Ask the other side to call its toString method. Update the callee so that
|
|
|
|
// it points to the CPOW and not to the synthesized CPOWToString function.
|
|
|
|
args.setCallee(ObjectValue(*cpow));
|
2014-07-01 04:50:58 +04:00
|
|
|
if (!callOrConstruct(cx, cpow, args, false))
|
2014-05-29 05:05:23 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!args.rval().isString())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
RootedString cpowResult(cx, args.rval().toString());
|
2014-07-05 19:30:54 +04:00
|
|
|
nsAutoJSString toStringResult;
|
2014-05-29 05:05:23 +04:00
|
|
|
if (!toStringResult.init(cx, cpowResult))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We don't want to wrap toString() results for things like the location
|
|
|
|
// object, where toString() is supposed to return a URL and nothing else.
|
|
|
|
nsAutoString result;
|
|
|
|
if (toStringResult[0] == '[') {
|
|
|
|
result.AppendLiteral("[object CPOW ");
|
|
|
|
result += toStringResult;
|
|
|
|
result.AppendLiteral("]");
|
|
|
|
} else {
|
|
|
|
result += toStringResult;
|
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
JSString* str = JS_NewUCStringCopyN(cx, result.get(), result.Length());
|
2014-05-29 05:05:23 +04:00
|
|
|
if (!str)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
args.rval().setString(str);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-03-11 00:36:01 +03:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::DOMQI(JSContext* cx, JS::HandleObject proxy, JS::CallArgs& args)
|
2015-03-11 00:36:01 +03:00
|
|
|
{
|
|
|
|
// Someone's calling us, handle nsISupports specially to avoid unnecessary
|
|
|
|
// CPOW traffic.
|
|
|
|
HandleValue id = args[0];
|
|
|
|
if (id.isObject()) {
|
|
|
|
RootedObject idobj(cx, &id.toObject());
|
|
|
|
nsCOMPtr<nsIJSID> jsid;
|
|
|
|
|
2017-02-01 23:43:37 +03:00
|
|
|
nsresult rv = UnwrapArg<nsIJSID>(cx, idobj, getter_AddRefs(jsid));
|
2015-03-11 00:36:01 +03:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
MOZ_ASSERT(jsid, "bad wrapJS");
|
2015-03-29 01:22:11 +03:00
|
|
|
const nsID* idptr = jsid->GetID();
|
2015-03-11 00:36:01 +03:00
|
|
|
if (idptr->Equals(NS_GET_IID(nsISupports))) {
|
|
|
|
args.rval().set(args.thisv());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Webidl-implemented DOM objects never have nsIClassInfo.
|
|
|
|
if (idptr->Equals(NS_GET_IID(nsIClassInfo)))
|
|
|
|
return Throw(cx, NS_ERROR_NO_INTERFACE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// It wasn't nsISupports, call into the other process to do the QI for us
|
|
|
|
// (since we don't know what other interfaces our object supports). Note
|
|
|
|
// that we have to use JS_GetPropertyDescriptor here to avoid infinite
|
|
|
|
// recursion back into CPOWDOMQI via WrapperOwner::get().
|
|
|
|
// We could stash the actual QI function on our own function object to avoid
|
|
|
|
// if we're called multiple times, but since we're transient, there's no
|
|
|
|
// point right now.
|
2016-01-28 13:28:04 +03:00
|
|
|
JS::Rooted<PropertyDescriptor> propDesc(cx);
|
2015-03-11 00:36:01 +03:00
|
|
|
if (!JS_GetPropertyDescriptor(cx, proxy, "QueryInterface", &propDesc))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!propDesc.value().isObject()) {
|
|
|
|
MOZ_ASSERT_UNREACHABLE("We didn't get QueryInterface off a node");
|
|
|
|
return Throw(cx, NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
return JS_CallFunctionValue(cx, proxy, propDesc.value(), args, args.rval());
|
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
bool
|
2015-09-18 01:14:41 +03:00
|
|
|
WrapperOwner::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
|
2014-10-07 13:29:02 +04:00
|
|
|
HandleId id, MutableHandleValue vp)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
2014-07-01 04:48:09 +04:00
|
|
|
|
2015-09-18 01:14:41 +03:00
|
|
|
JSVariant receiverVar;
|
|
|
|
if (!toVariant(cx, receiver, &receiverVar))
|
2014-07-01 04:48:09 +04:00
|
|
|
return false;
|
2014-05-17 03:40:36 +04:00
|
|
|
|
2014-10-07 13:29:02 +04:00
|
|
|
JSIDVariant idVar;
|
|
|
|
if (!toJSIDVariant(cx, id, &idVar))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
AuxCPOWData* data = AuxCPOWDataOf(proxy);
|
2015-03-11 00:36:01 +03:00
|
|
|
if (data->isDOMObject &&
|
|
|
|
idVar.type() == JSIDVariant::TnsString &&
|
|
|
|
idVar.get_nsString().EqualsLiteral("QueryInterface"))
|
|
|
|
{
|
|
|
|
// Handle QueryInterface on DOM Objects specially since we can assume
|
|
|
|
// certain things about their implementation.
|
|
|
|
RootedFunction qi(cx, JS_NewFunction(cx, CPOWDOMQI, 1, 0,
|
|
|
|
"QueryInterface"));
|
|
|
|
if (!qi)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
vp.set(ObjectValue(*JS_GetFunctionObject(qi)));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
JSVariant val;
|
|
|
|
ReturnStatus status;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendGet(objId, receiverVar, idVar, &status, &val))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
2014-05-29 05:05:22 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
if (!ok(cx, status))
|
|
|
|
return false;
|
|
|
|
|
2014-05-29 05:05:23 +04:00
|
|
|
if (!fromVariant(cx, val, vp))
|
|
|
|
return false;
|
|
|
|
|
2014-10-07 13:29:02 +04:00
|
|
|
if (idVar.type() == JSIDVariant::TnsString &&
|
|
|
|
idVar.get_nsString().EqualsLiteral("toString")) {
|
2015-03-09 19:50:03 +03:00
|
|
|
RootedFunction toString(cx, JS_NewFunction(cx, CPOWToString, 0, 0,
|
|
|
|
"toString"));
|
2014-05-29 05:05:23 +04:00
|
|
|
if (!toString)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
RootedObject toStringObj(cx, JS_GetFunctionObject(toString));
|
|
|
|
|
|
|
|
if (!JS_DefineProperty(cx, toStringObj, "__cpow__", vp, JSPROP_PERMANENT | JSPROP_READONLY))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
vp.set(ObjectValue(*toStringObj));
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
|
|
|
|
JS::HandleValue receiver, JS::ObjectOpResult& result) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(set, (cx, proxy, id, v, receiver, result));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
|
|
|
|
JS::HandleValue receiver, JS::ObjectOpResult& result)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
2014-07-01 04:48:09 +04:00
|
|
|
|
2014-10-07 13:29:02 +04:00
|
|
|
JSIDVariant idVar;
|
|
|
|
if (!toJSIDVariant(cx, id, &idVar))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
JSVariant val;
|
Bug 1142794 - Change 'receiver' argument to SetProperty functions and ProxyHandler::set methods to be a HandleValue. r=Waldo.
Also: Change signature of these functions and methods to all have the same arguments in the same order: (cx, obj, id, v, receiver). Also change v from MutableHandleValue to HandleValue.
There is no change in behavior.
In fact the new error message `JSMSG_SET_NON_OBJECT_RECEIVER` is
impossible to trigger from scripts for now, I think (after re-reading
the whole patch with this in mind). JS_ForwardSetPropertyTo is the only
way to get a non-object receiver into the engine, but no caller
currently does so.
We're installing new pipes here, and they should work, but for now it's
the same cold water flowing through as before. Actually hooking up the
hot water is left for another bug (one with tests, not to put too fine a
point on it).
Notes:
* InvokeGetterOrSetter had to be split into two functions:
InvokeGetter takes a MutableHandleValue out-param,
InvokeSetter a HandleValue in-param.
* Watchpoints can still tamper with values being assigned. So can
JSSetterOps. I'm pleased we can support this craziness in a way that
doesn't have to spread via the type system to encompass the entire
codebase.
* Change in GlobalObject::setIntrinsicValue is not really a change.
Yes, it asserted before, but an exception thrown during self-hosting
initialization is not going to go unnoticed either.
* Since the receiver argument to js::SetProperty() is at the end now, it
makes sense for it to be optional. Some callers look nicer.
--HG--
extra : rebase_source : e89f916fe267800bc73890e11aceef5c4855b272
2015-03-01 22:16:19 +03:00
|
|
|
if (!toVariant(cx, v, &val))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
JSVariant receiverVar;
|
|
|
|
if (!toVariant(cx, receiver, &receiverVar))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ReturnStatus status;
|
Bug 1142794 - Change 'receiver' argument to SetProperty functions and ProxyHandler::set methods to be a HandleValue. r=Waldo.
Also: Change signature of these functions and methods to all have the same arguments in the same order: (cx, obj, id, v, receiver). Also change v from MutableHandleValue to HandleValue.
There is no change in behavior.
In fact the new error message `JSMSG_SET_NON_OBJECT_RECEIVER` is
impossible to trigger from scripts for now, I think (after re-reading
the whole patch with this in mind). JS_ForwardSetPropertyTo is the only
way to get a non-object receiver into the engine, but no caller
currently does so.
We're installing new pipes here, and they should work, but for now it's
the same cold water flowing through as before. Actually hooking up the
hot water is left for another bug (one with tests, not to put too fine a
point on it).
Notes:
* InvokeGetterOrSetter had to be split into two functions:
InvokeGetter takes a MutableHandleValue out-param,
InvokeSetter a HandleValue in-param.
* Watchpoints can still tamper with values being assigned. So can
JSSetterOps. I'm pleased we can support this craziness in a way that
doesn't have to spread via the type system to encompass the entire
codebase.
* Change in GlobalObject::setIntrinsicValue is not really a change.
Yes, it asserted before, but an exception thrown during self-hosting
initialization is not going to go unnoticed either.
* Since the receiver argument to js::SetProperty() is at the end now, it
makes sense for it to be optional. Some callers look nicer.
--HG--
extra : rebase_source : e89f916fe267800bc73890e11aceef5c4855b272
2015-03-01 22:16:19 +03:00
|
|
|
if (!SendSet(objId, idVar, val, receiverVar, &status))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
2014-05-29 05:05:22 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
Bug 1142794 - Change 'receiver' argument to SetProperty functions and ProxyHandler::set methods to be a HandleValue. r=Waldo.
Also: Change signature of these functions and methods to all have the same arguments in the same order: (cx, obj, id, v, receiver). Also change v from MutableHandleValue to HandleValue.
There is no change in behavior.
In fact the new error message `JSMSG_SET_NON_OBJECT_RECEIVER` is
impossible to trigger from scripts for now, I think (after re-reading
the whole patch with this in mind). JS_ForwardSetPropertyTo is the only
way to get a non-object receiver into the engine, but no caller
currently does so.
We're installing new pipes here, and they should work, but for now it's
the same cold water flowing through as before. Actually hooking up the
hot water is left for another bug (one with tests, not to put too fine a
point on it).
Notes:
* InvokeGetterOrSetter had to be split into two functions:
InvokeGetter takes a MutableHandleValue out-param,
InvokeSetter a HandleValue in-param.
* Watchpoints can still tamper with values being assigned. So can
JSSetterOps. I'm pleased we can support this craziness in a way that
doesn't have to spread via the type system to encompass the entire
codebase.
* Change in GlobalObject::setIntrinsicValue is not really a change.
Yes, it asserted before, but an exception thrown during self-hosting
initialization is not going to go unnoticed either.
* Since the receiver argument to js::SetProperty() is at the end now, it
makes sense for it to be optional. Some callers look nicer.
--HG--
extra : rebase_source : e89f916fe267800bc73890e11aceef5c4855b272
2015-03-01 22:16:19 +03:00
|
|
|
return ok(cx, status, result);
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
|
|
|
|
AutoIdVector& props) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(getOwnEnumerablePropertyKeys, (cx, proxy, props));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy, AutoIdVector& props)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2014-09-27 00:16:36 +04:00
|
|
|
return getPropertyKeys(cx, proxy, JSITER_OWNONLY, props);
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
2014-10-21 22:40:04 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::preventExtensions(JSContext* cx, HandleObject proxy, ObjectOpResult& result) const
|
2014-10-21 22:40:04 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(preventExtensions, (cx, proxy, result));
|
2014-10-21 22:40:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::preventExtensions(JSContext* cx, HandleObject proxy, ObjectOpResult& result)
|
2014-10-21 22:40:04 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2015-02-04 21:01:01 +03:00
|
|
|
if (!SendPreventExtensions(objId, &status))
|
2014-10-21 22:40:04 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
|
|
|
LOG_STACK();
|
|
|
|
|
2015-02-04 21:01:01 +03:00
|
|
|
return ok(cx, status, result);
|
2014-10-21 22:40:04 +04:00
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(isExtensible, (cx, proxy, extensible));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::isExtensible(JSContext* cx, HandleObject proxy, bool* extensible)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendIsExtensible(objId, &status, extensible))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
2014-05-29 05:05:22 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
return ok(cx, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::call(JSContext* cx, HandleObject proxy, const CallArgs& args) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(callOrConstruct, (cx, proxy, args, false));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const
|
2014-07-01 04:50:58 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(callOrConstruct, (cx, proxy, args, true));
|
2014-07-01 04:50:58 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::callOrConstruct(JSContext* cx, HandleObject proxy, const CallArgs& args,
|
2014-07-01 04:50:58 +04:00
|
|
|
bool construct)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
|
|
|
InfallibleTArray<JSParam> vals;
|
|
|
|
AutoValueVector outobjects(cx);
|
|
|
|
|
|
|
|
RootedValue v(cx);
|
|
|
|
for (size_t i = 0; i < args.length() + 2; i++) {
|
2014-07-01 04:50:58 +04:00
|
|
|
// The |this| value for constructors is a magic value that we won't be
|
|
|
|
// able to convert, so skip it.
|
|
|
|
if (i == 1 && construct)
|
|
|
|
v = UndefinedValue();
|
|
|
|
else
|
|
|
|
v = args.base()[i];
|
2014-05-17 03:40:36 +04:00
|
|
|
if (v.isObject()) {
|
|
|
|
RootedObject obj(cx, &v.toObject());
|
|
|
|
if (xpc::IsOutObject(cx, obj)) {
|
|
|
|
// Make sure it is not an in-out object.
|
|
|
|
bool found;
|
|
|
|
if (!JS_HasProperty(cx, obj, "value", &found))
|
|
|
|
return false;
|
|
|
|
if (found) {
|
2016-08-14 14:39:28 +03:00
|
|
|
JS_ReportErrorASCII(cx, "in-out objects cannot be sent via CPOWs yet");
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
vals.AppendElement(JSParam(void_t()));
|
|
|
|
if (!outobjects.append(ObjectValue(*obj)))
|
|
|
|
return false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
JSVariant val;
|
|
|
|
if (!toVariant(cx, v, &val))
|
|
|
|
return false;
|
|
|
|
vals.AppendElement(JSParam(val));
|
|
|
|
}
|
|
|
|
|
|
|
|
JSVariant result;
|
|
|
|
ReturnStatus status;
|
|
|
|
InfallibleTArray<JSParam> outparams;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendCallOrConstruct(objId, vals, construct, &status, &result, &outparams))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
2014-05-29 05:05:22 +04:00
|
|
|
|
|
|
|
LOG_STACK();
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
if (!ok(cx, status))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (outparams.Length() != outobjects.length())
|
|
|
|
return ipcfail(cx);
|
|
|
|
|
|
|
|
RootedObject obj(cx);
|
|
|
|
for (size_t i = 0; i < outparams.Length(); i++) {
|
|
|
|
// Don't bother doing anything for outparams that weren't set.
|
|
|
|
if (outparams[i].type() == JSParam::Tvoid_t)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Take the value the child process returned, and set it on the XPC
|
|
|
|
// object.
|
|
|
|
if (!fromVariant(cx, outparams[i], &v))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
obj = &outobjects[i].toObject();
|
|
|
|
if (!JS_SetProperty(cx, obj, "value", v))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fromVariant(cx, result, args.rval()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-09-11 04:15:40 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v, bool* bp) const
|
2014-09-11 04:15:40 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(hasInstance, (cx, proxy, v, bp));
|
2014-09-11 04:15:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v, bool* bp)
|
2014-09-11 04:15:40 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
|
|
|
JSVariant vVar;
|
|
|
|
if (!toVariant(cx, v, &vVar))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendHasInstance(objId, vVar, &status, bp))
|
2014-09-11 04:15:40 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
|
|
|
LOG_STACK();
|
|
|
|
|
|
|
|
return ok(cx, status);
|
|
|
|
}
|
2014-05-17 03:40:36 +04:00
|
|
|
|
|
|
|
bool
|
2016-06-30 01:04:56 +03:00
|
|
|
CPOWProxyHandler::getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(getBuiltinClass, (cx, proxy, cls));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2016-06-30 01:04:56 +03:00
|
|
|
WrapperOwner::getBuiltinClass(JSContext* cx, HandleObject proxy, ESClass* cls)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
2016-06-30 01:04:56 +03:00
|
|
|
uint32_t classValue = uint32_t(ESClass::Other);
|
2015-08-29 07:55:40 +03:00
|
|
|
ReturnStatus status;
|
2016-06-30 01:04:56 +03:00
|
|
|
if (!SendGetBuiltinClass(objId, &status, &classValue))
|
2015-08-29 07:55:40 +03:00
|
|
|
return ipcfail(cx);
|
2016-06-30 01:04:56 +03:00
|
|
|
*cls = ESClass(classValue);
|
2014-05-17 03:40:36 +04:00
|
|
|
|
2014-05-29 05:05:22 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
2015-08-29 07:55:40 +03:00
|
|
|
return ok(cx, status);
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
2015-08-23 11:10:24 +03:00
|
|
|
bool
|
|
|
|
CPOWProxyHandler::isArray(JSContext* cx, HandleObject proxy,
|
|
|
|
IsArrayAnswer* answer) const
|
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(isArray, (cx, proxy, answer));
|
2015-08-23 11:10:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
WrapperOwner::isArray(JSContext* cx, HandleObject proxy, IsArrayAnswer* answer)
|
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
|
|
|
uint32_t ans;
|
|
|
|
ReturnStatus status;
|
|
|
|
if (!SendIsArray(objId, &status, &ans))
|
|
|
|
return ipcfail(cx);
|
|
|
|
|
|
|
|
LOG_STACK();
|
|
|
|
|
|
|
|
*answer = IsArrayAnswer(ans);
|
|
|
|
MOZ_ASSERT(*answer == IsArrayAnswer::Array ||
|
|
|
|
*answer == IsArrayAnswer::NotArray ||
|
|
|
|
*answer == IsArrayAnswer::RevokedProxy);
|
|
|
|
|
|
|
|
return ok(cx, status);
|
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
const char*
|
|
|
|
CPOWProxyHandler::className(JSContext* cx, HandleObject proxy) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner* parent = OwnerOf(proxy);
|
2014-05-17 03:40:36 +04:00
|
|
|
if (!parent->active())
|
|
|
|
return "<dead CPOW>";
|
|
|
|
return parent->className(cx, proxy);
|
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
const char*
|
|
|
|
WrapperOwner::className(JSContext* cx, HandleObject proxy)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
AuxCPOWData* data = AuxCPOWDataOf(proxy);
|
2015-03-27 23:12:37 +03:00
|
|
|
if (data->className.IsEmpty()) {
|
|
|
|
ObjectId objId = idOf(proxy);
|
2014-05-17 03:40:36 +04:00
|
|
|
|
2015-03-27 23:12:37 +03:00
|
|
|
if (!SendClassName(objId, &data->className))
|
|
|
|
return "<error>";
|
2014-05-17 03:40:36 +04:00
|
|
|
|
2015-03-27 23:12:37 +03:00
|
|
|
LOG_STACK();
|
|
|
|
}
|
2014-05-29 05:05:22 +04:00
|
|
|
|
2015-03-27 23:12:37 +03:00
|
|
|
return data->className.get();
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
2015-02-10 18:29:41 +03:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const
|
2015-02-10 18:29:41 +03:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(getPrototype, (cx, proxy, objp));
|
2015-02-10 18:29:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject objp)
|
2015-02-10 18:29:41 +03:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
|
|
|
ObjectOrNullVariant val;
|
|
|
|
ReturnStatus status;
|
2015-02-06 01:36:50 +03:00
|
|
|
if (!SendGetPrototype(objId, &status, &val))
|
2015-02-10 18:29:41 +03:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
|
|
|
LOG_STACK();
|
|
|
|
|
|
|
|
if (!ok(cx, status))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
objp.set(fromObjectOrNullVariant(cx, val));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-02-24 00:42:30 +03:00
|
|
|
bool
|
|
|
|
CPOWProxyHandler::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
|
|
|
|
MutableHandleObject objp) const
|
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(getPrototypeIfOrdinary, (cx, proxy, isOrdinary, objp));
|
2016-02-24 00:42:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
WrapperOwner::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
|
|
|
|
MutableHandleObject objp)
|
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
|
|
|
ObjectOrNullVariant val;
|
|
|
|
ReturnStatus status;
|
|
|
|
if (!SendGetPrototypeIfOrdinary(objId, &status, isOrdinary, &val))
|
|
|
|
return ipcfail(cx);
|
|
|
|
|
|
|
|
LOG_STACK();
|
|
|
|
|
|
|
|
if (!ok(cx, status))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
objp.set(fromObjectOrNullVariant(cx, val));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-07-11 13:59:09 +03:00
|
|
|
bool
|
|
|
|
CPOWProxyHandler::regexp_toShared(JSContext* cx, HandleObject proxy,
|
|
|
|
MutableHandle<RegExpShared*> shared) const
|
2014-10-01 19:22:15 +04:00
|
|
|
{
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(regexp_toShared, (cx, proxy, shared));
|
2014-10-01 19:22:15 +04:00
|
|
|
}
|
|
|
|
|
2017-07-11 13:59:09 +03:00
|
|
|
bool
|
|
|
|
WrapperOwner::regexp_toShared(JSContext* cx, HandleObject proxy, MutableHandle<RegExpShared*> shared)
|
2014-10-01 19:22:15 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
|
|
|
ReturnStatus status;
|
|
|
|
nsString source;
|
|
|
|
unsigned flags = 0;
|
2017-07-11 13:59:09 +03:00
|
|
|
if (!SendRegExpToShared(objId, &status, &source, &flags))
|
|
|
|
return ipcfail(cx);
|
|
|
|
|
2014-10-01 19:22:15 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
|
|
|
if (!ok(cx, status))
|
2017-07-11 13:59:09 +03:00
|
|
|
return false;
|
2014-10-01 19:22:15 +04:00
|
|
|
|
|
|
|
RootedObject regexp(cx);
|
2015-11-25 16:38:05 +03:00
|
|
|
regexp = JS_NewUCRegExpObject(cx, source.get(), source.Length(), flags);
|
2014-10-01 19:22:15 +04:00
|
|
|
if (!regexp)
|
2017-07-11 13:59:09 +03:00
|
|
|
return false;
|
2014-10-01 19:22:15 +04:00
|
|
|
|
2017-07-11 13:59:09 +03:00
|
|
|
return js::RegExpToSharedNonInline(cx, regexp, shared);
|
2014-10-01 19:22:15 +04:00
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
void
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::finalize(JSFreeOp* fop, JSObject* proxy) const
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
AuxCPOWData* aux = AuxCPOWDataOf(proxy);
|
2014-11-06 04:52:38 +03:00
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
OwnerOf(proxy)->drop(proxy);
|
2014-11-05 04:39:34 +03:00
|
|
|
|
|
|
|
if (aux)
|
|
|
|
delete aux;
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
2014-09-24 15:54:11 +04:00
|
|
|
void
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::objectMoved(JSObject* proxy, const JSObject* old) const
|
2014-09-24 15:54:11 +04:00
|
|
|
{
|
|
|
|
OwnerOf(proxy)->updatePointer(proxy, old);
|
|
|
|
}
|
|
|
|
|
2014-09-11 02:52:36 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::isCallable(JSObject* proxy) const
|
2014-09-11 02:52:36 +04:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
AuxCPOWData* aux = AuxCPOWDataOf(proxy);
|
2014-11-05 04:39:34 +03:00
|
|
|
return aux->isCallable;
|
2014-09-11 02:52:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
CPOWProxyHandler::isConstructor(JSObject* proxy) const
|
2014-09-25 15:13:29 +04:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
AuxCPOWData* aux = AuxCPOWDataOf(proxy);
|
2014-11-05 04:39:34 +03:00
|
|
|
return aux->isConstructor;
|
2014-09-11 02:52:36 +04:00
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:37 +04:00
|
|
|
void
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::drop(JSObject* obj)
|
2014-05-17 03:40:37 +04:00
|
|
|
{
|
2017-04-26 13:18:53 +03:00
|
|
|
// The association may have already been swept from the table but if it's
|
|
|
|
// there then remove it.
|
|
|
|
ObjectId objId = idOfUnchecked(obj);
|
|
|
|
if (cpows_.findPreserveColor(objId) == obj)
|
|
|
|
cpows_.remove(objId);
|
2014-05-17 03:40:37 +04:00
|
|
|
|
|
|
|
if (active())
|
2015-11-02 08:53:26 +03:00
|
|
|
Unused << SendDropObject(objId);
|
2014-05-17 03:40:37 +04:00
|
|
|
decref();
|
|
|
|
}
|
|
|
|
|
2014-09-24 15:54:11 +04:00
|
|
|
void
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::updatePointer(JSObject* obj, const JSObject* old)
|
2014-09-24 15:54:11 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOfUnchecked(obj);
|
2016-02-07 20:08:55 +03:00
|
|
|
MOZ_ASSERT(hasCPOW(objId, old));
|
2014-09-24 15:54:11 +04:00
|
|
|
cpows_.add(objId, obj);
|
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
bool
|
|
|
|
WrapperOwner::init()
|
|
|
|
{
|
|
|
|
if (!JavaScriptShared::init())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::getPropertyKeys(JSContext* cx, HandleObject proxy, uint32_t flags, AutoIdVector& props)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(proxy);
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2014-10-16 20:39:38 +04:00
|
|
|
InfallibleTArray<JSIDVariant> ids;
|
|
|
|
if (!SendGetPropertyKeys(objId, flags, &status, &ids))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
2014-05-29 05:05:22 +04:00
|
|
|
|
|
|
|
LOG_STACK();
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
if (!ok(cx, status))
|
|
|
|
return false;
|
|
|
|
|
2014-10-16 20:39:38 +04:00
|
|
|
for (size_t i = 0; i < ids.Length(); i++) {
|
|
|
|
RootedId id(cx);
|
|
|
|
if (!fromJSIDVariant(cx, ids[i], &id))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
2014-10-16 20:39:38 +04:00
|
|
|
if (!props.append(id))
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace jsipc {
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
IsCPOW(JSObject* obj)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
return IsProxy(obj) && GetProxyHandler(obj) == &CPOWProxyHandler::singleton;
|
|
|
|
}
|
|
|
|
|
2014-07-11 03:47:04 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
IsWrappedCPOW(JSObject* obj)
|
2014-07-11 03:47:04 +04:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
JSObject* unwrapped = js::UncheckedUnwrap(obj, true);
|
2014-07-11 03:47:04 +04:00
|
|
|
if (!unwrapped)
|
|
|
|
return false;
|
|
|
|
return IsCPOW(unwrapped);
|
|
|
|
}
|
|
|
|
|
2014-11-05 04:40:08 +03:00
|
|
|
void
|
2015-03-29 01:22:11 +03:00
|
|
|
GetWrappedCPOWTag(JSObject* obj, nsACString& out)
|
2014-11-05 04:40:08 +03:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
JSObject* unwrapped = js::UncheckedUnwrap(obj, true);
|
2014-11-05 04:40:08 +03:00
|
|
|
MOZ_ASSERT(IsCPOW(unwrapped));
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
AuxCPOWData* aux = AuxCPOWDataOf(unwrapped);
|
2014-11-05 04:40:08 +03:00
|
|
|
if (aux)
|
|
|
|
out = aux->objectTag;
|
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
nsresult
|
2015-03-29 01:22:11 +03:00
|
|
|
InstanceOf(JSObject* proxy, const nsID* id, bool* bp)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner* parent = OwnerOf(proxy);
|
2014-05-17 03:40:36 +04:00
|
|
|
if (!parent->active())
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
return parent->instanceOf(proxy, id, bp);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-10-24 02:31:54 +03:00
|
|
|
DOMInstanceOf(JSContext* cx, JSObject* proxyArg, int prototypeID, int depth, bool* bp)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2015-10-24 02:31:54 +03:00
|
|
|
RootedObject proxy(cx, proxyArg);
|
2017-07-11 13:59:09 +03:00
|
|
|
FORWARD(domInstanceOf, (cx, proxy, prototypeID, depth, bp));
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
} /* namespace jsipc */
|
|
|
|
} /* namespace mozilla */
|
|
|
|
|
|
|
|
nsresult
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::instanceOf(JSObject* obj, const nsID* id, bool* bp)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(obj);
|
|
|
|
|
|
|
|
JSIID iid;
|
|
|
|
ConvertID(*id, &iid);
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendInstanceOf(objId, iid, &status, bp))
|
2014-05-17 03:40:36 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
if (status.type() != ReturnStatus::TReturnSuccess)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::domInstanceOf(JSContext* cx, JSObject* obj, int prototypeID, int depth, bool* bp)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
ObjectId objId = idOf(obj);
|
|
|
|
|
|
|
|
ReturnStatus status;
|
2014-10-08 08:32:45 +04:00
|
|
|
if (!SendDOMInstanceOf(objId, prototypeID, depth, &status, bp))
|
2014-05-17 03:40:36 +04:00
|
|
|
return ipcfail(cx);
|
|
|
|
|
2014-05-29 05:05:22 +04:00
|
|
|
LOG_STACK();
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
return ok(cx, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
WrapperOwner::ActorDestroy(ActorDestroyReason why)
|
|
|
|
{
|
|
|
|
inactive_ = true;
|
2015-01-16 20:56:30 +03:00
|
|
|
|
|
|
|
objects_.clear();
|
|
|
|
unwaivedObjectIds_.clear();
|
|
|
|
waivedObjectIds_.clear();
|
2014-05-17 03:40:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::ipcfail(JSContext* cx)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
2016-08-14 14:39:28 +03:00
|
|
|
JS_ReportErrorASCII(cx, "cross-process JS call failed");
|
2014-05-17 03:40:36 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::ok(JSContext* cx, const ReturnStatus& status)
|
2014-05-17 03:40:36 +04:00
|
|
|
{
|
|
|
|
if (status.type() == ReturnStatus::TReturnSuccess)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (status.type() == ReturnStatus::TReturnStopIteration)
|
|
|
|
return JS_ThrowStopIteration(cx);
|
|
|
|
|
2016-07-26 13:30:42 +03:00
|
|
|
if (status.type() == ReturnStatus::TReturnDeadCPOW) {
|
2016-08-14 14:39:28 +03:00
|
|
|
JS_ReportErrorASCII(cx, "operation not possible on dead CPOW");
|
2016-07-26 13:30:42 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:36 +04:00
|
|
|
RootedValue exn(cx);
|
|
|
|
if (!fromVariant(cx, status.get_ReturnException().exn(), &exn))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
JS_SetPendingException(cx, exn);
|
|
|
|
return false;
|
|
|
|
}
|
2014-05-17 03:40:37 +04:00
|
|
|
|
2015-01-30 20:37:07 +03:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::ok(JSContext* cx, const ReturnStatus& status, ObjectOpResult& result)
|
2015-01-30 20:37:07 +03:00
|
|
|
{
|
|
|
|
if (status.type() == ReturnStatus::TReturnObjectOpResult)
|
|
|
|
return result.fail(status.get_ReturnObjectOpResult().code());
|
|
|
|
if (!ok(cx, status))
|
|
|
|
return false;
|
|
|
|
return result.succeed();
|
|
|
|
}
|
|
|
|
|
2016-04-22 07:51:16 +03:00
|
|
|
// CPOWs can have a tag string attached to them, originating in the local
|
|
|
|
// process from this function. It's sent with the CPOW to the remote process,
|
|
|
|
// where it can be fetched with Components.utils.getCrossProcessWrapperTag.
|
|
|
|
static nsCString
|
|
|
|
GetRemoteObjectTag(JS::Handle<JSObject*> obj)
|
2014-11-05 04:39:34 +03:00
|
|
|
{
|
2016-04-22 07:51:16 +03:00
|
|
|
if (nsCOMPtr<nsISupports> supports = xpc::UnwrapReflectorToISupports(obj)) {
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(supports));
|
|
|
|
if (treeItem)
|
|
|
|
return NS_LITERAL_CSTRING("ContentDocShellTreeItem");
|
2014-11-05 04:40:08 +03:00
|
|
|
|
2016-04-22 07:51:16 +03:00
|
|
|
nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(supports));
|
|
|
|
if (doc)
|
|
|
|
return NS_LITERAL_CSTRING("ContentDocument");
|
2014-11-05 04:40:08 +03:00
|
|
|
}
|
|
|
|
|
2016-04-22 07:51:16 +03:00
|
|
|
return NS_LITERAL_CSTRING("generic");
|
|
|
|
}
|
|
|
|
|
|
|
|
static RemoteObject
|
|
|
|
MakeRemoteObject(JSContext* cx, ObjectId id, HandleObject obj)
|
|
|
|
{
|
2014-11-05 04:40:08 +03:00
|
|
|
return RemoteObject(id.serialize(),
|
|
|
|
JS::IsCallable(obj),
|
|
|
|
JS::IsConstructor(obj),
|
2015-03-11 00:36:01 +03:00
|
|
|
dom::IsDOMObject(obj),
|
2016-04-22 07:51:16 +03:00
|
|
|
GetRemoteObjectTag(obj));
|
2014-11-05 04:39:34 +03:00
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:37 +04:00
|
|
|
bool
|
2015-03-29 01:22:11 +03:00
|
|
|
WrapperOwner::toObjectVariant(JSContext* cx, JSObject* objArg, ObjectVariant* objVarp)
|
2014-05-17 03:40:37 +04:00
|
|
|
{
|
2014-05-17 03:40:37 +04:00
|
|
|
RootedObject obj(cx, objArg);
|
2014-10-01 21:17:51 +04:00
|
|
|
MOZ_ASSERT(obj);
|
2014-05-17 03:40:37 +04:00
|
|
|
|
|
|
|
// We always save objects unwrapped in the CPOW table. If we stored
|
|
|
|
// wrappers, then the wrapper might be GCed while the target remained alive.
|
|
|
|
// Whenever operating on an object that comes from the table, we wrap it
|
|
|
|
// in findObjectById.
|
2014-09-25 15:13:29 +04:00
|
|
|
unsigned wrapperFlags = 0;
|
2014-12-19 04:34:24 +03:00
|
|
|
obj = js::UncheckedUnwrap(obj, true, &wrapperFlags);
|
2014-05-17 03:40:37 +04:00
|
|
|
if (obj && IsCPOW(obj) && OwnerOf(obj) == this) {
|
2014-09-25 15:13:29 +04:00
|
|
|
*objVarp = LocalObject(idOf(obj).serialize());
|
2014-05-17 03:40:37 +04:00
|
|
|
return true;
|
|
|
|
}
|
2014-09-25 15:13:29 +04:00
|
|
|
bool waiveXray = wrapperFlags & xpc::WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG;
|
2014-05-17 03:40:37 +04:00
|
|
|
|
2014-09-25 15:13:29 +04:00
|
|
|
ObjectId id = objectIdMap(waiveXray).find(obj);
|
2014-09-25 15:13:29 +04:00
|
|
|
if (!id.isNull()) {
|
2014-09-25 15:13:29 +04:00
|
|
|
MOZ_ASSERT(id.hasXrayWaiver() == waiveXray);
|
2014-11-05 04:40:08 +03:00
|
|
|
*objVarp = MakeRemoteObject(cx, id, obj);
|
2014-05-17 03:40:37 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-05-17 03:40:37 +04:00
|
|
|
// Need to call PreserveWrapper on |obj| in case it's a reflector.
|
|
|
|
// FIXME: What if it's an XPCWrappedNative?
|
|
|
|
if (mozilla::dom::IsDOMObject(obj))
|
|
|
|
mozilla::dom::TryPreserveWrapper(obj);
|
|
|
|
|
2014-09-25 15:13:29 +04:00
|
|
|
id = ObjectId(nextSerialNumber_++, waiveXray);
|
2014-05-17 03:40:37 +04:00
|
|
|
if (!objects_.add(id, obj))
|
|
|
|
return false;
|
2014-09-25 15:13:29 +04:00
|
|
|
if (!objectIdMap(waiveXray).add(cx, obj, id))
|
2014-05-17 03:40:37 +04:00
|
|
|
return false;
|
|
|
|
|
2014-11-05 04:40:08 +03:00
|
|
|
*objVarp = MakeRemoteObject(cx, id, obj);
|
2014-05-17 03:40:37 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
JSObject*
|
2016-10-20 23:37:26 +03:00
|
|
|
WrapperOwner::fromObjectVariant(JSContext* cx, const ObjectVariant& objVar)
|
2014-05-17 03:40:37 +04:00
|
|
|
{
|
|
|
|
if (objVar.type() == ObjectVariant::TRemoteObject) {
|
|
|
|
return fromRemoteObjectVariant(cx, objVar.get_RemoteObject());
|
|
|
|
} else {
|
|
|
|
return fromLocalObjectVariant(cx, objVar.get_LocalObject());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
JSObject*
|
2016-10-20 23:37:26 +03:00
|
|
|
WrapperOwner::fromRemoteObjectVariant(JSContext* cx, const RemoteObject& objVar)
|
2014-05-17 03:40:37 +04:00
|
|
|
{
|
2014-09-25 15:13:29 +04:00
|
|
|
ObjectId objId = ObjectId::deserialize(objVar.serializedId());
|
2014-05-17 03:40:37 +04:00
|
|
|
RootedObject obj(cx, findCPOWById(objId));
|
2014-09-13 04:41:18 +04:00
|
|
|
if (!obj) {
|
2014-05-17 03:40:37 +04:00
|
|
|
|
2014-09-13 04:41:18 +04:00
|
|
|
// All CPOWs live in the privileged junk scope.
|
|
|
|
RootedObject junkScope(cx, xpc::PrivilegedJunkScope());
|
|
|
|
JSAutoCompartment ac(cx, junkScope);
|
|
|
|
RootedValue v(cx, UndefinedValue());
|
2016-02-24 00:42:30 +03:00
|
|
|
// We need to setLazyProto for the getPrototype/getPrototypeIfOrdinary
|
|
|
|
// hooks.
|
2015-02-10 18:29:41 +03:00
|
|
|
ProxyOptions options;
|
|
|
|
options.setLazyProto(true);
|
2014-09-13 04:41:18 +04:00
|
|
|
obj = NewProxyObject(cx,
|
|
|
|
&CPOWProxyHandler::singleton,
|
|
|
|
v,
|
|
|
|
nullptr,
|
2015-02-10 18:29:41 +03:00
|
|
|
options);
|
2014-09-13 04:41:18 +04:00
|
|
|
if (!obj)
|
|
|
|
return nullptr;
|
2014-05-17 03:40:37 +04:00
|
|
|
|
2014-09-13 04:41:18 +04:00
|
|
|
if (!cpows_.add(objId, obj))
|
|
|
|
return nullptr;
|
2014-05-17 03:40:37 +04:00
|
|
|
|
2016-10-19 01:58:33 +03:00
|
|
|
nextCPOWNumber_ = objId.serialNumber() + 1;
|
|
|
|
|
2014-09-13 04:41:18 +04:00
|
|
|
// Incref once we know the decref will be called.
|
|
|
|
incref();
|
2014-05-17 03:40:37 +04:00
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
AuxCPOWData* aux = new AuxCPOWData(objId,
|
2014-11-05 04:40:08 +03:00
|
|
|
objVar.isCallable(),
|
|
|
|
objVar.isConstructor(),
|
2015-03-11 00:36:01 +03:00
|
|
|
objVar.isDOMObject(),
|
2014-11-05 04:40:08 +03:00
|
|
|
objVar.objectTag());
|
2014-11-05 04:39:34 +03:00
|
|
|
|
2017-04-28 15:12:28 +03:00
|
|
|
SetProxyReservedSlot(obj, 0, PrivateValue(this));
|
|
|
|
SetProxyReservedSlot(obj, 1, PrivateValue(aux));
|
2014-09-13 04:41:18 +04:00
|
|
|
}
|
2014-05-17 03:40:37 +04:00
|
|
|
|
2014-09-13 04:41:18 +04:00
|
|
|
if (!JS_WrapObject(cx, &obj))
|
|
|
|
return nullptr;
|
2014-05-17 03:40:37 +04:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2015-03-29 01:22:11 +03:00
|
|
|
JSObject*
|
2016-10-20 23:37:26 +03:00
|
|
|
WrapperOwner::fromLocalObjectVariant(JSContext* cx, const LocalObject& objVar)
|
2014-05-17 03:40:37 +04:00
|
|
|
{
|
2014-09-25 15:13:29 +04:00
|
|
|
ObjectId id = ObjectId::deserialize(objVar.serializedId());
|
2014-05-17 03:40:37 +04:00
|
|
|
Rooted<JSObject*> obj(cx, findObjectById(cx, id));
|
|
|
|
if (!obj)
|
|
|
|
return nullptr;
|
|
|
|
if (!JS_WrapObject(cx, &obj))
|
|
|
|
return nullptr;
|
|
|
|
return obj;
|
|
|
|
}
|