--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -20,17 +20,16 @@
#include "mozilla/dom/ExternalHelperAppChild.h"
#include "mozilla/dom/PCrashReporterChild.h"
#include "mozilla/dom/DOMStorageIPC.h"
#include "mozilla/Hal.h"
#include "mozilla/hal_sandbox/PHalChild.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/TestShellChild.h"
#include "mozilla/ipc/XPCShellEnvironment.h"
-#include "mozilla/jsipc/PContextWrapperChild.h"
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/PCompositorChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/Preferences.h"
#include "mozilla/unused.h"
#include "nsIMemoryReporter.h"
@@ -45,30 +44,32 @@
#include "nsWeakReference.h"
#include "nsIScriptError.h"
#include "nsIConsoleService.h"
#include "nsJSEnvironment.h"
#include "SandboxHal.h"
#include "nsDebugImpl.h"
#include "nsHashPropertyBag.h"
#include "nsLayoutStylesheetCache.h"
+#include "nsIJSRuntimeService.h"
#include "IHistory.h"
#include "nsDocShellCID.h"
#include "nsNetUtil.h"
#include "base/message_loop.h"
#include "base/process_util.h"
#include "base/task.h"
#include "nsChromeRegistryContent.h"
#include "mozilla/chrome/RegistryMessageUtils.h"
#include "nsFrameMessageManager.h"
#include "nsIGeolocationProvider.h"
+#include "JavaScriptParent.h"
#include "mozilla/dom/PMemoryReportRequestChild.h"
#ifdef MOZ_PERMISSIONS
#include "nsPermission.h"
#include "nsPermissionManager.h"
#endif
#if defined(MOZ_WIDGET_ANDROID)
@@ -104,30 +105,32 @@
#include "ProcessUtils.h"
#include "StructuredCloneUtils.h"
#include "URIUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsContentUtils.h"
#include "nsIPrincipal.h"
#include "nsDeviceStorage.h"
#include "AudioChannelService.h"
+#include "JavaScriptChild.h"
#include "ProcessPriorityManager.h"
using namespace base;
using namespace mozilla;
using namespace mozilla::docshell;
using namespace mozilla::dom::bluetooth;
using namespace mozilla::dom::devicestorage;
using namespace mozilla::dom::ipc;
using namespace mozilla::dom::mobilemessage;
using namespace mozilla::dom::indexedDB;
using namespace mozilla::hal_sandbox;
using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::net;
+using namespace mozilla::jsipc;
#if defined(MOZ_WIDGET_GONK)
using namespace mozilla::system;
#endif
namespace mozilla {
namespace dom {
class MemoryReportRequestChild : public PMemoryReportRequestChild
@@ -547,16 +550,41 @@ static CancelableTask* sFirstIdleTask;
static void FirstIdle(void)
{
MOZ_ASSERT(sFirstIdleTask);
sFirstIdleTask = nullptr;
ContentChild::GetSingleton()->SendFirstIdle();
}
+mozilla::jsipc::PJavaScriptChild *
+ContentChild::AllocPJavaScript()
+{
+ nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
+ NS_ENSURE_TRUE(svc, NULL);
+
+ JSRuntime *rt;
+ svc->GetRuntime(&rt);
+ NS_ENSURE_TRUE(svc, NULL);
+
+ mozilla::jsipc::JavaScriptChild *child = new mozilla::jsipc::JavaScriptChild(rt);
+ if (!child->init()) {
+ delete child;
+ return NULL;
+ }
+ return child;
+}
+
+bool
+ContentChild::DeallocPJavaScript(PJavaScriptChild *child)
+{
+ delete child;
+ return true;
+}
+
PBrowserChild*
ContentChild::AllocPBrowser(const IPCTabContext& aContext,
const uint32_t& aChromeFlags)
{
// We'll happily accept any kind of IPCTabContext here; we don't need to
// check that it's of a certain type for security purposes, because we
// believe whatever the parent process tells us.
@@ -755,20 +783,29 @@ ContentChild::AllocPTestShell()
bool
ContentChild::DeallocPTestShell(PTestShellChild* shell)
{
delete shell;
return true;
}
+jsipc::JavaScriptChild *
+ContentChild::GetCPOWManager()
+{
+ if (ManagedPJavaScriptChild().Length()) {
+ return static_cast<JavaScriptChild*>(ManagedPJavaScriptChild()[0]);
+ }
+ JavaScriptChild* actor = static_cast<JavaScriptChild*>(SendPJavaScriptConstructor());
+ return actor;
+}
+
bool
ContentChild::RecvPTestShellConstructor(PTestShellChild* actor)
{
- actor->SendPContextWrapperConstructor()->SendPObjectWrapperConstructor(true);
return true;
}
PDeviceStorageRequestChild*
ContentChild::AllocPDeviceStorageRequest(const DeviceStorageParams& aParams)
{
return new DeviceStorageRequestChild();
}
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -23,16 +23,20 @@ struct OverrideMapping;
namespace mozilla {
namespace ipc {
class OptionalURIParams;
class URIParams;
}// namespace ipc
+namespace jsipc {
+class JavaScriptChild;
+}
+
namespace layers {
class PCompositorChild;
} // namespace layers
namespace dom {
class AlertObserver;
class PrefObserver;
@@ -121,16 +125,17 @@ public:
const bool& aDumpChildProcesses);
virtual bool
RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier,
const bool& aDumpChildProcesses);
virtual PTestShellChild* AllocPTestShell();
virtual bool DeallocPTestShell(PTestShellChild*);
virtual bool RecvPTestShellConstructor(PTestShellChild*);
+ jsipc::JavaScriptChild *GetCPOWManager();
virtual PNeckoChild* AllocPNecko();
virtual bool DeallocPNecko(PNeckoChild*);
virtual PExternalHelperAppChild *AllocPExternalHelperApp(
const OptionalURIParams& uri,
const nsCString& aMimeContentType,
const nsCString& aContentDisposition,
@@ -151,16 +156,19 @@ public:
virtual PSpeechSynthesisChild* AllocPSpeechSynthesis();
virtual bool DeallocPSpeechSynthesis(PSpeechSynthesisChild* aActor);
virtual bool RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
const InfallibleTArray<ResourceMapping>& resources,
const InfallibleTArray<OverrideMapping>& overrides,
const nsCString& locale);
+ virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScript();
+ virtual bool DeallocPJavaScript(mozilla::jsipc::PJavaScriptChild*);
+
virtual bool RecvSetOffline(const bool& offline);
virtual bool RecvNotifyVisited(const URIParams& aURI);
// auto remove when alertfinished is received.
nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver);
virtual bool RecvPreferenceUpdate(const PrefSetting& aPref);
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -114,16 +114,17 @@
using namespace mozilla::system;
#endif
#ifdef MOZ_B2G_BT
#include "BluetoothParent.h"
#include "BluetoothService.h"
#endif
+#include "JavaScriptParent.h"
#include "Crypto.h"
#ifdef MOZ_WEBSPEECH
#include "mozilla/dom/SpeechSynthesisParent.h"
#endif
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
static const char* sClipboardTextFlavors[] = { kUnicodeMime };
@@ -135,16 +136,17 @@ using namespace mozilla::dom::devicestor
using namespace mozilla::dom::indexedDB;
using namespace mozilla::dom::power;
using namespace mozilla::dom::mobilemessage;
using namespace mozilla::hal;
using namespace mozilla::idl;
using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::net;
+using namespace mozilla::jsipc;
namespace mozilla {
namespace dom {
#define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
// This represents a single measurement taken by a memory reporter in a child
// process and passed to this one. Its process is non-empty, and its amount is
@@ -1003,16 +1005,26 @@ ContentParent::NotifyTabDestroyed(PBrows
// us down.
if (ManagedPBrowserParent().Length() == 1) {
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ContentParent::ShutDownProcess));
}
}
+jsipc::JavaScriptParent*
+ContentParent::GetCPOWManager()
+{
+ if (ManagedPJavaScriptParent().Length()) {
+ return static_cast<JavaScriptParent*>(ManagedPJavaScriptParent()[0]);
+ }
+ JavaScriptParent* actor = static_cast<JavaScriptParent*>(SendPJavaScriptConstructor());
+ return actor;
+}
+
TestShellParent*
ContentParent::CreateTestShell()
{
return static_cast<TestShellParent*>(SendPTestShellConstructor());
}
bool
ContentParent::DestroyTestShell(TestShellParent* aTestShell)
@@ -1573,16 +1585,34 @@ ContentParent::RecvGetXPCOMProcessAttrib
nsCOMPtr<nsIIOService> io(do_GetIOService());
NS_ASSERTION(io, "No IO service?");
DebugOnly<nsresult> rv = io->GetOffline(aIsOffline);
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed getting offline?");
return true;
}
+mozilla::jsipc::PJavaScriptParent *
+ContentParent::AllocPJavaScript()
+{
+ mozilla::jsipc::JavaScriptParent *parent = new mozilla::jsipc::JavaScriptParent();
+ if (!parent->init()) {
+ delete parent;
+ return NULL;
+ }
+ return parent;
+}
+
+bool
+ContentParent::DeallocPJavaScript(PJavaScriptParent *parent)
+{
+ static_cast<mozilla::jsipc::JavaScriptParent *>(parent)->destroyFromContent();
+ return true;
+}
+
PBrowserParent*
ContentParent::AllocPBrowser(const IPCTabContext& aContext,
const uint32_t &aChromeFlags)
{
unused << aChromeFlags;
const IPCTabAppBrowserContext& appBrowser = aContext.appBrowserContext();
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -39,16 +39,20 @@ class nsIDOMBlob;
namespace mozilla {
namespace ipc {
class OptionalURIParams;
class URIParams;
class TestShellParent;
} // namespace ipc
+namespace jsipc {
+class JavaScriptParent;
+}
+
namespace layers {
class PCompositorParent;
} // namespace layers
namespace dom {
class TabParent;
class PStorageParent;
@@ -121,16 +125,17 @@ public:
void NotifyTabDestroying(PBrowserParent* aTab);
/** Notify that a tab was destroyed during normal operation. */
void NotifyTabDestroyed(PBrowserParent* aTab,
bool aNotifiedDestroying);
TestShellParent* CreateTestShell();
bool DestroyTestShell(TestShellParent* aTestShell);
TestShellParent* GetTestShellSingleton();
+ jsipc::JavaScriptParent *GetCPOWManager();
void ReportChildAlreadyBlocked();
bool RequestRunToCompletion();
bool IsAlive();
bool IsForApp();
void SetChildMemoryReporters(const InfallibleTArray<MemoryReport>& report);
@@ -189,16 +194,17 @@ private:
hal::ProcessPriority aInitialPriority);
static hal::ProcessPriority GetInitialProcessPriority(nsIDOMElement* aFrameElement);
// Hide the raw constructor methods since we don't want client code
// using them.
using PContentParent::SendPBrowserConstructor;
using PContentParent::SendPTestShellConstructor;
+ using PContentParent::SendPJavaScriptConstructor;
// No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated may be
// true.
ContentParent(mozIApplication* aApp,
bool aIsForBrowser,
bool aIsForPreallocated,
ChildPrivileges aOSPrivileges = base::PRIVILEGES_DEFAULT,
hal::ProcessPriority aInitialPriority = hal::PROCESS_PRIORITY_FOREGROUND);
@@ -246,16 +252,19 @@ private:
AllocPImageBridge(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
virtual bool RecvGetProcessAttributes(uint64_t* aId,
bool* aIsForApp,
bool* aIsForBrowser) MOZ_OVERRIDE;
virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE;
+ virtual mozilla::jsipc::PJavaScriptParent* AllocPJavaScript();
+ virtual bool DeallocPJavaScript(mozilla::jsipc::PJavaScriptParent*);
+
virtual PBrowserParent* AllocPBrowser(const IPCTabContext& aContext,
const uint32_t& aChromeFlags);
virtual bool DeallocPBrowser(PBrowserParent* frame);
virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequest(const DeviceStorageParams&);
virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestParent*);
virtual PBlobParent* AllocPBlob(const BlobConstructorParams& aParams);
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -37,16 +37,17 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/toolkit/xre \
-I$(topsrcdir)/hal/sandbox \
-I$(topsrcdir)/dom/mobilemessage/src/ipc \
-I$(topsrcdir)/dom/devicestorage \
-I$(topsrcdir)/widget/xpwidgets \
-I$(topsrcdir)/dom/bluetooth \
-I$(topsrcdir)/dom/bluetooth/ipc \
-I$(topsrcdir)/content/media/webspeech/synth/ipc \
+ -I$(topsrcdir)/js/ipc \
$(NULL)
DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
ifeq ($(MOZ_WIDGET_TOOLKIT),$(findstring $(MOZ_WIDGET_TOOLKIT),android gtk2 gonk qt))
DEFINES += -DMOZ_ENABLE_FREETYPE
endif
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -15,16 +15,17 @@ include protocol PHal;
include protocol PImageBridge;
include protocol PIndexedDB;
include protocol PMemoryReportRequest;
include protocol PNecko;
include protocol PSms;
include protocol PSpeechSynthesis;
include protocol PStorage;
include protocol PTestShell;
+include protocol PJavaScript;
include DOMTypes;
include InputStreamParams;
include URIParams;
include "mozilla/chrome/RegistryMessageUtils.h";
include "mozilla/dom/PermissionMessageUtils.h";
include "mozilla/dom/TabMessageUtils.h";
include "mozilla/HalTypes.h";
@@ -247,16 +248,17 @@ rpc protocol PContent
manages PHal;
manages PIndexedDB;
manages PMemoryReportRequest;
manages PNecko;
manages PSms;
manages PSpeechSynthesis;
manages PStorage;
manages PTestShell;
+ manages PJavaScript;
both:
// Depending on exactly how the new browser is being created, it might be
// created from either the child or parent process!
//
// The child creates the PBrowser as part of
// TabChild::BrowserFrameProvideWindow (which happens when the child's
// content calls window.open()), and the parent creates the PBrowser as part
@@ -276,16 +278,18 @@ both:
// This allows the parent to prevent a malicious child from escalating its
// privileges by requesting a PBrowser corresponding to a highly-privileged
// app; the child can only request privileges for an app which the child has
// access to (in the form of a TabChild).
async PBrowser(IPCTabContext context, uint32_t chromeFlags);
async PBlob(BlobConstructorParams params);
+ PJavaScript();
+
child:
/**
* Update OS process privileges to |privs|. Can usually only be
* performed zero or one times. The child will abnormally exit if
* the privilege update fails.
*/
async SetProcessPrivileges(ChildPrivileges privs);
--- a/ipc/testshell/PTestShell.ipdl
+++ b/ipc/testshell/PTestShell.ipdl
@@ -1,33 +1,27 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* 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 protocol PContent;
include protocol PTestShellCommand;
-include protocol PContextWrapper;
namespace mozilla {
namespace ipc {
rpc protocol PTestShell
{
manager PContent;
manages PTestShellCommand;
- manages PContextWrapper;
child:
__delete__();
ExecuteCommand(nsString aCommand);
PTestShellCommand(nsString aCommand);
-
-parent:
- PContextWrapper();
-
};
} // namespace ipc
} // namespace mozilla
--- a/ipc/testshell/TestShellChild.cpp
+++ b/ipc/testshell/TestShellChild.cpp
@@ -1,20 +1,17 @@
/* 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 "TestShellChild.h"
-#include "mozilla/jsipc/ContextWrapperChild.h"
using mozilla::ipc::TestShellChild;
using mozilla::ipc::PTestShellCommandChild;
using mozilla::ipc::XPCShellEnvironment;
-using mozilla::jsipc::PContextWrapperChild;
-using mozilla::jsipc::ContextWrapperChild;
TestShellChild::TestShellChild()
: mXPCShell(XPCShellEnvironment::CreateEnvironment())
{
}
bool
TestShellChild::RecvExecuteCommand(const nsString& aCommand)
@@ -52,24 +49,8 @@ TestShellChild::RecvPTestShellCommandCon
nsString response;
if (!mXPCShell->EvaluateString(aCommand, &response)) {
return false;
}
return PTestShellCommandChild::Send__delete__(aActor, response);
}
-PContextWrapperChild*
-TestShellChild::AllocPContextWrapper()
-{
- JSContext* cx;
- if (mXPCShell && (cx = mXPCShell->GetContext())) {
- return new ContextWrapperChild(cx);
- }
- return NULL;
-}
-
-bool
-TestShellChild::DeallocPContextWrapper(PContextWrapperChild* actor)
-{
- delete actor;
- return true;
-}
--- a/ipc/testshell/TestShellChild.h
+++ b/ipc/testshell/TestShellChild.h
@@ -8,20 +8,16 @@
#include "mozilla/ipc/PTestShellChild.h"
#include "mozilla/ipc/PTestShellCommandChild.h"
#include "mozilla/ipc/XPCShellEnvironment.h"
#include "nsAutoPtr.h"
namespace mozilla {
-namespace jsipc {
-class PContextWrapperChild;
-}
-
namespace ipc {
class XPCShellEnvironment;
class TestShellChild : public PTestShellChild
{
public:
TestShellChild();
@@ -34,19 +30,16 @@ public:
bool
RecvPTestShellCommandConstructor(PTestShellCommandChild* aActor,
const nsString& aCommand);
bool
DeallocPTestShellCommand(PTestShellCommandChild* aCommand);
- PContextWrapperChild* AllocPContextWrapper();
- bool DeallocPContextWrapper(PContextWrapperChild* actor);
-
private:
nsAutoPtr<XPCShellEnvironment> mXPCShell;
};
} /* namespace ipc */
} /* namespace mozilla */
#endif /* ipc_testshell_TestShellChild_h */
--- a/ipc/testshell/TestShellParent.cpp
+++ b/ipc/testshell/TestShellParent.cpp
@@ -3,27 +3,24 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TestShellParent.h"
/* This must occur *after* TestShellParent.h to avoid typedefs conflicts. */
#include "mozilla/Util.h"
#include "mozilla/dom/ContentParent.h"
-#include "mozilla/jsipc/ContextWrapperParent.h"
#include "nsAutoPtr.h"
using namespace mozilla;
using mozilla::ipc::TestShellParent;
using mozilla::ipc::TestShellCommandParent;
using mozilla::ipc::PTestShellCommandParent;
using mozilla::dom::ContentParent;
-using mozilla::jsipc::PContextWrapperParent;
-using mozilla::jsipc::ContextWrapperParent;
PTestShellCommandParent*
TestShellParent::AllocPTestShellCommand(const nsString& aCommand)
{
return new TestShellCommandParent();
}
bool
@@ -39,42 +36,16 @@ TestShellParent::CommandDone(TestShellCo
{
// XXX what should happen if the callback fails?
/*JSBool ok = */command->RunCallback(aResponse);
command->ReleaseCallback();
return true;
}
-PContextWrapperParent*
-TestShellParent::AllocPContextWrapper()
-{
- return new ContextWrapperParent();
-}
-
-bool
-TestShellParent::DeallocPContextWrapper(PContextWrapperParent* actor)
-{
- delete actor;
- return true;
-}
-
-JSBool
-TestShellParent::GetGlobalJSObject(JSContext* cx, JSObject** globalp)
-{
- // TODO Unify this code with TabParent::GetGlobalJSObject.
- InfallibleTArray<PContextWrapperParent*> cwps(1);
- ManagedPContextWrapperParent(cwps);
- if (cwps.Length() < 1)
- return JS_FALSE;
- NS_ASSERTION(cwps.Length() == 1, "More than one PContextWrapper?");
- ContextWrapperParent* cwp = static_cast<ContextWrapperParent*>(cwps[0]);
- return cwp->GetGlobalJSObject(cx, globalp);
-}
-
JSBool
TestShellCommandParent::SetCallback(JSContext* aCx,
JS::Value aCallback)
{
if (!mCallback.Hold(aCx)) {
return JS_FALSE;
}
--- a/ipc/testshell/TestShellParent.h
+++ b/ipc/testshell/TestShellParent.h
@@ -15,40 +15,31 @@
#include "nsAutoJSValHolder.h"
#include "nsStringGlue.h"
struct JSContext;
class JSObject;
namespace mozilla {
-namespace jsipc {
-class PContextWrapperParent;
-}
-
namespace ipc {
class TestShellCommandParent;
class TestShellParent : public PTestShellParent
{
public:
PTestShellCommandParent*
AllocPTestShellCommand(const nsString& aCommand);
bool
DeallocPTestShellCommand(PTestShellCommandParent* aActor);
bool
CommandDone(TestShellCommandParent* aActor, const nsString& aResponse);
-
- PContextWrapperParent* AllocPContextWrapper();
- bool DeallocPContextWrapper(PContextWrapperParent* actor);
-
- JSBool GetGlobalJSObject(JSContext* cx, JSObject** globalp);
};
class TestShellCommandParent : public PTestShellCommandParent
{
public:
TestShellCommandParent() : mCx(NULL) { }
deleted file mode 100644
--- a/js/ipc/CPOWTypes.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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/. */
-
-#ifndef mozilla_jsipc_CPOWTypes_h
-#define mozilla_jsipc_CPOWTypes_h
-
-#include "jsapi.h"
-#include "jspubtd.h"
-
-using mozilla::void_t;
-
-namespace mozilla {
-namespace jsipc {
-
-
-template <typename P>
-struct CPOWSingleton
-{
- static void Write(IPC::Message*, const P&) {}
- static bool Read(const IPC::Message*, void**, P*) { return true; }
-};
-
-template <typename Type, typename As>
-struct CPOWConvertible
-{
- static void Write(IPC::Message* m, const Type& t) {
- WriteParam(m, As(t));
- }
- static bool Read(const IPC::Message* m, void** iter, Type* tp) {
- As a;
- return (ReadParam(m, iter, &a) &&
- (*tp = Type(a), true));
- }
-};
-
-} // namespace jsipc
-} // namespace mozilla
-
-namespace IPC {
-
-
-template <> struct ParamTraits<JSType> : public mozilla::jsipc::CPOWConvertible<JSType, int> {};
-
-}
-
-// TODO Use a more standard logging mechanism.
-#ifdef LOGGING
-#define CPOW_LOG(PRINTF_ARGS) \
- JS_BEGIN_MACRO \
- printf("CPOW | "); \
- printf PRINTF_ARGS ; \
- printf("\n"); \
- JS_END_MACRO
-#define JSVAL_TO_CSTR(CX, V) \
- NS_ConvertUTF16toUTF8(nsString(JS_GetStringChars(JS_ValueToString(CX, V)))).get()
-#else
-#define CPOW_LOG(_) JS_BEGIN_MACRO JS_END_MACRO
-#define JSVAL_TO_CSTR(CX, V) ((char*)0)
-#endif
-
-#endif /* mozilla_jsipc_CPOWTypes_h */
deleted file mode 100644
--- a/js/ipc/ContextWrapperChild.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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/. */
-
-#ifndef mozilla_jsipc_ContextWrapperChild_h
-#define mozilla_jsipc_ContextWrapperChild_h
-
-#include "mozilla/jsipc/PContextWrapperChild.h"
-#include "mozilla/jsipc/ObjectWrapperChild.h"
-
-#include "jsapi.h"
-#include "nsClassHashtable.h"
-#include "nsHashKeys.h"
-
-namespace mozilla {
-namespace jsipc {
-
-class ContextWrapperChild
- : public PContextWrapperChild
-{
-public:
-
- ContextWrapperChild(JSContext* cx)
- : mContext(cx)
- {
- mResidentObjectTable.Init();
- }
-
- JSContext* GetContext() { return mContext; }
-
- PObjectWrapperChild* GetOrCreateWrapper(JSObject* obj_,
- bool makeGlobal = false)
- {
- if (!obj_) // Don't wrap nothin'!
- return NULL;
- JS::RootedObject obj(mContext, obj_);
- PObjectWrapperChild* wrapper;
- while (!mResidentObjectTable.Get(obj, &wrapper)) {
- wrapper = SendPObjectWrapperConstructor(AllocPObjectWrapper(obj),
- makeGlobal);
- if (wrapper)
- mResidentObjectTable.Put(obj, wrapper);
- else
- return NULL;
- }
- return wrapper;
- }
-
-protected:
-
- PObjectWrapperChild* AllocPObjectWrapper(JSObject* obj) {
- return new ObjectWrapperChild(mContext, obj);
- }
-
- PObjectWrapperChild* AllocPObjectWrapper(const bool&) {
- // This stuff is unused and billm has a patch to delete it.
- JSAutoRequest ar(mContext);
- return AllocPObjectWrapper(JS_GetGlobalForScopeChain(mContext));
- }
-
- bool DeallocPObjectWrapper(PObjectWrapperChild* actor) {
- ObjectWrapperChild* owc = static_cast<ObjectWrapperChild*>(actor);
- mResidentObjectTable.Remove(owc->GetJSObject());
- return true;
- }
-
-private:
-
- JSContext* const mContext;
-
- nsClassHashtable<nsPtrHashKey<JSObject>,
- PObjectWrapperChild> mResidentObjectTable;
-
-};
-
-}}
-
-#endif /* mozilla_jsipc_ContextWrapperChild_h */
deleted file mode 100644
--- a/js/ipc/ContextWrapperParent.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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/. */
-
-#ifndef mozilla_jsipc_ContextWrapperParent_h
-#define mozilla_jsipc_ContextWrapperParent_h
-
-#include "mozilla/jsipc/PContextWrapperParent.h"
-#include "mozilla/jsipc/ObjectWrapperParent.h"
-#include "mozilla/jsipc/CPOWTypes.h"
-
-#include "mozilla/dom/ContentParent.h"
-
-#include "jsapi.h"
-#include "nsAutoJSValHolder.h"
-
-namespace mozilla {
-namespace jsipc {
-
-using mozilla::dom::ContentParent;
-
-class ContextWrapperParent
- : public PContextWrapperParent
-{
-public:
-
- ContextWrapperParent()
- : mGlobal(NULL)
- {}
-
- JSBool GetGlobalJSObject(JSContext* cx, JSObject** globalp) {
- if (!mGlobal)
- return JS_FALSE;
- mGlobalHolder.Hold(cx);
- mGlobalHolder = *globalp = mGlobal->GetJSObject(cx);
- return JS_TRUE;
- }
-
- ObjectWrapperParent* GetGlobalObjectWrapper() const {
- return mGlobal;
- }
-
- bool RequestRunToCompletion() {
- return false;
- }
-
-private:
-
- ObjectWrapperParent* mGlobal;
- nsAutoJSValHolder mGlobalHolder;
-
- PObjectWrapperParent* AllocPObjectWrapper(const bool&) {
- return new ObjectWrapperParent();
- }
-
- bool RecvPObjectWrapperConstructor(PObjectWrapperParent* actor,
- const bool& makeGlobal)
- {
- if (makeGlobal) {
- mGlobalHolder.Release();
- mGlobal = static_cast<ObjectWrapperParent*>(actor);
- }
- return true;
- }
-
- bool DeallocPObjectWrapper(PObjectWrapperParent* actor)
- {
- if (mGlobal &&
- mGlobal == static_cast<ObjectWrapperParent*>(actor)) {
- mGlobalHolder.Release();
- mGlobal = NULL;
- }
- delete actor;
- return true;
- }
-
-};
-
-}}
-
-#endif /* mozilla_jsipc_ContextWrapperParent_h */
new file mode 100644
--- /dev/null
+++ b/js/ipc/JavaScriptChild.cpp
@@ -0,0 +1,605 @@
+/* -*- 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 "JavaScriptChild.h"
+#include "mozilla/dom/ContentChild.h"
+#include "nsContentUtils.h"
+#include "xpcprivate.h"
+#include "jsfriendapi.h"
+#include "nsCxPusher.h"
+
+using namespace JS;
+using namespace mozilla;
+using namespace mozilla::jsipc;
+
+using mozilla::AutoSafeJSContext;
+
+JavaScriptChild::JavaScriptChild(JSRuntime *rt)
+ : lastId_(0),
+ rt_(rt)
+{
+}
+
+static void
+Trace(JSTracer *trc, void *data)
+{
+ reinterpret_cast<JavaScriptChild *>(data)->trace(trc);
+}
+
+JavaScriptChild::~JavaScriptChild()
+{
+ JS_RemoveExtraGCRootsTracer(rt_, Trace, this);
+}
+
+void
+JavaScriptChild::trace(JSTracer *trc)
+{
+ objects_.trace(trc);
+ ids_.trace(trc);
+}
+
+bool
+JavaScriptChild::init()
+{
+ if (!JavaScriptShared::init())
+ return false;
+ if (!ids_.init())
+ return false;
+
+ JS_AddExtraGCRootsTracer(rt_, Trace, this);
+ return true;
+}
+
+bool
+JavaScriptChild::RecvDropObject(const ObjectId &objId)
+{
+ JSObject *obj = findObject(objId);
+ if (obj) {
+ ids_.remove(obj);
+ objects_.remove(objId);
+ }
+ return true;
+}
+
+bool
+JavaScriptChild::makeId(JSContext *cx, JSObject *obj, ObjectId *idp)
+{
+ if (!obj) {
+ *idp = 0;
+ return true;
+ }
+
+ ObjectId id = ids_.find(obj);
+ if (id) {
+ *idp = id;
+ return true;
+ }
+
+ id = ++lastId_;
+ if (id > MAX_CPOW_IDS) {
+ JS_ReportError(cx, "CPOW id limit reached");
+ return false;
+ }
+
+ id <<= OBJECT_EXTRA_BITS;
+ if (JS_ObjectIsCallable(cx, obj))
+ id |= OBJECT_IS_CALLABLE;
+
+ if (!objects_.add(id, obj))
+ return false;
+ if (!ids_.add(obj, id))
+ return false;
+
+ *idp = id;
+ return true;
+}
+
+JSObject *
+JavaScriptChild::unwrap(JSContext *cx, ObjectId id)
+{
+ JSObject *obj = findObject(id);
+ MOZ_ASSERT(obj);
+ return obj;
+}
+
+bool
+JavaScriptChild::fail(JSContext *cx, ReturnStatus *rs)
+{
+ // By default, we set |undefined| unless we can get a more meaningful
+ // exception.
+ *rs = ReturnStatus(false, JSVariant(void_t()));
+
+ // Note we always return true from this function, since this propagates
+ // to the IPC code, and we don't want a JS failure to cause the death
+ // of the child process.
+
+ jsval exn;
+ if (!JS_GetPendingException(cx, &exn))
+ return true;
+
+ // If we don't clear the pending exception, JS will try to wrap it as it
+ // leaves the current compartment. Since there is no previous compartment,
+ // that would crash.
+ JS_ClearPendingException(cx);
+
+ if (!toVariant(cx, exn, &rs->exn()))
+ return true;
+
+ return true;
+}
+
+bool
+JavaScriptChild::ok(ReturnStatus *rs)
+{
+ *rs = ReturnStatus(true, JSVariant(void_t()));
+ return true;
+}
+
+bool
+JavaScriptChild::AnswerHas(const ObjectId &objId, const nsString &id,
+ ReturnStatus *rs, bool *bp)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ RootedId internedId(cx);
+ if (!convertGeckoStringToId(cx, id, &internedId))
+ return fail(cx, rs);
+
+ JSBool found;
+ if (!JS_HasPropertyById(cx, obj, internedId, &found))
+ return fail(cx, rs);
+ *bp = !!found;
+
+ return ok(rs);
+}
+
+bool
+JavaScriptChild::AnswerHasOwn(const ObjectId &objId, const nsString &id,
+ ReturnStatus *rs, bool *bp)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ RootedId internedId(cx);
+ if (!convertGeckoStringToId(cx, id, &internedId))
+ return fail(cx, rs);
+
+ JSPropertyDescriptor desc;
+ if (!JS_GetPropertyDescriptorById(cx, obj, internedId, 0, &desc))
+ return fail(cx, rs);
+ *bp = (desc.obj == obj);
+
+ return ok(rs);
+}
+
+bool
+JavaScriptChild::AnswerGet(const ObjectId &objId, const ObjectId &receiverId,
+ const nsString &id,
+ ReturnStatus *rs, JSVariant *result)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ RootedObject receiver(cx, findObject(receiverId));
+ if (!receiver)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ RootedId internedId(cx);
+ if (!convertGeckoStringToId(cx, id, &internedId))
+ return fail(cx, rs);
+
+ JS::Value val;
+ if (!JS_ForwardGetPropertyTo(cx, obj, internedId, receiver, &val))
+ return fail(cx, rs);
+
+ if (!toVariant(cx, val, result))
+ return fail(cx, rs);
+
+ return ok(rs);
+}
+
+bool
+JavaScriptChild::AnswerSet(const ObjectId &objId, const ObjectId &receiverId,
+ const nsString &id, const bool &strict,
+ const JSVariant &value,
+ ReturnStatus *rs, JSVariant *result)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ // The outparam will be written to the buffer, so it must be set even if
+ // the parent won't read it.
+ *result = void_t();
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ RootedObject receiver(cx, findObject(receiverId));
+ if (!receiver)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ RootedId internedId(cx);
+ if (!convertGeckoStringToId(cx, id, &internedId))
+ return fail(cx, rs);
+
+ MOZ_ASSERT(obj == receiver);
+
+ RootedValue val(cx);
+
+ if (!toValue(cx, value, &val))
+ return fail(cx, rs);
+
+ if (!JS_SetPropertyById(cx, obj, internedId, val.address()))
+ return fail(cx, rs);
+
+ if (!toVariant(cx, val, result))
+ return fail(cx, rs);
+
+ return ok(rs);
+}
+
+bool
+JavaScriptChild::AnswerCall(const ObjectId &objId,
+ const nsTArray<JSParam> &argv,
+ ReturnStatus *rs,
+ JSVariant *result,
+ nsTArray<JSParam> *outparams)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ // The outparam will be written to the buffer, so it must be set even if
+ // the parent won't read it.
+ *result = void_t();
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ MOZ_ASSERT(argv.Length() >= 2);
+
+ RootedValue objv(cx);
+ if (!toValue(cx, argv[0], &objv))
+ return fail(cx, rs);
+
+ JSAutoCompartment comp(cx, &objv.toObject());
+
+ *result = JSVariant(void_t());
+
+ JS::AutoValueVector vals(cx);
+ JS::AutoValueVector outobjects(cx);
+ for (size_t i = 0; i < argv.Length(); i++) {
+ if (argv[i].type() == JSParam::Tvoid_t) {
+ // This is an outparam.
+ JSCompartment *compartment = js::GetContextCompartment(cx);
+ RootedObject global(cx, JS_GetGlobalForCompartmentOrNull(cx, compartment));
+ RootedObject obj(cx, xpc::NewOutObject(cx, global));
+ if (!obj)
+ return fail(cx, rs);
+ if (!outobjects.append(ObjectValue(*obj)))
+ return fail(cx, rs);
+ if (!vals.append(ObjectValue(*obj)))
+ return fail(cx, rs);
+ } else {
+ RootedValue v(cx);
+ if (!toValue(cx, argv[i].get_JSVariant(), &v))
+ return fail(cx, rs);
+ if (!vals.append(v))
+ return fail(cx, rs);
+ }
+ }
+
+ uint32_t oldOpts =
+ JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT);
+
+ jsval rval;
+ bool success = JS::Call(cx, vals[1], vals[0], vals.length() - 2, vals.begin() + 2, &rval);
+
+ JS_SetOptions(cx, oldOpts);
+
+ if (!success)
+ return fail(cx, rs);
+
+ if (!toVariant(cx, rval, result))
+ return fail(cx, rs);
+
+ // Prefill everything with a dummy jsval.
+ for (size_t i = 0; i < outobjects.length(); i++)
+ outparams->AppendElement(JSParam(void_t()));
+
+ // Go through each argument that was an outparam, retrieve the "value"
+ // field, and add it to a temporary list. We need to do this separately
+ // because the outparams vector is not rooted.
+ vals.clear();
+ for (size_t i = 0; i < outobjects.length(); i++) {
+ RootedObject obj(cx, &outobjects[i].toObject());
+
+ jsval v;
+ JSBool found;
+ if (JS_HasProperty(cx, obj, "value", &found)) {
+ if (!JS_GetProperty(cx, obj, "value", &v))
+ return fail(cx, rs);
+ } else {
+ v = UndefinedValue();
+ }
+ if (!vals.append(v))
+ return fail(cx, rs);
+ }
+
+ // Copy the outparams. If any outparam is already set to a void_t, we
+ // treat this as the outparam never having been set.
+ for (size_t i = 0; i < vals.length(); i++) {
+ JSVariant variant;
+ if (!toVariant(cx, vals[i], &variant))
+ return fail(cx, rs);
+ outparams->ReplaceElementAt(i, JSParam(variant));
+ }
+
+ return ok(rs);
+}
+
+bool
+JavaScriptChild::AnswerInstanceOf(const ObjectId &objId,
+ const JSIID &iid,
+ ReturnStatus *rs,
+ bool *instanceof)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ nsID nsiid;
+ ConvertID(iid, &nsiid);
+
+ nsresult rv = xpc::HasInstance(cx, obj, &nsiid, instanceof);
+ if (rv != NS_OK)
+ return fail(cx, rs);
+
+ return ok(rs);
+}
+
+void
+EmptyDesc(PPropertyDescriptor *desc)
+{
+ desc->objId() = 0;
+ desc->attrs() = 0;
+ desc->shortid() = 0;
+ desc->value() = void_t();
+ desc->getter() = 0;
+ desc->setter() = 0;
+}
+
+bool
+JavaScriptChild::AnswerGetPropertyDescriptor(const ObjectId &objId,
+ const nsString &id,
+ const uint32_t &flags,
+ ReturnStatus *rs,
+ PPropertyDescriptor *out)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ RootedId internedId(cx);
+ if (!convertGeckoStringToId(cx, id, &internedId))
+ return fail(cx, rs);
+
+ JSPropertyDescriptor desc;
+ if (!JS_GetPropertyDescriptorById(cx, obj, internedId, flags, &desc))
+ return fail(cx, rs);
+
+ if (!desc.obj) {
+ EmptyDesc(out);
+ return ok(rs);
+ }
+
+ if (!fromDescriptor(cx, desc, out))
+ return fail(cx, rs);
+
+ return ok(rs);
+}
+
+bool
+JavaScriptChild::AnswerGetOwnPropertyDescriptor(const ObjectId &objId,
+ const nsString &id,
+ const uint32_t &flags,
+ ReturnStatus *rs,
+ PPropertyDescriptor *out)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ RootedId internedId(cx);
+ if (!convertGeckoStringToId(cx, id, &internedId))
+ return fail(cx, rs);
+
+ JSPropertyDescriptor desc;
+ if (!JS_GetPropertyDescriptorById(cx, obj, internedId, flags, &desc))
+ return fail(cx, rs);
+
+ if (desc.obj != obj) {
+ EmptyDesc(out);
+ return ok(rs);
+ }
+
+ if (!fromDescriptor(cx, desc, out))
+ return fail(cx, rs);
+
+ return ok(rs);
+}
+
+bool
+JavaScriptChild::AnswerGetOwnPropertyNames(const ObjectId &objId,
+ ReturnStatus *rs,
+ nsTArray<nsString> *names)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ AutoIdVector props(cx);
+ if (!js::GetPropertyNames(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &props))
+ return fail(cx, rs);
+
+ for (size_t i = 0; i < props.length(); i++) {
+ nsString name;
+ if (!convertIdToGeckoString(cx, props.handleAt(i), &name))
+ return false;
+
+ names->AppendElement(name);
+ }
+
+ return ok(rs);
+}
+
+bool
+JavaScriptChild::AnswerKeys(const ObjectId &objId,
+ ReturnStatus *rs,
+ nsTArray<nsString> *names)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ AutoIdVector props(cx);
+ if (!js::GetPropertyNames(cx, obj, JSITER_OWNONLY, &props))
+ return fail(cx, rs);
+
+ for (size_t i = 0; i < props.length(); i++) {
+ nsString name;
+ if (!convertIdToGeckoString(cx, props.handleAt(i), &name))
+ return false;
+
+ names->AppendElement(name);
+ }
+
+ return ok(rs);
+}
+
+bool
+JavaScriptChild::AnswerObjectClassIs(const ObjectId &objId,
+ const uint32_t &classValue,
+ bool *result)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ *result = js_ObjectClassIs(cx, obj, (js::ESClassValue)classValue);
+
+ return true;
+}
+
+bool
+JavaScriptChild::AnswerClassName(const ObjectId &objId,
+ nsString *name)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+
+ *name = NS_ConvertASCIItoUTF16(js_ObjectClassName(cx, obj));
+ return true;
+}
+
+bool
+JavaScriptChild::AnswerIsExtensible(const ObjectId &objId,
+ ReturnStatus *rs,
+ bool *result)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ *result = false;
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSBool extensible;
+ if (!JS_IsExtensible(cx, obj, &extensible))
+ return fail(cx, rs);
+
+ *result = !!extensible;
+ return true;
+}
+
+bool
+JavaScriptChild::AnswerPreventExtensions(const ObjectId &objId,
+ ReturnStatus *rs)
+{
+ AutoSafeJSContext cx;
+ JSAutoRequest request(cx);
+
+ RootedObject obj(cx, findObject(objId));
+ if (!obj)
+ return false;
+
+ JSAutoCompartment comp(cx, obj);
+ if (!JS_PreventExtensions(cx, obj))
+ return fail(cx, rs);
+
+ return ok(rs);
+}
new file mode 100644
--- /dev/null
+++ b/js/ipc/JavaScriptChild.h
@@ -0,0 +1,95 @@
+/* -*- 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/. */
+
+#ifndef mozilla_jsipc_JavaScriptChild_h_
+#define mozilla_jsipc_JavaScriptChild_h_
+
+#include "JavaScriptShared.h"
+#include "mozilla/jsipc/PJavaScriptChild.h"
+
+namespace mozilla {
+namespace jsipc {
+
+class JavaScriptChild
+ : public PJavaScriptChild,
+ public JavaScriptShared
+{
+ public:
+ JavaScriptChild(JSRuntime *rt);
+ ~JavaScriptChild();
+
+ bool init();
+ void trace(JSTracer *trc);
+
+ bool RecvDropObject(const ObjectId &objId);
+
+ bool AnswerHas(const ObjectId &objId, const nsString &id,
+ ReturnStatus *rs, bool *bp);
+ bool AnswerHasOwn(const ObjectId &objId, const nsString &id,
+ ReturnStatus *rs, bool *bp);
+ bool AnswerGet(const ObjectId &objId, const ObjectId &receiverId,
+ const nsString &id,
+ ReturnStatus *rs, JSVariant *result);
+ bool AnswerSet(const ObjectId &objId, const ObjectId &receiverId,
+ const nsString &id, const bool &strict,
+ const JSVariant &value,
+ ReturnStatus *rs, JSVariant *result);
+ bool AnswerCall(const ObjectId &objId,
+ const nsTArray<JSParam> &argv,
+ ReturnStatus *rs,
+ JSVariant *result,
+ nsTArray<JSParam> *outparams);
+
+ bool AnswerInstanceOf(const ObjectId &objId,
+ const JSIID &iid,
+ ReturnStatus *rs,
+ bool *instanceof);
+ bool AnswerGetPropertyDescriptor(const ObjectId &objId,
+ const nsString &id,
+ const uint32_t &flags,
+ ReturnStatus *rs,
+ PPropertyDescriptor *out);
+ bool AnswerGetOwnPropertyDescriptor(const ObjectId &objId,
+ const nsString &id,
+ const uint32_t &flags,
+ ReturnStatus *rs,
+ PPropertyDescriptor *out);
+ bool AnswerGetOwnPropertyNames(const ObjectId &objId,
+ ReturnStatus *rs,
+ nsTArray<nsString> *names);
+ bool AnswerKeys(const ObjectId &objId,
+ ReturnStatus *rs,
+ nsTArray<nsString> *names);
+ bool AnswerObjectClassIs(const ObjectId &objId,
+ const uint32_t &classValue,
+ bool *result);
+ bool AnswerClassName(const ObjectId &objId,
+ nsString *result);
+ bool AnswerIsExtensible(const ObjectId &objId,
+ ReturnStatus *rs,
+ bool *result);
+ bool AnswerPreventExtensions(const ObjectId &objId,
+ ReturnStatus *rs);
+
+ protected:
+ JSObject *unwrap(JSContext *cx, ObjectId id);
+
+ private:
+ bool makeId(JSContext *cx, JSObject *obj, ObjectId *idp);
+ bool fail(JSContext *cx, ReturnStatus *rs);
+ bool ok(ReturnStatus *rs);
+
+ private:
+ ObjectId lastId_;
+ JSRuntime *rt_;
+ ObjectIdCache ids_;
+};
+
+} // mozilla
+} // jsipc
+
+#endif
new file mode 100644
--- /dev/null
+++ b/js/ipc/JavaScriptParent.cpp
@@ -0,0 +1,635 @@
+/* -*- 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 "JavaScriptParent.h"
+#include "mozilla/dom/ContentParent.h"
+#include "nsJSUtils.h"
+#include "jsfriendapi.h"
+#include "jsproxy.h"
+#include "HeapAPI.h"
+#include "xpcprivate.h"
+#include "mozilla/Casting.h"
+
+using namespace js;
+using namespace JS;
+using namespace mozilla;
+using namespace mozilla::jsipc;
+
+JavaScriptParent::JavaScriptParent()
+ : refcount_(1),
+ inactive_(false)
+{
+}
+
+static inline JavaScriptParent *
+ParentOf(JSObject *obj)
+{
+ MOZ_ASSERT(JavaScriptParent::IsCPOW(obj));
+ return reinterpret_cast<JavaScriptParent *>(GetProxyExtra(obj, 0).toPrivate());
+}
+
+ObjectId
+JavaScriptParent::idOf(JSObject *obj)
+{
+ MOZ_ASSERT(JavaScriptParent::IsCPOW(obj));
+
+ Value v = GetProxyExtra(obj, 1);
+ MOZ_ASSERT(v.isDouble());
+
+ ObjectId objId = BitwiseCast<uint64_t>(v.toDouble());
+ MOZ_ASSERT(findObject(objId) == obj);
+ MOZ_ASSERT(objId);
+
+ return objId;
+}
+
+int sCPOWProxyHandler;
+
+class CPOWProxyHandler : public BaseProxyHandler
+{
+ public:
+ CPOWProxyHandler()
+ : BaseProxyHandler(&sCPOWProxyHandler) {}
+ virtual ~CPOWProxyHandler() {}
+
+ virtual bool finalizeInBackground(Value priv) MOZ_OVERRIDE {
+ return false;
+ }
+
+ virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
+ PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE;
+ virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
+ HandleId id, PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE;
+ virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
+ PropertyDescriptor *desc) MOZ_OVERRIDE;
+ virtual bool getOwnPropertyNames(JSContext *cx, HandleObject proxy,
+ AutoIdVector &props) MOZ_OVERRIDE;
+ virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
+ virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
+
+ virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
+ virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) MOZ_OVERRIDE;
+ virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
+ HandleId id, MutableHandleValue vp) MOZ_OVERRIDE;
+ virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
+ JS::HandleId id, bool strict, JS::MutableHandleValue vp) MOZ_OVERRIDE;
+ virtual bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) MOZ_OVERRIDE;
+ virtual bool iterate(JSContext *cx, HandleObject proxy, unsigned flags,
+ MutableHandleValue vp) MOZ_OVERRIDE;
+
+ virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) MOZ_OVERRIDE;
+ virtual void finalize(JSFreeOp *fop, JSObject *proxy) MOZ_OVERRIDE;
+ virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
+ virtual const char* className(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
+ virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
+ virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) MOZ_OVERRIDE;
+
+ static CPOWProxyHandler singleton;
+};
+
+CPOWProxyHandler CPOWProxyHandler::singleton;
+
+bool
+CPOWProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
+ PropertyDescriptor *desc, unsigned flags)
+{
+ return ParentOf(proxy)->getPropertyDescriptor(cx, proxy, id, desc, flags);
+}
+
+bool
+JavaScriptParent::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
+ PropertyDescriptor *desc, unsigned flags)
+{
+ ObjectId objId = idOf(proxy);
+
+ nsString idstr;
+ if (!convertIdToGeckoString(cx, id, &idstr))
+ return false;
+
+ ReturnStatus status;
+ PPropertyDescriptor result;
+ if (!CallGetPropertyDescriptor(objId, idstr, flags, &status, &result))
+ return ipcfail(cx);
+ if (!ok(cx, status))
+ return false;
+
+ return toDescriptor(cx, result, desc);
+}
+
+bool
+CPOWProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
+ HandleId id, PropertyDescriptor *desc, unsigned flags)
+{
+ return ParentOf(proxy)->getOwnPropertyDescriptor(cx, proxy, id, desc, flags);
+}
+
+bool
+JavaScriptParent::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
+ PropertyDescriptor *desc, unsigned flags)
+{
+ ObjectId objId = idOf(proxy);
+
+ nsString idstr;
+ if (!convertIdToGeckoString(cx, id, &idstr))
+ return false;
+
+ ReturnStatus status;
+ PPropertyDescriptor result;
+ if (!CallGetOwnPropertyDescriptor(objId, idstr, flags, &status, &result))
+ return ipcfail(cx);
+ if (!ok(cx, status))
+ return false;
+
+ return toDescriptor(cx, result, desc);
+}
+
+bool
+CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
+ PropertyDescriptor *desc)
+{
+ MOZ_CRASH("unimplemented");
+}
+
+bool
+CPOWProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
+{
+ return ParentOf(proxy)->getOwnPropertyNames(cx, proxy, props);
+}
+
+bool
+JavaScriptParent::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
+{
+ ObjectId objId = idOf(proxy);
+
+ ReturnStatus status;
+ InfallibleTArray<nsString> names;
+ if (!CallGetOwnPropertyNames(objId, &status, &names))
+ return ipcfail(cx);
+ if (!ok(cx, status))
+ return false;
+
+ RootedId name(cx);
+ for (size_t i = 0; i < names.Length(); i++) {
+ if (!convertGeckoStringToId(cx, names[i], &name))
+ return false;
+ if (!props.append(name))
+ return false;
+ }
+
+ return true;
+}
+
+bool
+CPOWProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
+{
+ return ParentOf(proxy)->keys(cx, proxy, props);
+}
+
+bool
+JavaScriptParent::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
+{
+ ObjectId objId = idOf(proxy);
+
+ ReturnStatus status;
+ InfallibleTArray<nsString> names;
+ if (!CallKeys(objId, &status, &names))
+ return ipcfail(cx);
+ if (!ok(cx, status))
+ return false;
+
+ RootedId name(cx);
+ for (size_t i = 0; i < names.Length(); i++) {
+ if (!convertGeckoStringToId(cx, names[i], &name))
+ return false;
+ if (!props.append(name))
+ return false;
+ }
+
+ return true;
+}
+
+bool
+CPOWProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
+{
+ MOZ_CRASH("unimplemented");
+}
+
+bool
+CPOWProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
+{
+ MOZ_CRASH("unimplemented");
+}
+
+bool
+CPOWProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
+{
+ return ParentOf(proxy)->preventExtensions(cx, proxy);
+}
+
+bool
+JavaScriptParent::preventExtensions(JSContext *cx, HandleObject proxy)
+{
+ ObjectId objId = idOf(proxy);
+
+ ReturnStatus status;
+ if (!CallPreventExtensions(objId, &status))
+ return ipcfail(cx);
+
+ return ok(cx, status);
+}
+
+bool
+CPOWProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
+{
+ return ParentOf(proxy)->isExtensible(cx, proxy, extensible);
+}
+
+bool
+JavaScriptParent::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
+{
+ ObjectId objId = idOf(proxy);
+
+ ReturnStatus status;
+ if (!CallIsExtensible(objId, &status, extensible))
+ return ipcfail(cx);
+
+ return ok(cx, status);
+}
+
+bool
+CPOWProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
+{
+ return ParentOf(proxy)->has(cx, proxy, id, bp);
+}
+
+bool
+JavaScriptParent::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
+{
+ ObjectId objId = idOf(proxy);
+
+ nsString idstr;
+ if (!convertIdToGeckoString(cx, id, &idstr))
+ return false;
+
+ ReturnStatus status;
+ if (!CallHas(objId, idstr, &status, bp))
+ return ipcfail(cx);
+
+ return ok(cx, status);
+}
+
+bool
+CPOWProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
+{
+ return ParentOf(proxy)->hasOwn(cx, proxy, id, bp);
+}
+
+bool
+JavaScriptParent::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
+{
+ ObjectId objId = idOf(proxy);
+
+ nsString idstr;
+ if (!convertIdToGeckoString(cx, id, &idstr))
+ return false;
+
+ ReturnStatus status;
+ if (!CallHasOwn(objId, idstr, &status, bp))
+ return ipcfail(cx);
+
+ return !!ok(cx, status);
+}
+
+bool
+CPOWProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
+ HandleId id, MutableHandleValue vp)
+{
+ return ParentOf(proxy)->get(cx, proxy, receiver, id, vp);
+}
+
+bool
+JavaScriptParent::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
+ HandleId id, MutableHandleValue vp)
+{
+ ObjectId objId = idOf(proxy);
+ ObjectId receiverId = idOf(receiver);
+
+ nsString idstr;
+ if (!convertIdToGeckoString(cx, id, &idstr))
+ return false;
+
+ JSVariant val;
+ ReturnStatus status;
+ if (!CallGet(objId, receiverId, idstr, &status, &val))
+ return ipcfail(cx);
+
+ if (!ok(cx, status))
+ return false;
+
+ return toValue(cx, val, vp);
+}
+
+bool
+CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
+ JS::HandleId id, bool strict, JS::MutableHandleValue vp)
+{
+ return ParentOf(proxy)->set(cx, proxy, receiver, id, strict, vp);
+}
+
+bool
+JavaScriptParent::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
+ JS::HandleId id, bool strict, JS::MutableHandleValue vp)
+{
+ ObjectId objId = idOf(proxy);
+ ObjectId receiverId = idOf(receiver);
+
+ nsString idstr;
+ if (!convertIdToGeckoString(cx, id, &idstr))
+ return false;
+
+ JSVariant val;
+ if (!toVariant(cx, vp, &val))
+ return false;
+
+ ReturnStatus status;
+ JSVariant result;
+ if (!CallSet(objId, receiverId, idstr, strict, val, &status, &result))
+ return ipcfail(cx);
+
+ if (!ok(cx, status))
+ return false;
+
+ return toValue(cx, result, vp);
+}
+
+bool
+CPOWProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags,
+ MutableHandleValue vp)
+{
+ MOZ_CRASH("unimplemented");
+}
+
+bool
+CPOWProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
+{
+ return ParentOf(proxy)->call(cx, proxy, args);
+}
+
+bool
+JavaScriptParent::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
+{
+ ObjectId objId = idOf(proxy);
+
+ InfallibleTArray<JSParam> vals;
+ AutoValueVector outobjects(cx);
+
+ RootedValue v(cx);
+ for (size_t i = 0; i < args.length() + 2; i++) {
+ v = args.base()[i];
+ if (v.isObject()) {
+ JSObject *obj = &v.toObject();
+ if (xpc::IsOutObject(cx, obj)) {
+ // Make sure it is not an in-out object.
+ JSBool found;
+ if (!JS_HasProperty(cx, obj, "value", &found))
+ return false;
+ if (found) {
+ JS_ReportError(cx, "in-out objects cannot be sent via CPOWs yet");
+ 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;
+ if (!CallCall(objId, vals, &status, &result, &outparams))
+ return ipcfail(cx);
+ if (!ok(cx, status))
+ return false;
+
+ if (outparams.Length() != outobjects.length())
+ return ipcfail(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 (!toValue(cx, outparams[i], &v))
+ return false;
+
+ JSObject *obj = &outobjects[i].toObject();
+ if (!JS_SetProperty(cx, obj, "value", v.address()))
+ return false;
+ }
+
+ if (!toValue(cx, result, args.rval()))
+ return false;
+
+ return true;
+}
+
+void
+CPOWProxyHandler::finalize(JSFreeOp *fop, JSObject *proxy)
+{
+ ParentOf(proxy)->drop(proxy);
+}
+
+void
+JavaScriptParent::drop(JSObject *obj)
+{
+ if (inactive_)
+ return;
+
+ ObjectId objId = idOf(obj);
+
+ objects_.remove(objId);
+ if (!SendDropObject(objId))
+ MOZ_CRASH();
+ decref();
+}
+
+bool
+CPOWProxyHandler::objectClassIs(HandleObject proxy, js::ESClassValue classValue, JSContext *cx)
+{
+ return ParentOf(proxy)->objectClassIs(cx, proxy, classValue);
+}
+
+bool
+JavaScriptParent::objectClassIs(JSContext *cx, HandleObject proxy, js::ESClassValue classValue)
+{
+ ObjectId objId = idOf(proxy);
+
+ // This function is assumed infallible, so we just return false if the IPC
+ // channel fails.
+ bool result;
+ if (!CallObjectClassIs(objId, classValue, &result))
+ return false;
+
+ return result;
+}
+
+const char *
+CPOWProxyHandler::className(JSContext *cx, HandleObject proxy)
+{
+ return ParentOf(proxy)->className(cx, proxy);
+}
+
+const char *
+JavaScriptParent::className(JSContext *cx, HandleObject proxy)
+{
+ ObjectId objId = idOf(proxy);
+
+ nsString name;
+ if (!CallClassName(objId, &name))
+ return NULL;
+
+ return ToNewCString(name);
+}
+
+bool
+JavaScriptParent::init()
+{
+ if (!JavaScriptShared::init())
+ return false;
+
+ return true;
+}
+
+bool
+JavaScriptParent::makeId(JSContext *cx, JSObject *obj, ObjectId *idp)
+{
+ if (!IsProxy(obj) || GetProxyHandler(obj) != &CPOWProxyHandler::singleton) {
+ JS_ReportError(cx, "cannot ipc non-cpow object");
+ return false;
+ }
+
+ *idp = idOf(obj);
+ return true;
+}
+
+JSObject *
+JavaScriptParent::unwrap(JSContext *cx, ObjectId objId)
+{
+ if (JSObject *obj = findObject(objId)) {
+ if (!JS_WrapObject(cx, &obj))
+ return NULL;
+ return obj;
+ }
+
+ if (objId > MAX_CPOW_IDS) {
+ JS_ReportError(cx, "unusable CPOW id");
+ return NULL;
+ }
+
+ bool callable = !!(objId & OBJECT_IS_CALLABLE);
+
+ RootedValue v(cx, UndefinedValue());
+ JSObject *obj = NewProxyObject(cx,
+ &CPOWProxyHandler::singleton,
+ v,
+ NULL,
+ NULL,
+ callable ? ProxyIsCallable : ProxyNotCallable);
+ if (!obj)
+ return NULL;
+
+ if (!objects_.add(objId, obj))
+ return NULL;
+
+ // Incref once we know the decref will be called.
+ incref();
+
+ SetProxyExtra(obj, 0, PrivateValue(this));
+ SetProxyExtra(obj, 1, DoubleValue(BitwiseCast<double>(objId)));
+ return obj;
+}
+
+bool
+JavaScriptParent::ipcfail(JSContext *cx)
+{
+ JS_ReportError(cx, "catastrophic IPC failure");
+ return false;
+}
+
+bool
+JavaScriptParent::ok(JSContext *cx, const ReturnStatus &status)
+{
+ if (status.ok())
+ return true;
+
+ RootedValue exn(cx);
+ if (!toValue(cx, status.exn(), &exn))
+ return false;
+
+ JS_SetPendingException(cx, exn);
+ return false;
+}
+
+void
+JavaScriptParent::decref()
+{
+ refcount_--;
+ if (!refcount_)
+ delete this;
+}
+
+void
+JavaScriptParent::incref()
+{
+ refcount_++;
+}
+
+void
+JavaScriptParent::destroyFromContent()
+{
+ inactive_ = true;
+ decref();
+}
+
+/* static */ bool
+JavaScriptParent::IsCPOW(JSObject *obj)
+{
+ return IsProxy(obj) && GetProxyHandler(obj) == &CPOWProxyHandler::singleton;
+}
+
+/* static */ nsresult
+JavaScriptParent::InstanceOf(JSObject *obj, const nsID *id, bool *bp)
+{
+ return ParentOf(obj)->instanceOf(obj, id, bp);
+}
+
+nsresult
+JavaScriptParent::instanceOf(JSObject *obj, const nsID *id, bool *bp)
+{
+ ObjectId objId = idOf(obj);
+
+ JSIID iid;
+ ConvertID(*id, &iid);
+
+ ReturnStatus status;
+ if (!CallInstanceOf(objId, iid, &status, bp))
+ return NS_ERROR_UNEXPECTED;
+
+ if (!status.ok())
+ return NS_ERROR_UNEXPECTED;
+
+ return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/js/ipc/JavaScriptParent.h
@@ -0,0 +1,84 @@
+/* -*- 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/. */
+
+#ifndef mozilla_jsipc_JavaScriptParent__
+#define mozilla_jsipc_JavaScriptParent__
+
+#include "JavaScriptShared.h"
+#include "mozilla/jsipc/PJavaScriptParent.h"
+#include "jsclass.h"
+
+#ifdef XP_WIN
+#undef GetClassName
+#undef GetClassInfo
+#endif
+
+namespace mozilla {
+namespace jsipc {
+
+class JavaScriptParent
+ : public PJavaScriptParent,
+ public JavaScriptShared
+{
+ public:
+ JavaScriptParent();
+
+ bool init();
+
+ public:
+ bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
+ bool hasOwn(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
+ bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
+ JS::HandleId id, JS::MutableHandleValue vp);
+ bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
+ JS::HandleId id, bool strict, JS::MutableHandleValue vp);
+ bool call(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args);
+ bool getPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
+ JSPropertyDescriptor *desc, unsigned flags);
+ bool getOwnPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
+ JSPropertyDescriptor *desc, unsigned flags);
+ bool getOwnPropertyNames(JSContext *cx, JS::HandleObject proxy, js::AutoIdVector &props);
+ bool keys(JSContext *cx, JS::HandleObject proxy, js::AutoIdVector &props);
+ bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
+ const char* className(JSContext *cx, JS::HandleObject proxy);
+ bool preventExtensions(JSContext *cx, JS::HandleObject proxy);
+ bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
+
+ void decref();
+ void incref();
+ void destroyFromContent();
+
+ void drop(JSObject *obj);
+
+ static bool IsCPOW(JSObject *obj);
+ static nsresult InstanceOf(JSObject *obj, const nsID *id, bool *bp);
+
+ nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp);
+
+ protected:
+ JSObject *unwrap(JSContext *cx, ObjectId objId);
+
+ private:
+ bool makeId(JSContext *cx, JSObject *obj, ObjectId *idp);
+ ObjectId idOf(JSObject *obj);
+
+ // Catastrophic IPC failure.
+ bool ipcfail(JSContext *cx);
+
+ // Check whether a return status is okay, and if not, propagate its error.
+ bool ok(JSContext *cx, const ReturnStatus &status);
+
+ private:
+ uintptr_t refcount_;
+ bool inactive_;
+};
+
+} // jsipc
+} // mozilla
+
+#endif // mozilla_jsipc_JavaScriptWrapper_h__
+
new file mode 100644
--- /dev/null
+++ b/js/ipc/JavaScriptShared.cpp
@@ -0,0 +1,397 @@
+/* -*- 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 "JavaScriptShared.h"
+#include "jsfriendapi.h"
+#include "xpcprivate.h"
+
+using namespace js;
+using namespace JS;
+using namespace mozilla;
+using namespace mozilla::jsipc;
+
+ObjectStore::ObjectStore()
+ : table_(SystemAllocPolicy())
+{
+}
+
+bool
+ObjectStore::init()
+{
+ return table_.init(32);
+}
+
+void
+ObjectStore::trace(JSTracer *trc)
+{
+ for (ObjectTable::Range r(table_.all()); !r.empty(); r.popFront()) {
+ JSObject *obj = r.front().value;
+ JS_CallObjectTracer(trc, &obj, "ipc-object");
+ MOZ_ASSERT(obj == r.front().value);
+ }
+}
+
+JSObject *
+ObjectStore::find(ObjectId id)
+{
+ ObjectTable::Ptr p = table_.lookup(id);
+ if (!p)
+ return NULL;
+ return p->value;
+}
+
+bool
+ObjectStore::add(ObjectId id, JSObject *obj)
+{
+ return table_.put(id, obj);
+}
+
+void
+ObjectStore::remove(ObjectId id)
+{
+ table_.remove(id);
+}
+
+ObjectIdCache::ObjectIdCache()
+ : table_(SystemAllocPolicy())
+{
+}
+
+bool
+ObjectIdCache::init()
+{
+ return table_.init(32);
+}
+
+void
+ObjectIdCache::trace(JSTracer *trc)
+{
+ for (ObjectIdTable::Range r(table_.all()); !r.empty(); r.popFront()) {
+ JSObject *obj = r.front().key;
+ JS_CallObjectTracer(trc, &obj, "ipc-id");
+ MOZ_ASSERT(obj == r.front().key);
+ }
+}
+
+ObjectId
+ObjectIdCache::find(JSObject *obj)
+{
+ ObjectIdTable::Ptr p = table_.lookup(obj);
+ if (!p)
+ return 0;
+ return p->value;
+}
+
+bool
+ObjectIdCache::add(JSObject *obj, ObjectId id)
+{
+ return table_.put(obj, id);
+}
+
+void
+ObjectIdCache::remove(JSObject *obj)
+{
+ table_.remove(obj);
+}
+
+bool
+JavaScriptShared::init()
+{
+ if (!objects_.init())
+ return false;
+ return true;
+}
+
+bool
+JavaScriptShared::convertIdToGeckoString(JSContext *cx, JS::HandleId id, nsString *to)
+{
+ RootedValue idval(cx);
+ if (!JS_IdToValue(cx, id, idval.address()))
+ return false;
+
+ RootedString str(cx, JS_ValueToString(cx, idval));
+ if (!str)
+ return false;
+
+ const jschar *chars = JS_GetStringCharsZ(cx, str);
+ if (!chars)
+ return false;
+
+ *to = chars;
+ return true;
+}
+
+bool
+JavaScriptShared::convertGeckoStringToId(JSContext *cx, const nsString &from, JS::MutableHandleId to)
+{
+ RootedString str(cx, JS_NewUCStringCopyN(cx, from.BeginReading(), from.Length()));
+ if (!str)
+ return false;
+
+ return JS_ValueToId(cx, StringValue(str), to.address());
+}
+
+bool
+JavaScriptShared::toVariant(JSContext *cx, jsval from, JSVariant *to)
+{
+ switch (JS_TypeOfValue(cx, from)) {
+ case JSTYPE_VOID:
+ *to = void_t();
+ return true;
+
+ case JSTYPE_NULL:
+ {
+ *to = uint64_t(0);
+ return true;
+ }
+
+ case JSTYPE_OBJECT:
+ case JSTYPE_FUNCTION:
+ {
+ JSObject *obj = from.toObjectOrNull();
+ if (!obj) {
+ JS_ASSERT(from == JSVAL_NULL);
+ *to = uint64_t(0);
+ return true;
+ }
+
+ if (xpc_JSObjectIsID(cx, obj)) {
+ JSIID iid;
+ const nsID *id = xpc_JSObjectToID(cx, obj);
+ ConvertID(*id, &iid);
+ *to = iid;
+ return true;
+ }
+
+ ObjectId id;
+ if (!makeId(cx, obj, &id))
+ return false;
+ *to = uint64_t(id);
+ return true;
+ }
+
+ case JSTYPE_STRING:
+ {
+ nsDependentJSString dep;
+ if (!dep.init(cx, from))
+ return false;
+ *to = dep;
+ return true;
+ }
+
+ case JSTYPE_NUMBER:
+ if (JSVAL_IS_INT(from))
+ *to = double(from.toInt32());
+ else
+ *to = from.toDouble();
+ return true;
+
+ case JSTYPE_BOOLEAN:
+ *to = from.toBoolean();
+ return true;
+
+ default:
+ MOZ_ASSERT(false);
+ return false;
+ }
+}
+
+bool
+JavaScriptShared::toValue(JSContext *cx, const JSVariant &from, MutableHandleValue to)
+{
+ switch (from.type()) {
+ case JSVariant::Tvoid_t:
+ to.set(UndefinedValue());
+ return true;
+
+ case JSVariant::Tuint64_t:
+ {
+ ObjectId id = from.get_uint64_t();
+ if (id) {
+ JSObject *obj = unwrap(cx, id);
+ if (!obj)
+ return false;
+ to.set(ObjectValue(*obj));
+ } else {
+ to.set(JSVAL_NULL);
+ }
+ return true;
+ }
+
+ case JSVariant::Tdouble:
+ to.set(JS_NumberValue(from.get_double()));
+ return true;
+
+ case JSVariant::Tbool:
+ to.set(BOOLEAN_TO_JSVAL(from.get_bool()));
+ return true;
+
+ case JSVariant::TnsString:
+ {
+ const nsString &old = from.get_nsString();
+ JSString *str = JS_NewUCStringCopyN(cx, old.BeginReading(), old.Length());
+ if (!str)
+ return false;
+ to.set(StringValue(str));
+ return true;
+ }
+
+ case JSVariant::TJSIID:
+ {
+ nsID iid;
+ const JSIID &id = from.get_JSIID();
+ ConvertID(id, &iid);
+
+ JSCompartment *compartment = GetContextCompartment(cx);
+ RootedObject global(cx, JS_GetGlobalForCompartmentOrNull(cx, compartment));
+ JSObject *obj = xpc_NewIDObject(cx, global, iid);
+ if (!obj)
+ return false;
+ to.set(ObjectValue(*obj));
+ return true;
+ }
+
+ default:
+ return false;
+ }
+}
+
+/* static */ void
+JavaScriptShared::ConvertID(const nsID &from, JSIID *to)
+{
+ to->m0() = from.m0;
+ to->m1() = from.m1;
+ to->m2() = from.m2;
+ to->m3_0() = from.m3[0];
+ to->m3_1() = from.m3[1];
+ to->m3_2() = from.m3[2];
+ to->m3_3() = from.m3[3];
+ to->m3_4() = from.m3[4];
+ to->m3_5() = from.m3[5];
+ to->m3_6() = from.m3[6];
+ to->m3_7() = from.m3[7];
+}
+
+/* static */ void
+JavaScriptShared::ConvertID(const JSIID &from, nsID *to)
+{
+ to->m0 = from.m0();
+ to->m1 = from.m1();
+ to->m2 = from.m2();
+ to->m3[0] = from.m3_0();
+ to->m3[1] = from.m3_1();
+ to->m3[2] = from.m3_2();
+ to->m3[3] = from.m3_3();
+ to->m3[4] = from.m3_4();
+ to->m3[5] = from.m3_5();
+ to->m3[6] = from.m3_6();
+ to->m3[7] = from.m3_7();
+}
+
+static const uint32_t DefaultPropertyOp = 1;
+static const uint32_t GetterOnlyPropertyStub = 2;
+static const uint32_t UnknownPropertyOp = 3;
+
+bool
+JavaScriptShared::fromDescriptor(JSContext *cx, const JSPropertyDescriptor &desc, PPropertyDescriptor *out)
+{
+ out->attrs() = desc.attrs;
+ out->shortid() = desc.shortid;
+ if (!toVariant(cx, desc.value, &out->value()))
+ return false;
+
+ if (!makeId(cx, desc.obj, &out->objId()))
+ return false;
+
+ if (!desc.getter) {
+ out->getter() = 0;
+ } else if (desc.attrs & JSPROP_GETTER) {
+ JSObject *getter = JS_FUNC_TO_DATA_PTR(JSObject *, desc.getter);
+ if (!makeId(cx, getter, &out->getter()))
+ return false;
+ } else {
+ if (desc.getter == JS_PropertyStub)
+ out->getter() = DefaultPropertyOp;
+ else
+ out->getter() = UnknownPropertyOp;
+ }
+
+ if (!desc.setter) {
+ out->setter() = 0;
+ } else if (desc.attrs & JSPROP_SETTER) {
+ JSObject *setter = JS_FUNC_TO_DATA_PTR(JSObject *, desc.setter);
+ if (!makeId(cx, setter, &out->setter()))
+ return false;
+ } else {
+ if (desc.setter == JS_StrictPropertyStub)
+ out->setter() = DefaultPropertyOp;
+ else if (desc.setter == js_GetterOnlyPropertyStub)
+ out->setter() = GetterOnlyPropertyStub;
+ else
+ out->setter() = UnknownPropertyOp;
+ }
+
+ return true;
+}
+
+JSBool
+UnknownPropertyStub(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
+{
+ JS_ReportError(cx, "getter could not be wrapped via CPOWs");
+ return JS_FALSE;
+}
+
+JSBool
+UnknownStrictPropertyStub(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp)
+{
+ JS_ReportError(cx, "setter could not be wrapped via CPOWs");
+ return JS_FALSE;
+}
+
+bool
+JavaScriptShared::toDescriptor(JSContext *cx, const PPropertyDescriptor &in, JSPropertyDescriptor *out)
+{
+ out->attrs = in.attrs();
+ out->shortid = in.shortid();
+ if (!toValue(cx, in.value(), &out->value))
+ return false;
+ if (!unwrap(cx, in.objId(), &out->obj))
+ return false;
+
+ if (!in.getter()) {
+ out->getter = NULL;
+ } else if (in.attrs() & JSPROP_GETTER) {
+ JSObject *getter;
+ if (!unwrap(cx, in.getter(), &getter))
+ return false;
+ out->getter = JS_DATA_TO_FUNC_PTR(JSPropertyOp, getter);
+ } else {
+ if (in.getter() == DefaultPropertyOp)
+ out->getter = JS_PropertyStub;
+ else
+ out->getter = UnknownPropertyStub;
+ }
+
+ if (!in.setter()) {
+ out->setter = NULL;
+ } else if (in.attrs() & JSPROP_SETTER) {
+ JSObject *setter;
+ if (!unwrap(cx, in.setter(), &setter))
+ return false;
+ out->setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, setter);
+ } else {
+ if (in.setter() == DefaultPropertyOp)
+ out->setter = JS_StrictPropertyStub;
+ else if (in.setter() == GetterOnlyPropertyStub)
+ out->setter = js_GetterOnlyPropertyStub;
+ else
+ out->setter = UnknownStrictPropertyStub;
+ }
+
+ return true;
+}
+
new file mode 100644
--- /dev/null
+++ b/js/ipc/JavaScriptShared.h
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 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/. */
+
+#ifndef mozilla_jsipc_JavaScriptShared_h__
+#define mozilla_jsipc_JavaScriptShared_h__
+
+#include "jsapi.h"
+#include "jspubtd.h"
+#include "js/HashTable.h"
+#include "mozilla/dom/DOMTypes.h"
+#include "mozilla/jsipc/PJavaScript.h"
+#include "nsJSUtils.h"
+#include "nsFrameMessageManager.h"
+
+namespace mozilla {
+namespace jsipc {
+
+typedef uint64_t ObjectId;
+
+// Map ids -> JSObjects
+class ObjectStore
+{
+ typedef js::DefaultHasher<ObjectId> TableKeyHasher;
+
+ typedef js::HashMap<ObjectId, JSObject *, TableKeyHasher, js::SystemAllocPolicy> ObjectTable;
+
+ public:
+ ObjectStore();
+
+ bool init();
+ void trace(JSTracer *trc);
+
+ bool add(ObjectId id, JSObject *obj);
+ JSObject *find(ObjectId id);
+ void remove(ObjectId id);
+
+ private:
+ ObjectTable table_;
+};
+
+// Map JSObjects -> ids
+class ObjectIdCache
+{
+ typedef js::PointerHasher<JSObject *, 3> Hasher;
+ typedef js::HashMap<JSObject *, ObjectId, Hasher, js::SystemAllocPolicy> ObjectIdTable;
+
+ public:
+ ObjectIdCache();
+
+ bool init();
+ void trace(JSTracer *trc);
+
+ bool add(JSObject *, ObjectId id);
+ ObjectId find(JSObject *obj);
+ void remove(JSObject *obj);
+
+ private:
+ ObjectIdTable table_;
+};
+
+class JavaScriptShared
+{
+ public:
+ bool init();
+
+ static const uint32_t OBJECT_EXTRA_BITS = 1;
+ static const uint32_t OBJECT_IS_CALLABLE = (1 << 0);
+
+ protected:
+ bool toVariant(JSContext *cx, jsval from, JSVariant *to);
+ bool toValue(JSContext *cx, const JSVariant &from, JS::MutableHandleValue to);
+ bool fromDescriptor(JSContext *cx, const JSPropertyDescriptor &desc, PPropertyDescriptor *out);
+ bool toDescriptor(JSContext *cx, const PPropertyDescriptor &in, JSPropertyDescriptor *out);
+ bool convertIdToGeckoString(JSContext *cx, JS::HandleId id, nsString *to);
+ bool convertGeckoStringToId(JSContext *cx, const nsString &from, JS::MutableHandleId id);
+
+ bool toValue(JSContext *cx, const JSVariant &from, jsval *to) {
+ JS::RootedValue v(cx);
+ if (!toValue(cx, from, &v))
+ return false;
+ *to = v;
+ return true;
+ }
+
+ virtual bool makeId(JSContext *cx, JSObject *obj, ObjectId *idp) = 0;
+ virtual JSObject *unwrap(JSContext *cx, ObjectId id) = 0;
+
+ bool unwrap(JSContext *cx, ObjectId id, JSObject **objp) {
+ if (!id) {
+ *objp = NULL;
+ return true;
+ }
+
+ *objp = unwrap(cx, id);
+ return !!*objp;
+ }
+
+ static void ConvertID(const nsID &from, JSIID *to);
+ static void ConvertID(const JSIID &from, nsID *to);
+
+ JSObject *findObject(uint32_t objId) {
+ return objects_.find(objId);
+ }
+
+ protected:
+ ObjectStore objects_;
+};
+
+// Use 47 at most, to be safe, since jsval privates are encoded as doubles.
+static const uint64_t MAX_CPOW_IDS = (uint64_t(1) << 47) - 1;
+
+} // namespace jsipc
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/js/ipc/JavaScriptTypes.ipdlh
@@ -0,0 +1,78 @@
+/* -*- 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 DOMTypes;
+
+using mozilla::void_t;
+
+namespace mozilla {
+namespace jsipc {
+
+struct JSIID
+{
+ uint32_t m0;
+ uint16_t m1;
+ uint16_t m2;
+ uint8_t m3_0;
+ uint8_t m3_1;
+ uint8_t m3_2;
+ uint8_t m3_3;
+ uint8_t m3_4;
+ uint8_t m3_5;
+ uint8_t m3_6;
+ uint8_t m3_7;
+};
+
+union JSVariant
+{
+ void_t; /* |undefined| */
+ nsString; /* StringValue(x) */
+ uint64_t; /* ID that maps to a JSObject (cpow on parent, original on child). */
+ double; /* NumberValue(x) */
+ bool; /* BooleanValue(x) */
+ JSIID; /* XPC nsIID */
+};
+
+struct ReturnStatus
+{
+ bool ok; /* True for success, false for failure. */
+ JSVariant exn; /* Exception, if |ok| is false. */
+};
+
+union JSParam
+{
+ void_t; /* value is strictly an xpc out param */
+ JSVariant; /* actual value to pass through */
+};
+
+struct PPropertyDescriptor
+{
+ uint64_t objId;
+ uint32_t attrs;
+ uint32_t shortid;
+ JSVariant value;
+
+ // How to interpret these values depends on whether JSPROP_GETTER/SETTER
+ // are set. If set, the corresponding value is a CPOW or 0 for NULL.
+ // Otherwise, the following table is used:
+ //
+ // 0 - NULL
+ // 1 - Default getter or setter.
+ // 2 - js_GetterOnlyPropertyStub (setter only)
+ // 3 - Unknown
+ uint64_t getter;
+ uint64_t setter;
+};
+
+struct CpowEntry
+{
+ nsString name;
+ JSVariant value;
+};
+
+}
+}
--- a/js/ipc/Makefile.in
+++ b/js/ipc/Makefile.in
@@ -10,18 +10,24 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = jsipc_s
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
FAIL_ON_WARNINGS = 1
-# For nsDependentJSString
+EXPORTS_mozilla/jsipc = \
+ JavaScriptParent.h \
+ $(NULL)
+
LOCAL_INCLUDES += \
-I$(topsrcdir)/dom/base \
+ -I$(topsrcdir)/js/ipc \
+ -I$(topsrcdir)/js/public \
+ -I$(topsrcdir)/js/xpconnect/src \
$(NULL)
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
deleted file mode 100644
--- a/js/ipc/ObjectWrapperChild.cpp
+++ /dev/null
@@ -1,621 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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 "mozilla/GuardObjects.h"
-
-#include "base/basictypes.h"
-
-#include "mozilla/jsipc/ContextWrapperChild.h"
-#include "mozilla/jsipc/ObjectWrapperChild.h"
-#include "mozilla/jsipc/CPOWTypes.h"
-
-#include "jsapi.h"
-#include "nsAutoPtr.h"
-#include "nsTArray.h"
-#include "nsContentUtils.h"
-#include "nsCxPusher.h"
-#include "nsJSUtils.h"
-
-using namespace mozilla::jsipc;
-using namespace js;
-
-namespace {
-
- class MOZ_STACK_CLASS AutoContextPusher {
-
- nsCxPusher mStack;
- JSContext* const mContext;
- const uint32_t mSavedOptions;
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-
- public:
-
- AutoContextPusher(JSContext* cx
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : mContext(cx)
- , mSavedOptions(JS_SetOptions(cx, (JS_GetOptions(cx) |
- JSOPTION_DONT_REPORT_UNCAUGHT)))
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- mStack.Push(cx);
- }
-
- ~AutoContextPusher() {
- mStack.Pop();
- JS_SetOptions(mContext, mSavedOptions);
- }
-
- };
-
- class StatusPtrOwner
- {
- OperationStatus* mStatusPtr;
- public:
- StatusPtrOwner() : mStatusPtr(NULL) {}
- void SetStatusPtr(OperationStatus* statusPtr) {
- mStatusPtr = statusPtr;
- // By default, initialize mStatusPtr to failure without an
- // exception. Doing so only when the union is uninitialized
- // allows AutoCheckOperation classes to be nested on the
- // stack, just in case AnswerConstruct, for example, calls
- // AnswerCall (as it once did, before there were unrelated
- // problems with that approach).
- if (mStatusPtr->type() == OperationStatus::T__None)
- *mStatusPtr = JS_FALSE;
- }
- OperationStatus* StatusPtr() {
- NS_ASSERTION(mStatusPtr, "Should have called SetStatusPtr by now.");
- return mStatusPtr;
- }
- };
-
- typedef AutoCheckOperationBase<StatusPtrOwner> ACOBase;
-
- class AutoCheckOperation : public ACOBase
- {
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
- public:
- AutoCheckOperation(ObjectWrapperChild* owc,
- OperationStatus* statusPtr
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : ACOBase(NULL, owc)
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- SetStatusPtr(statusPtr);
- }
- };
-}
-
-void
-ObjectWrapperChild::CheckOperation(JSContext*,
- OperationStatus* status)
-{
- NS_PRECONDITION(status->type() != OperationStatus::T__None,
- "Checking an uninitialized operation.");
-
- JSContext* cx = Manager()->GetContext();
- jsval thrown;
-
- if (JS_GetPendingException(cx, &thrown)) {
- NS_ASSERTION(!(status->type() == OperationStatus::TJSBool &&
- status->get_JSBool()),
- "Operation succeeded but exception was thrown?");
- JSVariant exception;
- if (!jsval_to_JSVariant(cx, thrown, &exception))
- exception = void_t(); // XXX Useful?
- *status = exception;
- JS_ClearPendingException(cx);
- }
-}
-
-ObjectWrapperChild::ObjectWrapperChild(JSContext* cx, JSObject* obj)
- : mObj(obj)
-{
- AutoContextPusher acp(cx);
-#ifdef DEBUG
- bool added =
-#endif
- JS_AddObjectRoot(cx, &mObj);
- NS_ASSERTION(added, "ObjectWrapperChild constructor failed to root JSObject*");
-}
-
-void
-ObjectWrapperChild::ActorDestroy(ActorDestroyReason why)
-{
- JSContext* cx = Manager()->GetContext();
- AutoContextPusher acp(cx);
- JS_RemoveObjectRoot(cx, &mObj);
-}
-
-bool
-ObjectWrapperChild::JSObject_to_JSVariant(JSContext* cx, JSObject* from,
- JSVariant* to)
-{
- *to = Manager()->GetOrCreateWrapper(from);
- return true;
-}
-
-bool
-ObjectWrapperChild::jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to)
-{
- switch (JS_TypeOfValue(cx, from)) {
- case JSTYPE_VOID:
- *to = void_t();
- return true;
- case JSTYPE_NULL:
- if (from != JSVAL_NULL)
- return false;
- // fall through
- case JSTYPE_FUNCTION:
- // fall through
- case JSTYPE_OBJECT:
- return JSObject_to_JSVariant(cx, JSVAL_TO_OBJECT(from), to);
- case JSTYPE_STRING:
- {
- nsDependentJSString depStr;
- if (!depStr.init(cx, from))
- return false;
- *to = depStr;
- }
- return true;
- case JSTYPE_NUMBER:
- if (JSVAL_IS_INT(from))
- *to = JSVAL_TO_INT(from);
- else if (JSVAL_IS_DOUBLE(from))
- *to = JSVAL_TO_DOUBLE(from);
- else return false;
- return true;
- case JSTYPE_BOOLEAN:
- *to = !!JSVAL_TO_BOOLEAN(from);
- return true;
- default:
- return false;
- }
-}
-
-/*static*/ bool
-ObjectWrapperChild::
-JSObject_from_PObjectWrapperChild(JSContext*,
- const PObjectWrapperChild* from,
- JSObject** to)
-{
- const ObjectWrapperChild* owc =
- static_cast<const ObjectWrapperChild*>(from);
- *to = owc ? owc->mObj : NULL;
- return true;
-}
-
-/*static*/ bool
-ObjectWrapperChild::JSObject_from_JSVariant(JSContext* cx,
- const JSVariant& from,
- JSObject** to)
-{
- if (from.type() != JSVariant::TPObjectWrapperChild)
- return false;
- return JSObject_from_PObjectWrapperChild(cx,
- from.get_PObjectWrapperChild(),
- to);
-}
-
-/*static*/ bool
-ObjectWrapperChild::jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
- jsval* to)
-{
- switch (from.type()) {
- case JSVariant::Tvoid_t:
- *to = JSVAL_VOID;
- return true;
- case JSVariant::TPObjectWrapperChild:
- {
- JSObject* obj;
- if (!JSObject_from_JSVariant(cx, from, &obj))
- return false;
- *to = OBJECT_TO_JSVAL(obj);
- return true;
- }
- case JSVariant::TnsString:
- {
- const nsString& str = from.get_nsString();
- JSString* s = JS_NewUCStringCopyN(cx,
- str.BeginReading(),
- str.Length());
- if (!s)
- return false;
- *to = STRING_TO_JSVAL(s);
- }
- return true;
- case JSVariant::Tint:
- *to = INT_TO_JSVAL(from.get_int());
- return true;
- case JSVariant::Tdouble:
- *to = JS_NumberValue(from.get_double());
- return true;
- case JSVariant::Tbool:
- *to = BOOLEAN_TO_JSVAL(from.get_bool());
- return true;
- default:
- return false;
- }
-}
-
-ContextWrapperChild*
-ObjectWrapperChild::Manager()
-{
- PContextWrapperChild* pcwc = PObjectWrapperChild::Manager();
- return static_cast<ContextWrapperChild*>(pcwc);
-}
-
-static bool
-jsid_to_nsString(JSContext* cx, jsid from, nsString* to)
-{
- if (JSID_IS_STRING(from)) {
- size_t length;
- const jschar* chars = JS_GetInternedStringCharsAndLength(JSID_TO_STRING(from), &length);
- *to = nsDependentString(chars, length);
- return true;
- }
- return false;
-}
-
-static bool
-jsid_from_nsString(JSContext* cx, const nsString& from, jsid* to)
-{
- JSString* str = JS_NewUCStringCopyN(cx, from.BeginReading(), from.Length());
- if (!str)
- return false;
- return JS_ValueToId(cx, STRING_TO_JSVAL(str), to);
-}
-
-#if 0
-// The general schema for ObjectWrapperChild::Answer* methods:
-bool
-ObjectWrapperChild::AnswerSomething(/* in-parameters */
- /* out-parameters */)
-{
- // initialize out-parameters for failure
- JSContext* cx = Manager()->GetContext();
- AutoContextPusher acp(cx);
- // validate in-parameters, else return false
- // successfully perform local JS operations, else return true
- // perform out-parameter conversions, else return false
- return true;
-}
-// There's an important subtlety here: though a local JS operation may
-// fail, leaving out-parameters uninitialized, we must initialize all
-// out-parameters when reporting success (returning true) to the IPC
-// messaging system. See AnswerGetProperty for illustration.
-#endif
-
-bool
-ObjectWrapperChild::AnswerAddProperty(const nsString& id,
- OperationStatus* status)
-{
- JSContext* cx = Manager()->GetContext();
- JS::RootedId interned_id(cx);
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
-
- if (!jsid_from_nsString(cx, id, interned_id.address()))
- return false;
-
- *status = JS_DefinePropertyById(cx, mObj, interned_id, JSVAL_VOID,
- NULL, NULL, 0);
- return true;
-}
-
-bool
-ObjectWrapperChild::AnswerGetProperty(const nsString& id,
- OperationStatus* status, JSVariant* vp)
-{
- JSContext* cx = Manager()->GetContext();
- JS::RootedId interned_id(cx);
- JS::RootedValue val(cx);
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
-
- if (!jsid_from_nsString(cx, id, interned_id.address()))
- return false;
-
- *status = JS_GetPropertyById(cx, mObj, interned_id, val.address());
-
- // Since we fully expect this call to jsval_to_JSVariant to return
- // true, we can't just leave vp uninitialized when JS_GetPropertyById
- // returns JS_FALSE. This pitfall could be avoided in general if IPDL
- // ensured that outparams were pre-initialized to some default value
- // (XXXfixme cjones?).
- return jsval_to_JSVariant(cx, aco.Ok() ? val : JSVAL_VOID, vp);
-}
-
-bool
-ObjectWrapperChild::AnswerSetProperty(const nsString& id, const JSVariant& v,
- OperationStatus* status, JSVariant* vp)
-{
- *vp = v;
-
- JSContext* cx = Manager()->GetContext();
- JS::RootedId interned_id(cx);
- JS::RootedValue val(cx);
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
-
- if (!jsid_from_nsString(cx, id, interned_id.address()) ||
- !jsval_from_JSVariant(cx, v, val.address())) {
- return false;
- }
-
- *status = JS_SetPropertyById(cx, mObj, interned_id, val.address());
-
- return jsval_to_JSVariant(cx, aco.Ok() ? val : JSVAL_VOID, vp);
-}
-
-bool
-ObjectWrapperChild::AnswerDelProperty(const nsString& id,
- OperationStatus* status, JSVariant* vp)
-{
- JSContext* cx = Manager()->GetContext();
- JS::RootedId interned_id(cx);
- JS::RootedValue val(cx);
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
-
- if (!jsid_from_nsString(cx, id, interned_id.address()))
- return false;
-
- *status = JS_DeletePropertyById2(cx, mObj, interned_id, val.address());
-
- return jsval_to_JSVariant(cx, aco.Ok() ? val : JSVAL_VOID, vp);
-}
-
-static const uint32_t sNextIdIndexSlot = 0;
-static const uint32_t sNumNewEnumerateStateSlots = 1;
-
-static void
-CPOW_NewEnumerateState_FreeIds(JSObject* state)
-{
- nsTArray<nsString>* strIds =
- static_cast<nsTArray<nsString>*>(JS_GetPrivate(state));
-
- if (strIds) {
- delete strIds;
- JS_SetPrivate(state, NULL);
- }
-}
-
-static void
-CPOW_NewEnumerateState_Finalize(JSFreeOp* fop, JSObject* state)
-{
- CPOW_NewEnumerateState_FreeIds(state);
-}
-
-// Similar to IteratorClass in XPCWrapper.cpp
-static const JSClass sCPOW_NewEnumerateState_JSClass = {
- "CPOW NewEnumerate State",
- JSCLASS_HAS_PRIVATE |
- JSCLASS_HAS_RESERVED_SLOTS(sNumNewEnumerateStateSlots),
- JS_PropertyStub, JS_DeletePropertyStub,
- JS_PropertyStub, JS_StrictPropertyStub,
- JS_EnumerateStub, JS_ResolveStub,
- JS_ConvertStub, CPOW_NewEnumerateState_Finalize
-};
-
-bool
-ObjectWrapperChild::AnswerNewEnumerateInit(/* no in-parameters */
- OperationStatus* status, JSVariant* statep, int* idp)
-{
- *idp = 0;
-
- JSContext* cx = Manager()->GetContext();
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
-
- JSClass* clasp = const_cast<JSClass*>(&sCPOW_NewEnumerateState_JSClass);
- JS::Rooted<JSObject*> state(cx, JS_NewObjectWithGivenProto(cx, clasp, NULL, NULL));
- if (!state)
- return false;
-
- for (JS::RootedObject proto(cx, mObj); proto; ) {
- AutoIdArray ids(cx, JS_Enumerate(cx, proto));
- for (size_t i = 0; i < ids.length(); ++i)
- JS_DefinePropertyById(cx, state, ids[i], JSVAL_VOID,
- NULL, NULL, JSPROP_ENUMERATE | JSPROP_SHARED);
-
- if (!JS_GetPrototype(cx, proto, proto.address()))
- return false;
- }
-
- InfallibleTArray<nsString>* strIds;
- {
- AutoIdArray ids(cx, JS_Enumerate(cx, state));
- if (!ids)
- return false;
- strIds = new InfallibleTArray<nsString>(ids.length());
- for (size_t i = 0; i < ids.length(); ++i)
- if (!jsid_to_nsString(cx, ids[i], strIds->AppendElement())) {
- delete strIds;
- return false;
- }
- }
- *idp = strIds->Length();
-
- JS_SetPrivate(state, strIds);
- JS_SetReservedSlot(state, sNextIdIndexSlot, JSVAL_ZERO);
-
- *status = JSObject_to_JSVariant(cx, state, statep);
-
- return true;
-}
-
-bool
-ObjectWrapperChild::AnswerNewEnumerateNext(const JSVariant& in_state,
- OperationStatus* status, JSVariant* statep, nsString* idp)
-{
- JSObject* state;
-
- *statep = in_state;
- idp->Truncate();
-
- JSContext* cx = Manager()->GetContext();
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
-
- if (!JSObject_from_JSVariant(cx, in_state, &state))
- return false;
-
- InfallibleTArray<nsString>* strIds =
- static_cast<InfallibleTArray<nsString>*>(JS_GetPrivate(state));
-
- if (!strIds)
- return false;
-
- jsval v = JS_GetReservedSlot(state, sNextIdIndexSlot);
-
- int32_t i = JSVAL_TO_INT(v);
- NS_ASSERTION(i >= 0, "Index of next jsid negative?");
- NS_ASSERTION(size_t(i) <= strIds->Length(), "Index of next jsid too large?");
-
- if (size_t(i) == strIds->Length()) {
- *status = JS_TRUE;
- return JSObject_to_JSVariant(cx, NULL, statep);
- }
-
- *idp = strIds->ElementAt(i);
- JS_SetReservedSlot(state, sNextIdIndexSlot, INT_TO_JSVAL(i + 1));
- *status = JS_TRUE;
- return true;
-}
-
-bool
-ObjectWrapperChild::RecvNewEnumerateDestroy(const JSVariant& in_state)
-{
- JSObject* state;
-
- JSContext* cx = Manager()->GetContext();
- AutoContextPusher acp(cx);
-
- if (!JSObject_from_JSVariant(cx, in_state, &state))
- return false;
-
- CPOW_NewEnumerateState_FreeIds(state);
-
- return true;
-}
-
-bool
-ObjectWrapperChild::AnswerNewResolve(const nsString& id, const int& flags,
- OperationStatus* status, PObjectWrapperChild** obj2)
-{
- *obj2 = NULL;
-
- JSContext* cx = Manager()->GetContext();
- JS::RootedId interned_id(cx);
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
-
- if (!jsid_from_nsString(cx, id, interned_id.address()))
- return false;
-
- CPOW_LOG(("new-resolving \"%s\"...",
- NS_ConvertUTF16toUTF8(id).get()));
-
- JS::Rooted<JSPropertyDescriptor> desc(cx);
- if (!JS_GetPropertyDescriptorById(cx, mObj, interned_id, flags, desc.address()))
- return true;
-
- *status = JS_TRUE;
-
- if (desc.get().obj)
- *obj2 = Manager()->GetOrCreateWrapper(desc.get().obj);
-
- return true;
-}
-
-bool
-ObjectWrapperChild::AnswerConvert(const JSType& type,
- OperationStatus* status, JSVariant* vp)
-{
- JSContext* cx = Manager()->GetContext();
- JS::RootedValue v(cx);
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
- *status = JS_ConvertValue(cx, OBJECT_TO_JSVAL(mObj), type, v.address());
- return jsval_to_JSVariant(cx, aco.Ok() ? v : JSVAL_VOID, vp);
-}
-
-namespace {
- // Should be an overestimate of typical JS function arity.
- typedef nsAutoTArray<jsval, 5> AutoJSArgs;
-}
-
-bool
-ObjectWrapperChild::AnswerCall(PObjectWrapperChild* receiver, const InfallibleTArray<JSVariant>& argv,
- OperationStatus* status, JSVariant* rval)
-{
- JSContext* cx = Manager()->GetContext();
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
-
- JS::RootedObject obj(cx);
- if (!JSObject_from_PObjectWrapperChild(cx, receiver, obj.address()))
- return false;
-
- AutoJSArgs args;
- uint32_t argc = argv.Length();
- jsval *jsargs = args.AppendElements(argc);
- if (!jsargs)
- return false;
- AutoArrayRooter tvr(cx, argc, jsargs);
-
- for (uint32_t i = 0; i < argc; ++i)
- if (!jsval_from_JSVariant(cx, argv.ElementAt(i), jsargs + i))
- return false;
-
- JS::RootedValue rv(cx);
- *status = JS_CallFunctionValue(cx, obj, OBJECT_TO_JSVAL(mObj),
- argv.Length(), jsargs, rv.address());
-
- return jsval_to_JSVariant(cx, aco.Ok() ? rv : JSVAL_VOID, rval);
-}
-
-bool
-ObjectWrapperChild::AnswerConstruct(const InfallibleTArray<JSVariant>& argv,
- OperationStatus* status, PObjectWrapperChild** rval)
-{
- JSContext* cx = Manager()->GetContext();
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
-
- AutoJSArgs args;
- uint32_t argc = argv.Length();
- jsval* jsargs = args.AppendElements(argc);
- if (!jsargs)
- return false;
- AutoArrayRooter tvr(cx, argc, jsargs);
-
- for (uint32_t i = 0; i < argc; ++i)
- if (!jsval_from_JSVariant(cx, argv.ElementAt(i), jsargs + i))
- return false;
-
- JSObject* obj = JS_New(cx, mObj, argc, jsargs);
-
- *status = !!obj;
- *rval = Manager()->GetOrCreateWrapper(obj);
-
- return true;
-}
-
-bool
-ObjectWrapperChild::AnswerHasInstance(const JSVariant& v,
- OperationStatus* status, JSBool* bp)
-{
- JSContext* cx = Manager()->GetContext();
- JS::RootedValue candidate(cx);
- AutoContextPusher acp(cx);
- AutoCheckOperation aco(this, status);
- if (!jsval_from_JSVariant(cx, v, candidate.address()))
- return false;
- *status = JS_HasInstance(cx, mObj, candidate, bp);
- return true;
-}
deleted file mode 100644
--- a/js/ipc/ObjectWrapperChild.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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/. */
-
-#ifndef mozilla_jsipc_ObjectWrapperChild_h
-#define mozilla_jsipc_ObjectWrapperChild_h
-
-#include "mozilla/jsipc/PObjectWrapperChild.h"
-
-// For OperationChecker and AutoCheckOperationBase.
-#include "mozilla/jsipc/ObjectWrapperParent.h"
-
-using mozilla::jsipc::JSVariant;
-
-namespace mozilla {
-namespace jsipc {
-
-class ContextWrapperChild;
-
-class ObjectWrapperChild
- : public PObjectWrapperChild
- , public OperationChecker
-{
-public:
-
- ObjectWrapperChild(JSContext* cx, JSObject* obj);
-
- JSObject* GetJSObject() const { return mObj; }
-
- void CheckOperation(JSContext* cx, OperationStatus* status);
-
-private:
-
- JSObject* mObj;
-
- bool JSObject_to_JSVariant(JSContext* cx, JSObject* from, JSVariant* to);
- bool jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to);
-
- static bool JSObject_from_PObjectWrapperChild(JSContext* cx,
- const PObjectWrapperChild* from,
- JSObject** to);
- static bool JSObject_from_JSVariant(JSContext* cx, const JSVariant& from,
- JSObject** to);
- static bool jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
- jsval* to);
-
- ContextWrapperChild* Manager();
-
-protected:
-
- void ActorDestroy(ActorDestroyReason why);
-
- bool AnswerAddProperty(const nsString& id,
- OperationStatus* status);
-
- bool AnswerGetProperty(const nsString& id,
- OperationStatus* status, JSVariant* vp);
-
- bool AnswerSetProperty(const nsString& id, const JSVariant& v,
- OperationStatus* status, JSVariant* vp);
-
- bool AnswerDelProperty(const nsString& id,
- OperationStatus* status, JSVariant* vp);
-
- bool AnswerNewEnumerateInit(/* no in-parameters */
- OperationStatus* status, JSVariant* statep, int* idp);
-
- bool AnswerNewEnumerateNext(const JSVariant& in_state,
- OperationStatus* status, JSVariant* statep, nsString* idp);
-
- bool RecvNewEnumerateDestroy(const JSVariant& in_state);
-
- bool AnswerNewResolve(const nsString& id, const int& flags,
- OperationStatus* status, PObjectWrapperChild** obj2);
-
- bool AnswerConvert(const JSType& type,
- OperationStatus* status, JSVariant* vp);
-
- bool AnswerCall(PObjectWrapperChild* receiver, const InfallibleTArray<JSVariant>& argv,
- OperationStatus* status, JSVariant* rval);
-
- bool AnswerConstruct(const InfallibleTArray<JSVariant>& argv,
- OperationStatus* status, PObjectWrapperChild** rval);
-
- bool AnswerHasInstance(const JSVariant& v,
- OperationStatus* status, JSBool* bp);
-};
-
-}}
-
-#endif /* mozilla_jsipc_ObjectWrapperChild_h */
deleted file mode 100644
--- a/js/ipc/ObjectWrapperParent.cpp
+++ /dev/null
@@ -1,733 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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 "mozilla/GuardObjects.h"
-
-#include "mozilla/jsipc/ObjectWrapperParent.h"
-#include "mozilla/jsipc/ContextWrapperParent.h"
-#include "mozilla/jsipc/CPOWTypes.h"
-#include "mozilla/unused.h"
-#include "nsJSUtils.h"
-
-#include "jsutil.h"
-#include "jsfriendapi.h"
-
-using namespace mozilla::jsipc;
-using namespace JS;
-
-namespace {
-
- // Only need one reserved slot because the ObjectWrapperParent* is
- // stored in the private slot.
- static const unsigned sFlagsSlot = 0;
- static const unsigned sNumSlots = 1;
- static const unsigned CPOW_FLAG_RESOLVING = 1 << 0;
-
- class AutoResolveFlag
- {
- Rooted<JSObject*> mObj;
- unsigned mOldFlags;
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-
- static unsigned GetFlags(JSObject* obj) {
- jsval v = JS_GetReservedSlot(obj, sFlagsSlot);
- return JSVAL_TO_INT(v);
- }
-
- static unsigned SetFlags(JSObject* obj, unsigned flags) {
- unsigned oldFlags = GetFlags(obj);
- if (oldFlags != flags)
- JS_SetReservedSlot(obj, sFlagsSlot, INT_TO_JSVAL(flags));
- return oldFlags;
- }
-
- public:
-
- AutoResolveFlag(JSContext *cx, JSObject* obj
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : mObj(cx, obj)
- , mOldFlags(SetFlags(obj, GetFlags(obj) | CPOW_FLAG_RESOLVING))
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- }
-
- ~AutoResolveFlag() {
- SetFlags(mObj, mOldFlags);
- }
-
- static JSBool IsSet(JSObject* obj) {
- return GetFlags(obj) & CPOW_FLAG_RESOLVING;
- }
-
- };
-
- class StatusMemberOwner
- {
- OperationStatus mStatus;
- public:
- StatusMemberOwner() : mStatus(JS_FALSE) {}
- OperationStatus* StatusPtr() {
- return &mStatus;
- }
- };
-
- typedef AutoCheckOperationBase<StatusMemberOwner> ACOBase;
-
- class AutoCheckOperation : public ACOBase
- {
- MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
- public:
- AutoCheckOperation(JSContext* cx,
- ObjectWrapperParent* owp
- MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
- : ACOBase(cx, owp)
- {
- MOZ_GUARD_OBJECT_NOTIFIER_INIT;
- }
- };
-
-}
-
-void
-ObjectWrapperParent::CheckOperation(JSContext* cx,
- OperationStatus* status)
-{
- NS_PRECONDITION(status->type() != OperationStatus::T__None,
- "Checking an uninitialized operation.");
-
- switch (status->type()) {
- case OperationStatus::TJSVariant:
- {
- Rooted<Value> thrown(cx);
- if (jsval_from_JSVariant(cx, status->get_JSVariant(), thrown.address()))
- JS_SetPendingException(cx, thrown);
- *status = JS_FALSE;
- }
- break;
- case OperationStatus::TJSBool:
- if (!status->get_JSBool() && !JS_IsExceptionPending(cx)) {
- NS_WARNING("CPOW operation failed without setting an exception.");
- }
- break;
- default:
- NS_NOTREACHED("Invalid or uninitialized OperationStatus type.");
- break;
- }
-}
-
-template <typename RType>
-static RType
-with_error(JSContext* cx,
- RType rval,
- const char* error = NULL)
-{
- if (!JS_IsExceptionPending(cx))
- JS_ReportError(cx, error ? error : "Unspecified CPOW error");
- return rval;
-}
-
-const js::Class ObjectWrapperParent::sCPOW_JSClass = {
- "CrossProcessObjectWrapper",
- JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE |
- JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(sNumSlots),
- ObjectWrapperParent::CPOW_AddProperty,
- ObjectWrapperParent::CPOW_DelProperty,
- ObjectWrapperParent::CPOW_GetProperty,
- ObjectWrapperParent::CPOW_SetProperty,
- (JSEnumerateOp) ObjectWrapperParent::CPOW_NewEnumerate,
- (JSResolveOp) ObjectWrapperParent::CPOW_NewResolve,
- ObjectWrapperParent::CPOW_Convert,
- ObjectWrapperParent::CPOW_Finalize,
- nullptr, // checkAccess
- ObjectWrapperParent::CPOW_Call,
- ObjectWrapperParent::CPOW_HasInstance,
- ObjectWrapperParent::CPOW_Construct,
- nullptr // trace
-};
-
-void
-ObjectWrapperParent::ActorDestroy(ActorDestroyReason)
-{
- if (mObj) {
- JS_SetPrivate(mObj, NULL);
- mObj = NULL;
- }
-}
-
-ContextWrapperParent*
-ObjectWrapperParent::Manager()
-{
- PContextWrapperParent* pcwp = PObjectWrapperParent::Manager();
- return static_cast<ContextWrapperParent*>(pcwp);
-}
-
-JSObject*
-ObjectWrapperParent::GetJSObject(JSContext* cx) const
-{
- if (!mObj) {
- js::Class *clasp = const_cast<js::Class *>(&ObjectWrapperParent::sCPOW_JSClass);
- mObj = JS_NewObject(cx, js::Jsvalify(clasp), NULL, NULL);
- if (mObj) {
- JS_SetPrivate(mObj, (void*)this);
- JS_SetReservedSlot(mObj, sFlagsSlot, JSVAL_ZERO);
- }
- }
- return mObj;
-}
-
-static ObjectWrapperParent*
-Unwrap(JSContext* cx, JSObject* objArg)
-{
- Rooted<JSObject*> obj(cx, objArg), proto(cx);
- while (js::GetObjectClass(obj) != &ObjectWrapperParent::sCPOW_JSClass) {
- if (!js::GetObjectProto(cx, obj, &proto) || !proto)
- return NULL;
- obj = proto;
- }
-
- ObjectWrapperParent* self =
- static_cast<ObjectWrapperParent*>(JS_GetPrivate(obj));
-
- NS_ASSERTION(!self || self->GetJSObjectOrNull() == obj,
- "Wrapper and wrapped object disagree?");
-
- return self;
-}
-
-/*static*/ bool
-ObjectWrapperParent::jsval_to_JSVariant(JSContext* cx, jsval from,
- JSVariant* to)
-{
- switch (JS_TypeOfValue(cx, from)) {
- case JSTYPE_VOID:
- *to = void_t();
- return true;
- case JSTYPE_NULL:
- if (from != JSVAL_NULL)
- return false;
- // fall through
- case JSTYPE_FUNCTION:
- // CPOWs can fool JS_TypeOfValue into returning JSTYPE_FUNCTION
- // because they have a call hook, but CPOWs are really objects, so
- // fall through to the JSTYPE_OBJECT case:
- case JSTYPE_OBJECT:
- {
- PObjectWrapperParent* powp;
- if (!JSObject_to_PObjectWrapperParent(cx, JSVAL_TO_OBJECT(from), &powp))
- return with_error(cx, false, "Cannot pass parent-created object to child");
- *to = powp;
- }
- return true;
- case JSTYPE_STRING:
- {
- nsDependentJSString depStr;
- if (!depStr.init(cx, from))
- return false;
- *to = depStr;
- }
- return true;
- case JSTYPE_NUMBER:
- if (JSVAL_IS_INT(from))
- *to = JSVAL_TO_INT(from);
- else if (JSVAL_IS_DOUBLE(from))
- *to = JSVAL_TO_DOUBLE(from);
- else return false;
- return true;
- case JSTYPE_BOOLEAN:
- *to = !!JSVAL_TO_BOOLEAN(from);
- return true;
- default:
- return with_error(cx, false, "Bad jsval type");
- }
-}
-
-/*static*/ bool
-ObjectWrapperParent::jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
- jsval* to)
-{
- switch (from.type()) {
- case JSVariant::Tvoid_t:
- *to = JSVAL_VOID;
- return true;
- case JSVariant::TPObjectWrapperParent:
- return jsval_from_PObjectWrapperParent(cx, from.get_PObjectWrapperParent(), to);
- case JSVariant::TnsString:
- {
- JSString* str = JS_NewUCStringCopyZ(cx, from.get_nsString().BeginReading());
- if (!str)
- return false;
- *to = STRING_TO_JSVAL(str);
- return true;
- }
- case JSVariant::Tint:
- *to = INT_TO_JSVAL(from.get_int());
- return true;
- case JSVariant::Tdouble:
- *to = JS_NumberValue(from.get_double());
- return true;
- case JSVariant::Tbool:
- *to = BOOLEAN_TO_JSVAL(from.get_bool());
- return true;
- default:
- return false;
- }
-}
-
-/*static*/ bool
-ObjectWrapperParent::boolean_from_JSVariant(JSContext* cx, const JSVariant& from,
- JSBool* to)
-{
- switch (from.type()) {
- case JSVariant::Tvoid_t:
- *to = false;
- return true;
- case JSVariant::TPObjectWrapperParent: {
- Rooted<Value> v(cx);
- if (!jsval_from_PObjectWrapperParent(cx, from.get_PObjectWrapperParent(), v.address()))
- return false;
- *to = JS::ToBoolean(v);
- return true;
- }
- case JSVariant::TnsString:
- {
- JSString* str = JS_NewUCStringCopyZ(cx, from.get_nsString().BeginReading());
- if (!str)
- return false;
- *to = JS::ToBoolean(JS::StringValue(str));
- return true;
- }
- case JSVariant::Tint:
- *to = from.get_int() != 0;
- return true;
- case JSVariant::Tdouble:
- *to = JS::ToBoolean(JS::DoubleValue(from.get_double()));
- return true;
- case JSVariant::Tbool:
- *to = from.get_bool();
- return true;
- default:
- return false;
- }
-}
-
-/*static*/ bool
-ObjectWrapperParent::
-JSObject_to_PObjectWrapperParent(JSContext* cx, JSObject* from, PObjectWrapperParent** to)
-{
- if (!from) {
- *to = NULL;
- return true;
- }
- ObjectWrapperParent* owp = Unwrap(cx, from);
- if (!owp)
- return false;
- *to = owp;
- return true;
-}
-
-/*static*/ bool
-ObjectWrapperParent::
-JSObject_from_PObjectWrapperParent(JSContext* cx,
- const PObjectWrapperParent* from,
- MutableHandleObject to)
-{
- const ObjectWrapperParent* owp =
- static_cast<const ObjectWrapperParent*>(from);
- to.set(owp
- ? owp->GetJSObject(cx)
- : JSVAL_TO_OBJECT(JSVAL_NULL));
- return true;
-}
-
-/*static*/ bool
-ObjectWrapperParent::
-jsval_from_PObjectWrapperParent(JSContext* cx,
- const PObjectWrapperParent* from,
- jsval* to)
-{
- Rooted<JSObject*> obj(cx);
- if (!JSObject_from_PObjectWrapperParent(cx, from, &obj))
- return false;
- *to = OBJECT_TO_JSVAL(obj);
- return true;
-}
-
-static bool
-jsid_from_int(JSContext* cx, int from, jsid* to)
-{
- jsval v = INT_TO_JSVAL(from);
- return JS_ValueToId(cx, v, to);
-}
-
-static bool
-jsid_from_nsString(JSContext* cx, const nsString& from, jsid* to)
-{
- JSString* str = JS_NewUCStringCopyZ(cx, from.BeginReading());
- if (!str)
- return false;
- return JS_ValueToId(cx, STRING_TO_JSVAL(str), to);
-}
-
-static bool
-jsval_to_nsString(JSContext* cx, jsid from, nsString* to)
-{
- JSString* str;
- const jschar* chars;
- jsval idval;
- if (JS_IdToValue(cx, from, &idval) &&
- (str = JS_ValueToString(cx, idval)) &&
- (chars = JS_GetStringCharsZ(cx, str))) {
- *to = chars;
- return true;
- }
- return false;
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_AddProperty(JSContext *cx, HandleObject obj, HandleId id,
- MutableHandleValue vp)
-{
- CPOW_LOG(("Calling CPOW_AddProperty (%s)...",
- JSVAL_TO_CSTR(cx, id)));
-
- ObjectWrapperParent* self = Unwrap(cx, obj);
- if (!self)
- return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_AddProperty");
-
- if (AutoResolveFlag::IsSet(obj))
- return JS_TRUE;
-
- AutoCheckOperation aco(cx, self);
-
- nsString in_id;
-
- if (!jsval_to_nsString(cx, id, &in_id))
- return JS_FALSE;
-
- return (self->Manager()->RequestRunToCompletion() &&
- self->CallAddProperty(in_id,
- aco.StatusPtr()) &&
- aco.Ok());
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_GetProperty(JSContext *cx, HandleObject obj, HandleId id,
- MutableHandleValue vp)
-{
- CPOW_LOG(("Calling CPOW_GetProperty (%s)...",
- JSVAL_TO_CSTR(cx, id)));
-
- ObjectWrapperParent* self = Unwrap(cx, obj);
- if (!self)
- return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_GetProperty");
-
- AutoCheckOperation aco(cx, self);
-
- nsString in_id;
-
- if (!jsval_to_nsString(cx, id, &in_id))
- return JS_FALSE;
-
- JSVariant out_v;
-
- return (self->Manager()->RequestRunToCompletion() &&
- self->CallGetProperty(in_id,
- aco.StatusPtr(), &out_v) &&
- aco.Ok() &&
- self->jsval_from_JSVariant(cx, out_v, vp.address()));
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_SetProperty(JSContext *cx, HandleObject obj, HandleId id,
- JSBool strict, MutableHandleValue vp)
-{
- CPOW_LOG(("Calling CPOW_SetProperty (%s)...",
- JSVAL_TO_CSTR(cx, id)));
-
- ObjectWrapperParent* self = Unwrap(cx, obj);
- if (!self)
- return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_SetProperty");
-
- AutoCheckOperation aco(cx, self);
-
- nsString in_id;
- JSVariant in_v;
-
- if (!jsval_to_nsString(cx, id, &in_id) ||
- !self->jsval_to_JSVariant(cx, vp, &in_v))
- return JS_FALSE;
-
- JSVariant out_v;
-
- return (self->Manager()->RequestRunToCompletion() &&
- self->CallSetProperty(in_id, in_v,
- aco.StatusPtr(), &out_v) &&
- aco.Ok() &&
- self->jsval_from_JSVariant(cx, out_v, vp.address()));
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_DelProperty(JSContext *cx, HandleObject obj, HandleId id,
- JSBool *succeeded)
-{
- CPOW_LOG(("Calling CPOW_DelProperty (%s)...",
- JSVAL_TO_CSTR(cx, id)));
-
- ObjectWrapperParent* self = Unwrap(cx, obj);
- if (!self)
- return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_DelProperty");
-
- AutoCheckOperation aco(cx, self);
-
- nsString in_id;
-
- if (!jsval_to_nsString(cx, id, &in_id))
- return JS_FALSE;
-
- JSVariant out_v;
-
- return (self->Manager()->RequestRunToCompletion() &&
- self->CallDelProperty(in_id,
- aco.StatusPtr(), &out_v) &&
- aco.Ok() &&
- boolean_from_JSVariant(cx, out_v, succeeded));
-}
-
-JSBool
-ObjectWrapperParent::NewEnumerateInit(JSContext* cx, jsval* statep, jsid* idp)
-{
- AutoCheckOperation aco(cx, this);
-
- JSVariant out_state;
- int out_id;
-
- return (CallNewEnumerateInit(aco.StatusPtr(), &out_state, &out_id) &&
- aco.Ok() &&
- jsval_from_JSVariant(cx, out_state, statep) &&
- (!idp || jsid_from_int(cx, out_id, idp)));
-}
-
-JSBool
-ObjectWrapperParent::NewEnumerateNext(JSContext* cx, jsval* statep, jsid* idp)
-{
- AutoCheckOperation aco(cx, this);
-
- JSVariant in_state;
-
- if (!jsval_to_JSVariant(cx, *statep, &in_state))
- return JS_FALSE;
-
- JSVariant out_state;
- nsString out_id;
-
- if (CallNewEnumerateNext(in_state,
- aco.StatusPtr(), &out_state, &out_id) &&
- aco.Ok() &&
- jsval_from_JSVariant(cx, out_state, statep) &&
- jsid_from_nsString(cx, out_id, idp))
- {
- JSObject* obj = GetJSObject(cx);
- AutoResolveFlag arf(cx, obj);
- return JS_DefinePropertyById(cx, obj, *idp, JSVAL_VOID, NULL, NULL,
- JSPROP_ENUMERATE);
- }
- return JS_FALSE;
-}
-
-JSBool
-ObjectWrapperParent::NewEnumerateDestroy(JSContext* cx, jsval state)
-{
- AutoCheckOperation aco(cx, this);
-
- JSVariant in_state;
-
- if (!jsval_to_JSVariant(cx, state, &in_state))
- return JS_FALSE;
-
- return SendNewEnumerateDestroy(in_state);
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_NewEnumerate(JSContext *cx, HandleObject obj,
- JSIterateOp enum_op, jsval *statep,
- jsid *idp)
-{
- CPOW_LOG(("Calling CPOW_NewEnumerate..."));
-
- ObjectWrapperParent* self = Unwrap(cx, obj);
- if (!self)
- return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_NewEnumerate");
-
- switch (enum_op) {
- case JSENUMERATE_INIT:
- case JSENUMERATE_INIT_ALL:
- self->Manager()->RequestRunToCompletion();
- return self->NewEnumerateInit(cx, statep, idp);
- case JSENUMERATE_NEXT:
- return self->NewEnumerateNext(cx, statep, idp);
- case JSENUMERATE_DESTROY:
- return self->NewEnumerateDestroy(cx, *statep);
- }
-
- NS_NOTREACHED("Unknown enum_op value in CPOW_NewEnumerate");
- return JS_FALSE;
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_NewResolve(JSContext *cx, HandleObject obj, HandleId id,
- unsigned flags, MutableHandleObject objp)
-{
- CPOW_LOG(("Calling CPOW_NewResolve (%s)...",
- JSVAL_TO_CSTR(cx, id)));
-
- ObjectWrapperParent* self = Unwrap(cx, obj);
- if (!self)
- return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_NewResolve");
-
- AutoCheckOperation aco(cx, self);
-
- nsString in_id;
-
- if (!jsval_to_nsString(cx, id, &in_id))
- return JS_FALSE;
-
- PObjectWrapperParent* out_pobj;
-
- if (!self->Manager()->RequestRunToCompletion() ||
- !self->CallNewResolve(in_id, flags,
- aco.StatusPtr(), &out_pobj) ||
- !aco.Ok() ||
- !JSObject_from_PObjectWrapperParent(cx, out_pobj, objp))
- return JS_FALSE;
-
- if (objp) {
- AutoResolveFlag arf(cx, objp.get());
- Rooted<JSObject*> obj2(cx, objp);
- JS_DefinePropertyById(cx, obj2, id, JSVAL_VOID, NULL, NULL,
- JSPROP_ENUMERATE);
- }
- return JS_TRUE;
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_Convert(JSContext *cx, HandleObject obj, JSType type,
- MutableHandleValue vp)
-{
- CPOW_LOG(("Calling CPOW_Convert (to %s)...",
- JS_GetTypeName(cx, type)));
-
- ObjectWrapperParent* self = Unwrap(cx, obj);
- if (!self)
- return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_Convert");
-
- vp.set(OBJECT_TO_JSVAL(obj));
-
- return JS_TRUE;
-}
-
-/*static*/ void
-ObjectWrapperParent::CPOW_Finalize(js::FreeOp* fop, JSObject* obj)
-{
- CPOW_LOG(("Calling CPOW_Finalize..."));
-
- MOZ_ASSERT(js::GetObjectClass(obj) == &ObjectWrapperParent::sCPOW_JSClass);
- ObjectWrapperParent* self =
- static_cast<ObjectWrapperParent*>(JS_GetPrivate(obj));
- if (self) {
- self->mObj = NULL;
- unused << ObjectWrapperParent::Send__delete__(self);
- }
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_Call(JSContext* cx, unsigned argc, jsval* vp)
-{
- CPOW_LOG(("Calling CPOW_Call..."));
-
- Rooted<JSObject*> thisobj(cx, JS_THIS_OBJECT(cx, vp));
- if (!thisobj)
- return JS_FALSE;
-
- ObjectWrapperParent* function =
- Unwrap(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
- if (!function)
- return with_error(cx, JS_FALSE, "Could not unwrap CPOW function");
-
- AutoCheckOperation aco(cx, function);
-
- ObjectWrapperParent* receiver = Unwrap(cx, thisobj);
- if (!receiver) {
- // Substitute child global for parent global object.
- // TODO First make sure we're really replacing the global object?
- ContextWrapperParent* manager =
- static_cast<ContextWrapperParent*>(function->Manager());
- receiver = manager->GetGlobalObjectWrapper();
- }
-
- InfallibleTArray<JSVariant> in_argv(argc);
- jsval* argv = JS_ARGV(cx, vp);
- for (unsigned i = 0; i < argc; i++)
- if (!jsval_to_JSVariant(cx, argv[i], in_argv.AppendElement()))
- return JS_FALSE;
-
- JSVariant out_rval;
-
- return (function->Manager()->RequestRunToCompletion() &&
- function->CallCall(receiver, in_argv,
- aco.StatusPtr(), &out_rval) &&
- aco.Ok() &&
- jsval_from_JSVariant(cx, out_rval, vp));
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_Construct(JSContext* cx, unsigned argc, jsval* vp)
-{
- CPOW_LOG(("Calling CPOW_Construct..."));
-
- ObjectWrapperParent* constructor = Unwrap(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
- if (!constructor)
- return with_error(cx, JS_FALSE, "Could not unwrap CPOW constructor function");
-
- AutoCheckOperation aco(cx, constructor);
-
- InfallibleTArray<JSVariant> in_argv(argc);
- jsval* argv = JS_ARGV(cx, vp);
- for (unsigned i = 0; i < argc; i++)
- if (!jsval_to_JSVariant(cx, argv[i], in_argv.AppendElement()))
- return JS_FALSE;
-
- PObjectWrapperParent* out_powp;
-
- return (constructor->Manager()->RequestRunToCompletion() &&
- constructor->CallConstruct(in_argv, aco.StatusPtr(), &out_powp) &&
- aco.Ok() &&
- jsval_from_PObjectWrapperParent(cx, out_powp, vp));
-}
-
-/*static*/ JSBool
-ObjectWrapperParent::CPOW_HasInstance(JSContext *cx, HandleObject obj, MutableHandleValue v,
- JSBool *bp)
-{
- CPOW_LOG(("Calling CPOW_HasInstance..."));
-
- *bp = JS_FALSE;
-
- ObjectWrapperParent* self = Unwrap(cx, obj);
- if (!self)
- return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_HasInstance");
-
- AutoCheckOperation aco(cx, self);
-
- JSVariant in_v;
-
- if (!jsval_to_JSVariant(cx, v, &in_v))
- return JS_FALSE;
-
- return (self->Manager()->RequestRunToCompletion() &&
- self->CallHasInstance(in_v,
- aco.StatusPtr(), bp) &&
- aco.Ok());
-}
deleted file mode 100644
--- a/js/ipc/ObjectWrapperParent.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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/. */
-
-#ifndef mozilla_jsipc_ObjectWrapperParent_h
-#define mozilla_jsipc_ObjectWrapperParent_h
-
-#include "mozilla/jsipc/PObjectWrapperParent.h"
-#include "jsapi.h"
-#include "jsclass.h"
-#include "nsAutoJSValHolder.h"
-
-namespace mozilla {
-namespace jsipc {
-
-class ContextWrapperParent;
-
-class OperationChecker {
-public:
- virtual void CheckOperation(JSContext* cx,
- OperationStatus* status) = 0;
-};
-
-class ObjectWrapperParent
- : public PObjectWrapperParent
- , public OperationChecker
-{
-public:
-
- ObjectWrapperParent()
- : mObj(NULL)
- {}
-
- JSObject* GetJSObject(JSContext* cx) const;
-
- JSObject* GetJSObjectOrNull() const {
- return mObj;
- }
-
- jsval GetJSVal(JSContext* cx) const {
- return OBJECT_TO_JSVAL(GetJSObject(cx));
- }
-
- void CheckOperation(JSContext* cx,
- OperationStatus* status);
-
- static const js::Class sCPOW_JSClass;
-
-protected:
-
- void ActorDestroy(ActorDestroyReason why);
-
- ContextWrapperParent* Manager();
-
-private:
-
- mutable JSObject* mObj;
-
- static JSBool
- CPOW_AddProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandleValue vp);
-
- static JSBool
- CPOW_DelProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JSBool *succeeded);
-
- static JSBool
- CPOW_GetProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
- JS::MutableHandleValue vp);
-
- static JSBool
- CPOW_SetProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JSBool strict,
- JS::MutableHandleValue vp);
-
- JSBool NewEnumerateInit(JSContext* cx, jsval* statep, jsid* idp);
- JSBool NewEnumerateNext(JSContext* cx, jsval* statep, jsid* idp);
- JSBool NewEnumerateDestroy(JSContext* cx, jsval state);
- static JSBool
- CPOW_NewEnumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp enum_op,
- jsval *statep, jsid *idp);
-
- static JSBool
- CPOW_NewResolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned flags,
- JS::MutableHandleObject objp);
-
- static JSBool
- CPOW_Convert(JSContext *cx, JS::HandleObject obj, JSType type, JS::MutableHandleValue vp);
-
- static void
- CPOW_Finalize(js::FreeOp* fop, JSObject* obj);
-
- static JSBool
- CPOW_Call(JSContext* cx, unsigned argc, jsval* vp);
-
- static JSBool
- CPOW_Construct(JSContext *cx, unsigned argc, jsval *vp);
-
- static JSBool
- CPOW_HasInstance(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue vp, JSBool *bp);
-
- static bool jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to);
- static bool jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
- jsval* to);
- static bool boolean_from_JSVariant(JSContext* cx, const JSVariant& from,
- JSBool* to);
- static bool
- JSObject_to_PObjectWrapperParent(JSContext* cx, JSObject* from,
- PObjectWrapperParent** to);
- static bool
- JSObject_from_PObjectWrapperParent(JSContext* cx,
- const PObjectWrapperParent* from,
- JS::MutableHandleObject to);
- static bool
- jsval_from_PObjectWrapperParent(JSContext* cx,
- const PObjectWrapperParent* from,
- jsval* to);
-};
-
-template <class StatusOwnerPolicy>
-class AutoCheckOperationBase
- : public StatusOwnerPolicy
-{
- JSContext* const mContext;
- OperationChecker* const mChecker;
-
-protected:
-
- AutoCheckOperationBase(JSContext* cx,
- OperationChecker* checker)
- : mContext(cx)
- , mChecker(checker)
- {}
-
- virtual ~AutoCheckOperationBase() {
- mChecker->CheckOperation(mContext, StatusOwnerPolicy::StatusPtr());
- }
-
-public:
-
- bool Ok() {
- return (StatusOwnerPolicy::StatusPtr()->type() == OperationStatus::TJSBool &&
- StatusOwnerPolicy::StatusPtr()->get_JSBool());
- }
-};
-
-}}
-
-#endif /* mozilla_jsipc_ObjectWrapperParent_h */
deleted file mode 100644
--- a/js/ipc/PContextWrapper.ipdl
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 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 protocol PTestShell;
-include protocol PObjectWrapper;
-
-namespace mozilla {
-namespace jsipc {
-
-rpc protocol PContextWrapper
-{
- manager PTestShell;
- manages PObjectWrapper;
-parent:
- async __delete__();
- async PObjectWrapper(bool makeGlobal);
-};
-
-}}
new file mode 100644
--- /dev/null
+++ b/js/ipc/PJavaScript.ipdl
@@ -0,0 +1,47 @@
+/* -*- 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 protocol PContent;
+include DOMTypes;
+include JavaScriptTypes;
+
+using mozilla::void_t;
+
+namespace mozilla {
+namespace jsipc {
+
+rpc protocol PJavaScript
+{
+ manager PContent;
+
+child:
+ // The parent process no longer holds any references to the child object.
+ async DropObject(uint64_t objId);
+
+ // These roughly map to the ProxyHandler hooks that CPOWs need.
+ urgent Has(uint64_t objId, nsString id) returns (ReturnStatus rs, bool has);
+ urgent HasOwn(uint64_t objId, nsString id) returns (ReturnStatus rs, bool has);
+ urgent Get(uint64_t objId, uint64_t receiverId, nsString id) returns (ReturnStatus rs, JSVariant result);
+ urgent Set(uint64_t objId, uint64_t receiverId, nsString id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
+ urgent Call(uint64_t objId, JSParam[] argv) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
+
+ urgent InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
+ urgent GetPropertyDescriptor(uint64_t objId, nsString id, uint32_t flags) returns (ReturnStatus rs, PPropertyDescriptor result);
+ urgent GetOwnPropertyDescriptor(uint64_t objId, nsString id, uint32_t flags) returns (ReturnStatus rs, PPropertyDescriptor result);
+ urgent GetOwnPropertyNames(uint64_t objId) returns (ReturnStatus rs, nsString[] names);
+ urgent Keys(uint64_t objId) returns (ReturnStatus rs, nsString[] names);
+ urgent ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
+ urgent ClassName(uint64_t objId) returns (nsString name);
+ urgent IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
+ urgent PreventExtensions(uint64_t objId) returns (ReturnStatus rs);
+
+parent:
+ async __delete__();
+};
+
+}
+}
deleted file mode 100644
--- a/js/ipc/PObjectWrapper.ipdl
+++ /dev/null
@@ -1,92 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 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 protocol PContextWrapper;
-
-include "mozilla/jsipc/CPOWTypes.h";
-
-using mozilla::void_t;
-using JSType;
-using JSBool;
-
-namespace mozilla {
-namespace jsipc {
-
-union JSVariant {
- void_t;
- nullable PObjectWrapper;
- nsString;
- int;
- double;
- bool; // We'd like to use JSBool here, but IPC::ParamTraits would
- // treat JSBool as int.
-};
-
-union OperationStatus {
- JSBool;
- JSVariant; // Exception thrown.
-};
-
-rpc protocol PObjectWrapper
-{
- manager PContextWrapper;
-
-child:
- __delete__(); // unroot
-
- rpc AddProperty(nsString id)
- returns (OperationStatus status);
-
- rpc GetProperty(nsString id)
- returns (OperationStatus status,
- JSVariant vp);
-
- rpc SetProperty(nsString id,
- JSVariant v)
- returns (OperationStatus status,
- JSVariant vp);
-
- rpc DelProperty(nsString id)
- returns (OperationStatus status,
- JSVariant vp);
-
- rpc NewEnumerateInit()
- returns (OperationStatus status,
- JSVariant statep,
- int idp);
-
- rpc NewEnumerateNext(JSVariant in_state)
- returns (OperationStatus status,
- JSVariant statep,
- nsString idp);
-
- async NewEnumerateDestroy(JSVariant in_state);
-
- rpc NewResolve(nsString id,
- int flags)
- returns (OperationStatus status,
- nullable PObjectWrapper obj2);
-
- rpc Convert(JSType type)
- returns (OperationStatus status,
- JSVariant vp);
-
- rpc Call(PObjectWrapper receiver,
- JSVariant[] argv)
- returns (OperationStatus status,
- JSVariant rval);
-
- rpc Construct(JSVariant[] argv)
- returns (OperationStatus status,
- nullable PObjectWrapper rval);
-
- rpc HasInstance(JSVariant v)
- returns (OperationStatus status,
- JSBool bp);
-};
-
-}}
--- a/js/ipc/ipdl.mk
+++ b/js/ipc/ipdl.mk
@@ -1,8 +1,8 @@
# 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/.
IPDLSRCS = \
- PContextWrapper.ipdl \
- PObjectWrapper.ipdl \
+ JavaScriptTypes.ipdlh \
+ PJavaScript.ipdl \
$(NULL)
deleted file mode 100644
--- a/js/ipc/jar.mn
+++ /dev/null
@@ -1,7 +0,0 @@
-# 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/.
-
-toolkit.jar:
- content/global/cpow/test.xul (tests/adhoc/test.xul)
- content/global/cpow/child.html (tests/adhoc/child.html)
--- a/js/ipc/moz.build
+++ b/js/ipc/moz.build
@@ -1,21 +1,14 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
MODULE = 'js'
-EXPORTS.mozilla.jsipc += [
- 'CPOWTypes.h',
- 'ContextWrapperChild.h',
- 'ContextWrapperParent.h',
- 'ObjectWrapperChild.h',
- 'ObjectWrapperParent.h',
+CPP_SOURCES += [
+ 'JavaScriptChild.cpp',
+ 'JavaScriptParent.cpp',
+ 'JavaScriptShared.cpp',
]
-CPP_SOURCES += [
- 'ObjectWrapperChild.cpp',
- 'ObjectWrapperParent.cpp',
-]
-
deleted file mode 100644
--- a/js/ipc/tests/adhoc/child.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<html>
- <head>
- </head>
- <body>
- <script>
- window.foo = {
- a: 42,
- b: 37 * 73,
- ctor: function(name, value) {
- this[name] = value;
- },
- fakector: function(name, value) {
- window[name] = "oyez";
- this[name] = value;
- return window;
- },
- f: function(x) {
- document.body.appendChild(document.createElement("div")).innerHTML =
- "called f(" + x + ")";
- return x + Math.PI;
- },
- pitch: function(ball) {
- throw ball;
- }
- };
- window.foo.self = window.foo;
- </script>
- oyez
- </body>
-</html>
deleted file mode 100644
--- a/js/ipc/tests/adhoc/test.xul
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- width="800" height="600" orient="vertical">
-
- <script type="application/javascript">
-
- var cpow_tests = {
- resolve: function(obj, keys) {
- alert("resolving");
- keys = keys.split(" ");
- for (var i = 0; i != keys.length; ++i)
- alert("has " + keys[i] + "? " + (keys[i] in obj));
- alert("done resolving");
- },
- iterate: function(obj) {
- alert("iterating");
- for (var k in obj)
- alert("key: " + k);
- alert("done iterating");
- },
- navigate: function(child) {
- alert("navigating");
- child.location = prompt("Where to?");
- setTimeout(function() {
- alert(child.location.href);
- }, 2000);
- },
- construct: function(foo) {
- alert(new foo.ctor("answer", 42).answer);
- alert(new foo.fakector("answer", 42).answer);
- },
- indirect_eval: function(child) {
- alert(child.eval("location.href"));
- alert(new child.Function("x", "return x+1")(42));
- },
- funcalls: function(foo) {
- var fn = foo.f;
- alert(foo.f(2));
- alert(fn.call.call(fn, foo, 3));
- },
- equality: function(child) {
- var foo = child.foo,
- self = foo.self;
- alert("foo == self? " + (foo == self));
- alert("foo === self? " + (foo === self));
- },
- exceptions: function(child) {
- var ball = "ball";
- try {
- child.foo.pitch(ball);
- alert("shouldn't reach this point");
- } catch (x) {
- alert("ball === x? " + (ball === x));
- }
- }
- }
-
- function getCPOW() {
- if (!getCPOW.cpow) {
- var page = document.getElementById("page"),
- owner = page.QueryInterface(Components.interfaces.nsIFrameLoaderOwner);
- getCPOW.cpow = owner.crossProcessObjectWrapper;
- alert("got fresh CPOW");
- }
- return getCPOW.cpow;
- }
-
- function test_cpow() {
- var child = getCPOW();
- cpow_tests.construct(child.foo);
- cpow_tests.resolve(child.location, "href hostname");
- cpow_tests.iterate(child.location);
- cpow_tests.iterate(child.foo);
- cpow_tests.funcalls(child.foo);
- cpow_tests.navigate(child);
- cpow_tests.equality(child);
- cpow_tests.exceptions(child);
- setTimeout(function() {
- alert("going back");
- child.history.back();
- }, 3000);
- }
-
- function show_location() {
- var child = getCPOW();
- child.location += "#fragment";
- alert(child.location.href);
- alert(child.document.documentURI);
- }
- </script>
-
- <toolbar id="controls">
- <toolbarbutton onclick="test_cpow()" label="Run tests."/>
- <toolbarbutton onclick="show_location()" label="Show location."/>
- </toolbar>
-
- <browser remote="true" width="200" height="200"
- type="content"
- src="child.html"
- id="page" />
-
-</window>
deleted file mode 100644
--- a/js/ipc/tests/moz.build
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-MODULE = 'test_jsipc'
-
-# FIXME/bug 575918: out-of-process xpcshell is broken on OS X
-if CONFIG['OS_ARCH'] != 'Darwin':
- XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
deleted file mode 100644
--- a/js/ipc/tests/unit/cpow_child.js
+++ /dev/null
@@ -1,66 +0,0 @@
-var data = {
- answer: 42,
- nested: { objects: { work: "yes they do" } },
- arr: [
- "zeroeth",
- { foo: "bar" },
- function() { return data },
- { toString: function() { return "last" } }
- ],
- toString: function() {
- return "CPOW";
- }
-};
-
-var empty = function() {
- this.try_to_delete = "just try";
-};
-empty.prototype = {
- try_to_delete: "bwahaha",
- inherited: "inherited",
- method: function() {
- return "called"
- }
-};
-data.derived = new empty;
-
-(data.constructor = function(value) {
- var self = this;
- this.value = value;
- this.check = function(that) {
- do_check_eq(this.value, that.value);
- do_check_eq(this, self);
- do_check_eq(this, that);
- do_check_false(this.isGlobal());
- };
-}).prototype = {
- isGlobal: function() {
- return (function() { return this })() == this;
- }
-};
-
-function A() {
- this.a = A;
- this.b = A;
-}
-function B() {
- this.b = B;
- this.c = B;
-}
-B.prototype = new A;
-
-function pitch(ball) {
- throw ball;
-}
-
-get_set = {
- get foo() { return 42; },
- get foo_throws() { throw "BAM"; },
- set one(val) { this.two = val + 1; }
-};
-
-function type(x) {
- return typeof x;
-}
-
-function run_test() {}
deleted file mode 100644
--- a/js/ipc/tests/unit/test_cpow.js
+++ /dev/null
@@ -1,277 +0,0 @@
-function run_test() {
- run_test_in_child("cpow_child.js", run_actual_tests);
-}
-
-function run_actual_tests() {
- var obj = getChildGlobalObject();
-
- test_properties(obj.data);
- test_delete(obj.data);
- test_toString(obj.data);
- test_inheritance(obj.data.derived);
- test_constructor(obj.data.constructor,
- obj.Function,
- obj.Object,
- obj.Date);
- test_instanceof(obj.A, obj.B);
- test_enumeration(obj.A, obj.B);
- test_Array(obj.Array);
- test_Function(obj.Function);
- test_exceptions(obj.pitch, obj.Object);
- test_generators(obj.Function);
- test_Iterator(obj.data, obj.Iterator, obj.StopIteration);
- test_getters_setters(obj.get_set, obj.Function);
- test_forbidden_things(obj);
-
- do_test_finished();
-}
-
-function test_properties(data) {
- do_check_true("answer" in data);
- do_check_false("cnefhasefho" in data.nested);
-
- do_check_eq(data.answer, 42);
- do_check_eq(data.nested.objects.work,
- "yes they do");
- do_check_eq(data.asodfijasdiofj, void(0));
-
- do_check_eq(data.arr.length, 4);
- do_check_eq(data.arr[4], void(0));
- do_check_eq(data.arr[0], "zeroeth");
- do_check_eq(data.arr[1].foo, "bar");
-
- do_check_true(2 in data.arr);
- do_check_eq(data.arr[2], data.arr[2]); // ensure reuse
- do_check_true(data.arr[2]() === data);
- do_check_eq(data.arr[2]().arr[0], "zeroeth");
- do_check_true("call" in data.arr[2]);
-
- do_check_eq(data.arr[3], "last");
-}
-
-function test_delete(data) {
- do_check_eq(data.derived.try_to_delete, "just try");
- do_check_true(delete data.derived.try_to_delete);
- do_check_eq(data.derived.try_to_delete, "bwahaha");
- do_check_true(delete data.derived.try_to_delete);
- do_check_eq(data.derived.try_to_delete, "bwahaha");
-}
-
-function test_toString(data) {
- do_check_eq(data.toString(), "CPOW");
- do_check_eq(data + "asdf", "CPOWasdf");
- do_check_eq(new String(data), "CPOW");
-}
-
-function test_inheritance(derived) {
- do_check_true("inherited" in derived);
- do_check_false(derived.hasOwnProperty("inherited"));
- var base = derived.__proto__;
- do_check_true(base.hasOwnProperty("inherited"));
- do_check_eq(derived.inherited, "inherited");
- do_check_eq(derived.method(), "called");
- do_check_eq(base.method, derived.method);
- do_check_true(base.method === derived.method);
-}
-
-function test_constructor(ctor,
- ChildFunction,
- ChildObject,
- ChildDate) {
- var obj = new ctor(42);
- obj.check(obj);
-
- // Re-run test_inheritance, creating locally everything that
- // test_inheritance expects to be created in the child process:
- var empty = new ChildFunction(),
- proto = new ChildObject();
- proto.inherited = "inherited";
- proto.method = new ChildFunction("return 'called'");
- empty.prototype = proto;
- test_inheritance(new empty);
-
- var cd = new ChildDate,
- tolerance_ms = 20000; // Ridiculously large to accommodate gcZeal delays.
- do_check_eq(Math.max(Math.abs(cd.getTime() - new Date),
- tolerance_ms),
- tolerance_ms);
- do_check_true(cd instanceof ChildDate);
-}
-
-function test_enumeration(A, B) {
- function check(obj, nk, s) {
- var keys = [];
- for (var k in obj)
- keys[keys.length] = k;
- do_check_eq(keys.length, nk);
- do_check_eq(keys.sort().join("~"), s);
- }
- check(new B, 3, "a~b~c");
- check(B.prototype, 2, "a~b");
- B.prototype = A.prototype;
- A.prototype = new B;
- check(new A, 3, "a~b~c");
- check(new B, 2, "b~c");
-
- // Put things back the way they were, mostly:
- A.prototype = B.prototype;
- B.prototype = new A;
-}
-
-function test_instanceof(A, B) {
- var a = new A, b = new B;
- do_check_true(a instanceof A);
- do_check_false(a instanceof B);
- do_check_true(b instanceof A);
- do_check_true(b instanceof B);
-}
-
-function test_Array(ChildArray) {
- do_check_true(!!ChildArray);
- var arr = new ChildArray(1, new ChildArray(2, 3), 4);
- do_check_eq(arr.length, 3);
- do_check_eq(arr.slice(1).shift()[1], 3);
- arr[2] = arr[1];
- do_check_eq(arr.pop()[0], 2);
-}
-
-function test_Function(ChildFunction) {
- var succ = new ChildFunction("x", "return x + 1");
- do_check_eq(succ(succ(3)), 5);
- do_check_eq(succ + "", "" + new Function("x", "return x + 1"));
-}
-
-function test_exceptions(pitch, ChildObject) {
- try {
- throw "parent-only";
- } catch (x) {
- do_check_eq(x, "parent-only");
- }
- var ball = new ChildObject(),
- thrown = false;
- ball.sport = "baseball";
- try {
- pitch(ball);
- do_throw("Should have thrown.");
- } catch (x) {
- thrown = true;
- do_check_eq(x.sport, "baseball");
- do_check_eq(x, ball);
- do_check_true(x === ball);
- }
- do_check_true(thrown);
-}
-
-function test_generators(ChildFunction) {
- // Run the test with own Function just to keep sane:
- if (ChildFunction != Function)
- test_generators(Function);
-
- var count = 0, sum = 0,
- genFn = new ChildFunction("for(var i = 1; i < 4; i++) yield i");
-
- var gen = genFn();
- do try { sum += gen.next(); }
- catch (x) { break; }
- while ((count += 1));
- do_check_eq(count, 3);
- do_check_eq(sum, 6);
-
- try {
- for (var n in genFn()) {
- count += 1;
- sum += n;
- }
- } catch (x) {}
- do_check_eq(count, 6);
- do_check_eq(sum, 12);
-}
-
-function test_Iterator(data, ChildIterator, ChildStopIteration) {
- do_check_true(data && ChildIterator && true);
- var copy = {},
- thrown = null;
- try {
- for (var kv in ChildIterator(data)) {
- do_check_true(kv[0] in data);
- do_check_eq(data[kv[0]], kv[1]);
- copy[kv[0]] = kv[1];
- }
- // XXX I shouldn't have to be catching this, should I?
- } catch (x) { thrown = x; }
- do_check_true(thrown != null);
- do_check_true(thrown instanceof ChildStopIteration);
- do_check_eq(copy + "", "CPOW");
-}
-
-function test_getters_setters(get_set, ChildFunction) {
- do_check_eq(get_set.foo, 42);
- var thrown = null;
- try { get_set.bar = get_set.foo_throws; }
- catch (x) { thrown = x; }
- do_check_true(thrown != null);
- do_check_eq(thrown, "BAM");
- do_check_false("bar" in get_set);
-
- get_set.two = 2222;
- get_set.one = 1;
- do_check_eq(get_set.two, 2);
-
- var getter = new ChildFunction("return 'you got me'");
- get_set.__defineGetter__("defined_getter", getter);
- do_check_eq(get_set.defined_getter, "you got me");
- do_check_eq(get_set.__lookupGetter__("defined_getter"),
- getter);
-
- var setter = new ChildFunction("val", "this.side_effect = val");
- get_set.__defineSetter__("defined_setter", setter);
- get_set.side_effect = "can't touch this";
- get_set.defined_setter = "you set me";
- do_check_eq(get_set.side_effect, "you set me");
- do_check_eq(get_set.__lookupSetter__("defined_setter"),
- setter);
-}
-
-function test_forbidden_things(child) {
- var x_count = 0;
-
- do_check_eq(child.type(42), "number");
-
- try {
- child.type(function(){});
- do_throw("Should not have been able to pass a parent-created " +
- "function to the child");
- } catch (x) {
- print(x);
- x_count += 1;
- }
-
- try {
- child.type({});
- do_throw("Should not have been able to pass a parent-created " +
- "object to the child");
- } catch (x) {
- print(x);
- x_count += 1;
- }
-
- try {
- child.type.prop = {};
- do_throw("Should not have been able to set a property of a child " +
- "object to a parent-created object value");
- } catch (x) {
- print(x);
- x_count += 1;
- }
-
- try {
- child.type.prop = function(){};
- do_throw("Should not have been able to set a property of a child " +
- "object to a parent-created function value");
- } catch (x) {
- print(x);
- x_count += 1;
- }
-
- do_check_eq(x_count, 4);
-}
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -755,28 +755,30 @@ js::gc::MarkRuntime(JSTracer *trc, bool
* which have been entered. Globals aren't nursery allocated so there's
* no need to do this for minor GCs.
*/
for (CompartmentsIter c(rt); !c.done(); c.next())
c->mark(trc);
}
/* The embedding can register additional roots here. */
- if (JSTraceDataOp op = rt->gcBlackRootsTraceOp)
- (*op)(trc, rt->gcBlackRootsData);
+ for (size_t i = 0; i < rt->gcBlackRootTracers.length(); i++) {
+ const JSRuntime::ExtraTracer &e = rt->gcBlackRootTracers[i];
+ (*e.op)(trc, e.data);
+ }
/* During GC, we don't mark gray roots at this stage. */
- if (JSTraceDataOp op = rt->gcGrayRootsTraceOp) {
+ if (JSTraceDataOp op = rt->gcGrayRootTracer.op) {
if (!IS_GC_MARKING_TRACER(trc))
- (*op)(trc, rt->gcGrayRootsData);
+ (*op)(trc, rt->gcGrayRootTracer.data);
}
}
void
js::gc::BufferGrayRoots(GCMarker *gcmarker)
{
JSRuntime *rt = gcmarker->runtime;
- if (JSTraceDataOp op = rt->gcGrayRootsTraceOp) {
+ if (JSTraceDataOp op = rt->gcGrayRootTracer.op) {
gcmarker->startBufferingGrayRoots();
- (*op)(gcmarker, rt->gcGrayRootsData);
+ (*op)(gcmarker, rt->gcGrayRootTracer.data);
gcmarker->endBufferingGrayRoots();
}
}
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -811,20 +811,16 @@ JSRuntime::JSRuntime(JSUseHelperThreads
gcValidate(true),
gcFullCompartmentChecks(false),
gcCallback(NULL),
gcSliceCallback(NULL),
gcFinalizeCallback(NULL),
analysisPurgeCallback(NULL),
analysisPurgeTriggerBytes(0),
gcMallocBytes(0),
- gcBlackRootsTraceOp(NULL),
- gcBlackRootsData(NULL),
- gcGrayRootsTraceOp(NULL),
- gcGrayRootsData(NULL),
autoGCRooters(NULL),
scriptAndCountsVector(NULL),
NaNValue(UndefinedValue()),
negativeInfinityValue(UndefinedValue()),
positiveInfinityValue(UndefinedValue()),
emptyString(NULL),
sourceHook(NULL),
debugMode(false),
@@ -2287,22 +2283,34 @@ JS_RemoveScriptRootRT(JSRuntime *rt, JSS
js_RemoveRoot(rt, (void *)rp);
}
JS_NEVER_INLINE JS_PUBLIC_API(void)
JS_AnchorPtr(void *p)
{
}
-JS_PUBLIC_API(void)
-JS_SetExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
+JS_PUBLIC_API(JSBool)
+JS_AddExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
{
AssertHeapIsIdle(rt);
- rt->gcBlackRootsTraceOp = traceOp;
- rt->gcBlackRootsData = data;
+ return !!rt->gcBlackRootTracers.append(JSRuntime::ExtraTracer(traceOp, data));
+}
+
+JS_PUBLIC_API(void)
+JS_RemoveExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
+{
+ AssertHeapIsIdle(rt);
+ for (size_t i = 0; i < rt->gcBlackRootTracers.length(); i++) {
+ JSRuntime::ExtraTracer *e = &rt->gcBlackRootTracers[i];
+ if (e->op == traceOp && e->data == data) {
+ rt->gcBlackRootTracers.erase(e);
+ break;
+ }
+ }
}
JS_PUBLIC_API(void)
JS_CallValueTracer(JSTracer *trc, Value *valuep, const char *name)
{
MarkValueUnbarriered(trc, valuep, name);
}
@@ -7152,8 +7160,20 @@ JS_PUBLIC_API(JSObject *)
JS_GetScriptedGlobal(JSContext *cx)
{
ScriptFrameIter i(cx);
if (i.done())
return cx->global();
return &i.scopeChain()->global();
}
+JS_PUBLIC_API(JSBool)
+JS_PreventExtensions(JSContext *cx, JS::HandleObject obj)
+{
+ JSBool extensible;
+ if (!JS_IsExtensible(cx, obj, &extensible))
+ return JS_TRUE;
+ if (extensible)
+ return JS_TRUE;
+
+ return JSObject::preventExtensions(cx, obj);
+}
+
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2368,18 +2368,22 @@ JS_AnchorPtr(void *p);
/*
* Register externally maintained GC roots.
*
* traceOp: the trace operation. For each root the implementation should call
* JS_CallTracer whenever the root contains a traceable thing.
* data: the data argument to pass to each invocation of traceOp.
*/
+extern JS_PUBLIC_API(JSBool)
+JS_AddExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
+
+/* Undo a call to JS_AddExtraGCRootsTracer. */
extern JS_PUBLIC_API(void)
-JS_SetExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
+JS_RemoveExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
/*
* JS_CallTracer API and related macros for implementors of JSTraceOp, to
* enumerate all references to traceable things reachable via a property or
* other strong ref identified for debugging purposes by name or index or
* a naming callback.
*
* See the JSTraceOp typedef.
@@ -3212,16 +3216,19 @@ extern JS_PUBLIC_API(JSBool)
JS_DeepFreezeObject(JSContext *cx, JSObject *obj);
/*
* Freezes an object; see ES5's Object.freeze(obj) method.
*/
extern JS_PUBLIC_API(JSBool)
JS_FreezeObject(JSContext *cx, JSObject *obj);
+extern JS_PUBLIC_API(JSBool)
+JS_PreventExtensions(JSContext *cx, JS::HandleObject obj);
+
extern JS_PUBLIC_API(JSObject *)
JS_New(JSContext *cx, JSObject *ctor, unsigned argc, jsval *argv);
extern JS_PUBLIC_API(JSObject *)
JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
JSObject *proto, unsigned attrs);
extern JS_PUBLIC_API(JSBool)
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1160,26 +1160,37 @@ struct JSRuntime : public JS::shadow::Ru
void setNeedsBarrier(bool needs) {
needsBarrier_ = needs;
}
bool needsBarrier() const {
return needsBarrier_;
}
+ struct ExtraTracer {
+ JSTraceDataOp op;
+ void *data;
+
+ ExtraTracer()
+ : op(NULL), data(NULL)
+ {}
+ ExtraTracer(JSTraceDataOp op, void *data)
+ : op(op), data(data)
+ {}
+ };
+
/*
* The trace operations to trace embedding-specific GC roots. One is for
* tracing through black roots and the other is for tracing through gray
* roots. The black/gray distinction is only relevant to the cycle
* collector.
*/
- JSTraceDataOp gcBlackRootsTraceOp;
- void *gcBlackRootsData;
- JSTraceDataOp gcGrayRootsTraceOp;
- void *gcGrayRootsData;
+ typedef js::Vector<ExtraTracer, 4, js::SystemAllocPolicy> ExtraTracerVector;
+ ExtraTracerVector gcBlackRootTracers;
+ ExtraTracer gcGrayRootTracer;
/* Stack of thread-stack-allocated GC roots. */
js::AutoGCRooter *autoGCRooters;
/*
* The GC can only safely decommit memory when the page size of the
* running process matches the compiled arena size.
*/
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -47,18 +47,18 @@ JS_FRIEND_API(void)
JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook)
{
rt->sourceHook = hook;
}
JS_FRIEND_API(void)
JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
{
- rt->gcGrayRootsTraceOp = traceOp;
- rt->gcGrayRootsData = data;
+ rt->gcGrayRootTracer.op = traceOp;
+ rt->gcGrayRootTracer.data = data;
}
JS_FRIEND_API(JSString *)
JS_GetAnonymousString(JSRuntime *rt)
{
JS_ASSERT(rt->hasContexts());
return rt->atomState.anonymous;
}
@@ -297,16 +297,28 @@ JS_DefineFunctionsWithHelp(JSContext *cx
if (!DefineHelpProperty(cx, fun, "help", fs->help))
return false;
}
}
return true;
}
+JS_FRIEND_API(bool)
+js_ObjectClassIs(JSContext *cx, HandleObject obj, ESClassValue classValue)
+{
+ return ObjectClassIs(obj, classValue, cx);
+}
+
+JS_FRIEND_API(const char *)
+js_ObjectClassName(JSContext *cx, HandleObject obj)
+{
+ return JSObject::className(cx, obj);
+}
+
AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: cx(cx), oldCompartment(cx->compartment())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
cx->setCompartment(newCompartment);
}
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -128,16 +128,22 @@ JS_BasicObjectToString(JSContext *cx, JS
extern JS_FRIEND_API(JSBool)
js_GetterOnlyPropertyStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JSBool strict,
JS::MutableHandleValue vp);
JS_FRIEND_API(void)
js_ReportOverRecursed(JSContext *maybecx);
+JS_FRIEND_API(bool)
+js_ObjectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
+
+JS_FRIEND_API(const char *)
+js_ObjectClassName(JSContext *cx, JS::HandleObject obj);
+
#ifdef DEBUG
/*
* Routines to print out values during debugging. These are FRIEND_API to help
* the debugger find them and to support temporarily hacking js_Dump* calls
* into other code.
*/
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2912,18 +2912,18 @@ MarkGrayReferences(JSRuntime *rt)
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_MARK);
gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_SWEEP_MARK_GRAY);
gcmarker->setMarkColorGray();
if (gcmarker->hasBufferedGrayRoots()) {
for (ZoneIterT zone(rt); !zone.done(); zone.next())
gcmarker->markBufferedGrayRoots(zone);
} else {
JS_ASSERT(!rt->gcIsIncremental);
- if (JSTraceDataOp op = rt->gcGrayRootsTraceOp)
- (*op)(gcmarker, rt->gcGrayRootsData);
+ if (JSTraceDataOp op = rt->gcGrayRootTracer.op)
+ (*op)(gcmarker, rt->gcGrayRootTracer.data);
}
SliceBudget budget;
gcmarker->drainMarkStack(budget);
}
MarkWeakReferences<CompartmentIterT>(rt, gcstats::PHASE_SWEEP_MARK_GRAY_WEAK);
JS_ASSERT(gcmarker->isDrained());
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -675,29 +675,16 @@ SendCommand(JSContext* cx,
JS_ReportError(cx, "Couldn't send command!");
return false;
}
JS_SET_RVAL(cx, vp, JSVAL_VOID);
return true;
}
-static JSBool
-GetChildGlobalObject(JSContext* cx,
- unsigned,
- jsval* vp)
-{
- JS::Rooted<JSObject*> global(cx);
- if (XRE_GetChildGlobalObject(cx, global.address())) {
- JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(global));
- return true;
- }
- return false;
-}
-
/*
* JSContext option name to flag map. The option names are in alphabetical
* order for better reporting.
*/
static const struct JSOption {
const char *name;
uint32_t flag;
} js_options[] = {
@@ -914,17 +901,16 @@ static const JSFunctionSpec glob_functio
JS_FS("gczeal", GCZeal, 1,0),
#endif
JS_FS("options", Options, 0,0),
JS_FN("parent", Parent, 1,0),
#ifdef DEBUG
JS_FS("dumpHeap", DumpHeap, 5,0),
#endif
JS_FS("sendCommand", SendCommand, 1,0),
- JS_FS("getChildGlobalObject", GetChildGlobalObject, 0,0),
JS_FS("atob", Atob, 1,0),
JS_FS("btoa", Btoa, 1,0),
JS_FS("Blob", Blob, 2,JSFUN_CONSTRUCTOR),
JS_FS("File", File, 2,JSFUN_CONSTRUCTOR),
JS_FS_END
};
JSClass global_class = {
--- a/js/xpconnect/src/Makefile.in
+++ b/js/xpconnect/src/Makefile.in
@@ -27,18 +27,21 @@ LOCAL_INCLUDES = \
-I$(topsrcdir)/content/events/src \
-I$(topsrcdir)/content/html/content/src \
-I$(topsrcdir)/content/html/document/src \
-I$(topsrcdir)/content/svg/content/src \
-I$(topsrcdir)/layout/style \
-I$(topsrcdir)/layout/base \
-I$(topsrcdir)/dom/base \
-I$(topsrcdir)/xpcom/ds \
+ -I$(topsrcdir)/js/ipc \
$(NULL)
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
SHARED_LIBRARY_LIBS = \
../loader/$(LIB_PREFIX)jsloader_s.$(LIB_SUFFIX) \
../wrappers/$(LIB_PREFIX)xpcwrappers_s.$(LIB_SUFFIX) \
$(NULL)
EXTRA_MDDEPEND_FILES = dom_qsgen.pp dictionary_helper_gen.pp event_impl_gen.pp
include $(topsrcdir)/config/rules.mk
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -18,16 +18,17 @@
#include "AccessCheck.h"
#include "nsJSUtils.h"
#include "WrapperFactory.h"
#include "nsWrapperCacheInlines.h"
#include "jsapi.h"
#include "jsfriendapi.h"
+#include "JavaScriptParent.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/PrimitiveConversions.h"
using namespace xpc;
using namespace mozilla;
using namespace mozilla::dom;
using namespace JS;
@@ -57,16 +58,28 @@ XPCConvert::IsMethodReflectable(const XP
// Reflected methods can't use native types. All native types end up
// getting tagged as void*, so this check is easy.
if (type.TagPart() == nsXPTType::T_VOID)
return false;
}
return true;
}
+static JSObject*
+UnwrapNativeCPOW(nsISupports* wrapper)
+{
+ nsCOMPtr<nsIXPConnectWrappedJS> underware = do_QueryInterface(wrapper);
+ if (underware) {
+ JSObject* mainObj = underware->GetJSObject();
+ if (mainObj && mozilla::jsipc::JavaScriptParent::IsCPOW(mainObj))
+ return mainObj;
+ }
+ return nullptr;
+}
+
/***************************************************************************/
// static
JSBool
XPCConvert::GetISupportsFromJSObject(JSObject* obj, nsISupports** iface)
{
JSClass* jsclass = js::GetObjectJSClass(obj);
NS_ASSERTION(jsclass, "obj has no class");
@@ -788,18 +801,17 @@ XPCConvert::NativeInterface2JSObject(jsv
nsresult* pErr)
{
NS_ASSERTION(!Interface || iid,
"Need the iid if you pass in an XPCNativeInterface cache.");
*d = JSVAL_NULL;
if (dest)
*dest = nullptr;
- nsISupports *src = aHelper.Object();
- if (!src)
+ if (!aHelper.Object())
return true;
if (pErr)
*pErr = NS_ERROR_XPC_BAD_CONVERT_NATIVE;
// We used to have code here that unwrapped and simply exposed the
// underlying JSObject. That caused anomolies when JSComponents were
// accessed from other JS code - they didn't act like other xpconnect
// wrapped components. So, instead, we create "double wrapped" objects
@@ -834,16 +846,27 @@ XPCConvert::NativeInterface2JSObject(jsv
return false;
return CreateHolderIfNeeded(flat, d, dest);
}
} else {
flat = nullptr;
}
+ // Don't double wrap CPOWs. This is a temporary measure for compatibility
+ // with objects that don't provide necessary QIs (such as objects under
+ // the new DOM bindings). We expect the other side of the CPOW to have
+ // the appropriate wrappers in place.
+ if (JSObject *cpow = UnwrapNativeCPOW(aHelper.Object())) {
+ if (!JS_WrapObject(cx, &cpow))
+ return false;
+ *d = OBJECT_TO_JSVAL(cpow);
+ return true;
+ }
+
// We can't simply construct a slim wrapper. Go ahead and create an
// XPCWrappedNative for this object. At this point, |flat| could be
// non-null, meaning that either we already have a wrapped native from
// the cache (which might need to be QI'd to the new interface) or that
// we found a slim wrapper that we'll have to morph.
AutoMarkingNativeInterfacePtr iface(cx);
if (iid) {
if (Interface)
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -6,16 +6,17 @@
/* An xpcom implementation of the JavaScript nsIID and nsCID objects. */
#include "xpcprivate.h"
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/Attributes.h"
#include "XPCWrapper.h"
+#include "JavaScriptParent.h"
using namespace mozilla::dom;
using namespace JS;
/***************************************************************************/
// nsJSID
NS_IMPL_THREADSAFE_ISUPPORTS1(nsJSID, nsIJSID)
@@ -471,90 +472,100 @@ nsJSIID::Enumerate(nsIXPConnectWrappedNa
*
* This static method handles both complexities, returning either an XPCWN, a
* DOM object, or null. The object may well be cross-compartment from |cx|.
*/
static JSObject *
FindObjectForHasInstance(JSContext *cx, HandleObject objArg)
{
RootedObject obj(cx, objArg), proto(cx);
- while (obj && !IS_WN_REFLECTOR(obj) && !IsDOMObject(obj)) {
+
+ while (obj && !IS_WN_REFLECTOR(obj) &&
+ !IsDOMObject(obj) && !mozilla::jsipc::JavaScriptParent::IsCPOW(obj))
+ {
if (js::IsWrapper(obj)) {
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
continue;
}
if (!js::GetObjectProto(cx, obj, &proto))
return nullptr;
obj = proto;
}
return obj;
}
+nsresult
+xpc::HasInstance(JSContext *cx, HandleObject objArg, const nsID *iid, bool *bp)
+{
+ *bp = false;
+
+ RootedObject obj(cx, FindObjectForHasInstance(cx, objArg));
+ if (!obj)
+ return NS_OK;
+
+ if (IsDOMObject(obj)) {
+ // Not all DOM objects implement nsISupports. But if they don't,
+ // there's nothing to do in this HasInstance hook.
+ nsISupports *identity = UnwrapDOMObjectToISupports(obj);
+ if (!identity)
+ return NS_OK;;
+ nsCOMPtr<nsISupports> supp;
+ identity->QueryInterface(*iid, getter_AddRefs(supp));
+ *bp = supp;
+ return NS_OK;
+ }
+
+ if (mozilla::jsipc::JavaScriptParent::IsCPOW(obj))
+ return mozilla::jsipc::JavaScriptParent::InstanceOf(obj, iid, bp);
+
+ MOZ_ASSERT(IS_WN_REFLECTOR(obj));
+ XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj);
+ if (!other_wrapper)
+ return NS_OK;
+
+ // We'll trust the interface set of the wrapper if this is known
+ // to be an interface that the objects *expects* to be able to
+ // handle.
+ if (other_wrapper->HasInterfaceNoQI(*iid)) {
+ *bp = true;
+ return NS_OK;
+ }
+
+ // Otherwise, we'll end up Querying the native object to be sure.
+ XPCCallContext ccx(JS_CALLER, cx);
+
+ AutoMarkingNativeInterfacePtr iface(ccx);
+ iface = XPCNativeInterface::GetNewOrUsed(iid);
+
+ nsresult findResult = NS_OK;
+ if (iface && other_wrapper->FindTearOff(iface, false, &findResult))
+ *bp = true;
+ if (NS_FAILED(findResult) && findResult != NS_ERROR_NO_INTERFACE)
+ return findResult;
+
+ return NS_OK;
+}
/* bool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval val, out bool bp); */
NS_IMETHODIMP
nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * /* unused */,
const jsval &val, bool *bp, bool *_retval)
{
*bp = false;
- nsresult rv = NS_OK;
- if (!JSVAL_IS_PRIMITIVE(val)) {
- // we have a JSObject
- RootedObject obj(cx, JSVAL_TO_OBJECT(val));
-
- NS_ASSERTION(obj, "when is an object not an object?");
-
- // is this really a native xpcom object with a wrapper?
- const nsIID* iid;
- mInfo->GetIIDShared(&iid);
-
- obj = FindObjectForHasInstance(cx, obj);
- if (!obj)
- return NS_OK;
+ if (JSVAL_IS_PRIMITIVE(val))
+ return NS_OK;
- if (IsDOMObject(obj)) {
- // Not all DOM objects implement nsISupports. But if they don't,
- // there's nothing to do in this HasInstance hook.
- nsISupports *identity = UnwrapDOMObjectToISupports(obj);
- if (!identity)
- return NS_OK;
- nsCOMPtr<nsISupports> supp;
- identity->QueryInterface(*iid, getter_AddRefs(supp));
- *bp = supp;
- return NS_OK;
- }
-
- MOZ_ASSERT(IS_WN_REFLECTOR(obj));
- XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj);
- if (!other_wrapper)
- return NS_OK;
+ // we have a JSObject
+ RootedObject obj(cx, JSVAL_TO_OBJECT(val));
- // We'll trust the interface set of the wrapper if this is known
- // to be an interface that the objects *expects* to be able to
- // handle.
- if (other_wrapper->HasInterfaceNoQI(*iid)) {
- *bp = true;
- return NS_OK;
- }
-
- // Otherwise, we'll end up Querying the native object to be sure.
- XPCCallContext ccx(JS_CALLER, cx);
-
- AutoMarkingNativeInterfacePtr iface(ccx);
- iface = XPCNativeInterface::GetNewOrUsed(iid);
-
- nsresult findResult = NS_OK;
- if (iface && other_wrapper->FindTearOff(iface, false, &findResult))
- *bp = true;
- if (NS_FAILED(findResult) && findResult != NS_ERROR_NO_INTERFACE)
- rv = findResult;
- }
- return rv;
+ const nsIID* iid;
+ mInfo->GetIIDShared(&iid);
+ return xpc::HasInstance(cx, obj, iid, bp);
}
/* string canCreateWrapper (in nsIIDPtr iid); */
NS_IMETHODIMP
nsJSIID::CanCreateWrapper(const nsIID * iid, char **_retval)
{
// We let anyone do this...
*_retval = xpc_CloneAllAccess();
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -11,16 +11,17 @@
#include "nsArrayEnumerator.h"
#include "nsWrapperCache.h"
#include "XPCWrapper.h"
#include "AccessCheck.h"
#include "nsJSUtils.h"
#include "mozilla/Attributes.h"
#include "jsapi.h"
+#include "jsfriendapi.h"
using namespace xpc;
using namespace JS;
NS_IMPL_THREADSAFE_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass)
// the value of this variable is never used - we use its address as a sentinel
static uint32_t zero_methods_descriptor;
@@ -1644,18 +1645,47 @@ pre_call_clean_up:
const char*
nsXPCWrappedJSClass::GetInterfaceName()
{
if (!mName)
mInfo->GetName(&mName);
return mName;
}
+static void
+FinalizeStub(JSFreeOp *fop, JSObject *obj)
+{
+}
+
+static JSClass XPCOutParamClass = {
+ "XPCOutParam",
+ 0,
+ JS_PropertyStub,
+ JS_DeletePropertyStub,
+ JS_PropertyStub,
+ JS_StrictPropertyStub,
+ JS_EnumerateStub,
+ JS_ResolveStub,
+ JS_ConvertStub,
+ FinalizeStub,
+ NULL, /* checkAccess */
+ NULL, /* call */
+ NULL, /* hasInstance */
+ NULL, /* construct */
+ NULL /* trace */
+};
+
+bool
+xpc::IsOutObject(JSContext* cx, JSObject* obj)
+{
+ return js::GetObjectJSClass(obj) == &XPCOutParamClass;
+}
+
JSObject*
-nsXPCWrappedJSClass::NewOutObject(JSContext* cx, JSObject* scope)
+xpc::NewOutObject(JSContext* cx, JSObject* scope)
{
return JS_NewObject(cx, nullptr, nullptr, JS_GetGlobalForObject(cx, scope));
}
NS_IMETHODIMP
nsXPCWrappedJSClass::DebugDump(int16_t depth)
{
--- a/js/xpconnect/src/xpc.msg
+++ b/js/xpconnect/src/xpc.msg
@@ -57,16 +57,17 @@ XPC_MSG_DEF(NS_ERROR_XPC_CANT_SET_READ_O
XPC_MSG_DEF(NS_ERROR_XPC_CANT_ADD_PROP_TO_WRAPPED_NATIVE, "Cannot add property to WrappedNative object")
XPC_MSG_DEF(NS_ERROR_XPC_CALL_TO_SCRIPTABLE_FAILED , "Call to nsIXPCScriptable interface for WrappedNative failed unexpecedly")
XPC_MSG_DEF(NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED , "JavaScript component does not have a method named:")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_ID_STRING , "Bad ID string")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_INITIALIZER_NAME , "Bad initializer name in Constructor - Component has no method with that name")
XPC_MSG_DEF(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN , "Operation failed because the XPConnect subsystem has been shutdown")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN , "Cannot modify properties of a WrappedNative")
XPC_MSG_DEF(NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL , "Could not convert JavaScript argument - 0 was passed, expected object. Did you mean null?")
+XPC_MSG_DEF(NS_ERROR_XPC_CANT_PASS_CPOW_TO_NATIVE , "It's illegal to pass a CPOW to native code")
/* common global codes (from nsError.h) */
XPC_MSG_DEF(NS_OK , "Success")
XPC_MSG_DEF(NS_ERROR_NOT_INITIALIZED , "Component not initialized")
XPC_MSG_DEF(NS_ERROR_ALREADY_INITIALIZED , "Component already initialized")
XPC_MSG_DEF(NS_ERROR_NOT_IMPLEMENTED , "Method not implemented")
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2703,18 +2703,16 @@ public:
const char * aPropertyName,
const char * anInterfaceName,
bool aForceReport);
private:
nsXPCWrappedJSClass(); // not implemented
nsXPCWrappedJSClass(JSContext* cx, REFNSIID aIID,
nsIInterfaceInfo* aInfo);
- JSObject* NewOutObject(JSContext* cx, JSObject* scope);
-
JSBool IsReflectable(uint16_t i) const
{return (JSBool)(mDescriptors[i/32] & (1 << (i%32)));}
void SetReflectable(uint16_t i, JSBool b)
{if (b) mDescriptors[i/32] |= (1 << (i%32));
else mDescriptors[i/32] &= ~(1 << (i%32));}
JSBool GetArraySizeFromParam(JSContext* cx,
const XPTMethodDescriptor* method,
@@ -3862,16 +3860,21 @@ inline XPCWrappedNativeScope*
GetObjectScope(JSObject *obj)
{
return EnsureCompartmentPrivate(obj)->scope;
}
extern JSBool gDebugMode;
extern JSBool gDesiredDebugMode;
+JSObject* NewOutObject(JSContext* cx, JSObject* scope);
+bool IsOutObject(JSContext* cx, JSObject* obj);
+
+nsresult HasInstance(JSContext *cx, JS::HandleObject objArg, const nsID *iid, bool *bp);
+
// Internal use only.
bool PushJSContext(JSContext *aCx);
void PopJSContext();
bool IsJSContextOnStack(JSContext *aCx);
} // namespace xpc
/***************************************************************************/
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -64,18 +64,16 @@
#include "mozilla/ipc/ProcessChild.h"
#include "ScopedXREEmbed.h"
#include "mozilla/plugins/PluginProcessChild.h"
#include "mozilla/dom/ContentProcess.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentChild.h"
-#include "mozilla/jsipc/ContextWrapperParent.h"
-
#include "mozilla/ipc/TestShellParent.h"
#include "mozilla/ipc/XPCShellEnvironment.h"
#include "GeckoProfiler.h"
#ifdef MOZ_IPDL_TESTS
#include "mozilla/_ipdltest/IPDLUnitTests.h"
#include "mozilla/_ipdltest/IPDLUnitTestProcessChild.h"
@@ -91,19 +89,16 @@ using mozilla::ipc::IOThreadChild;
using mozilla::ipc::ProcessChild;
using mozilla::ipc::ScopedXREEmbed;
using mozilla::plugins::PluginProcessChild;
using mozilla::dom::ContentProcess;
using mozilla::dom::ContentParent;
using mozilla::dom::ContentChild;
-using mozilla::jsipc::PContextWrapperParent;
-using mozilla::jsipc::ContextWrapperParent;
-
using mozilla::ipc::TestShellParent;
using mozilla::ipc::TestShellCommandParent;
using mozilla::ipc::XPCShellEnvironment;
using mozilla::startup::sChildProcessType;
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
@@ -759,23 +754,16 @@ XRE_SendTestShellCommand(JSContext* aCx,
JS::Value callbackVal = *reinterpret_cast<JS::Value*>(aCallback);
NS_ENSURE_TRUE(callback->SetCallback(aCx, callbackVal), false);
return true;
}
bool
-XRE_GetChildGlobalObject(JSContext* aCx, JSObject** aGlobalP)
-{
- TestShellParent* tsp = GetOrCreateTestShellParent();
- return tsp && tsp->GetGlobalJSObject(aCx, aGlobalP);
-}
-
-bool
XRE_ShutdownTestShell()
{
if (!gContentParent) {
return true;
}
bool ret = true;
if (gContentParent->IsAlive()) {
ret = gContentParent->DestroyTestShell(
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -459,17 +459,19 @@ CycleCollectedJSRuntime::CycleCollectedJ
, mExpectUnrootedGlobals(aExpectUnrootedGlobals)
#endif
{
mJSRuntime = JS_NewRuntime(aMaxbytes, aUseHelperThreads);
if (!mJSRuntime) {
MOZ_CRASH();
}
- JS_SetExtraGCRootsTracer(mJSRuntime, TraceBlackJS, this);
+ if (!JS_AddExtraGCRootsTracer(mJSRuntime, TraceBlackJS, this)) {
+ MOZ_CRASH();
+ }
JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this);
mJSHolders.Init(512);
nsCycleCollector_registerJSRuntime(this);
}
CycleCollectedJSRuntime::~CycleCollectedJSRuntime()
--- a/xpcom/base/ErrorList.h
+++ b/xpcom/base/ErrorList.h
@@ -587,16 +587,17 @@
ERROR(NS_ERROR_XPC_CANT_ADD_PROP_TO_WRAPPED_NATIVE, FAILURE(46)),
ERROR(NS_ERROR_XPC_CALL_TO_SCRIPTABLE_FAILED, FAILURE(47)),
ERROR(NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED, FAILURE(48)),
ERROR(NS_ERROR_XPC_BAD_ID_STRING, FAILURE(49)),
ERROR(NS_ERROR_XPC_BAD_INITIALIZER_NAME, FAILURE(50)),
ERROR(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, FAILURE(51)),
ERROR(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, FAILURE(52)),
ERROR(NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL, FAILURE(53)),
+ ERROR(NS_ERROR_XPC_CANT_PASS_CPOW_TO_NATIVE, FAILURE(54)),
/* any new errors here should have an associated entry added in xpc.msg */
ERROR(NS_SUCCESS_I_DID_SOMETHING, SUCCESS(1)),
/* Classes that want to only be touched by chrome (or from code whose
* filename begins with chrome://global/) shoudl return this from their
* scriptable helper's PreCreate hook. */
ERROR(NS_SUCCESS_CHROME_ACCESS_ONLY, SUCCESS(2)),
#undef MODULE
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -431,20 +431,16 @@ class JSString;
XRE_API(bool,
XRE_SendTestShellCommand, (JSContext* aCx,
JSString* aCommand,
void* aCallback))
class JSObject;
XRE_API(bool,
- XRE_GetChildGlobalObject, (JSContext* aCx,
- JSObject** globalp))
-
-XRE_API(bool,
XRE_ShutdownTestShell, ())
XRE_API(void,
XRE_InstallX11ErrorHandler, ())
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
#define XRE_HAS_DLL_BLOCKLIST
XRE_API(void,