--- a/dom/public/idl/threads/nsIDOMWorkers.idl
+++ b/dom/public/idl/threads/nsIDOMWorkers.idl
@@ -40,20 +40,20 @@
* From http://www.whatwg.org/specs/web-workers/current-work
*/
#include "nsIDOMEvent.idl"
#include "nsIDOMEventTarget.idl"
interface nsIDOMEventListener;
-[scriptable, uuid(6c32d0c5-6bfa-438b-ad44-be0df80cd4a8)]
+[scriptable, uuid(ab3725b8-3fca-40cc-a42c-92fb154ef01d)]
interface nsIWorkerMessagePort : nsISupports
{
- void postMessage(in DOMString aMessage);
+ void postMessage(/* in JSObject aMessage */);
};
[scriptable, uuid(508f2d49-e9a0-4fe8-bd33-321820173b4a)]
interface nsIWorkerMessageEvent : nsIDOMEvent
{
readonly attribute DOMString data;
readonly attribute DOMString origin;
@@ -78,33 +78,31 @@ interface nsIWorkerNavigator : nsISuppor
[scriptable, uuid(a41ac154-ba18-4926-8954-cd6973ea490e)]
interface nsIWorkerGlobalScope : nsISupports
{
readonly attribute nsIWorkerGlobalScope self;
readonly attribute nsIWorkerNavigator navigator;
};
-[scriptable, uuid(b10cfe72-91b9-45c6-ab13-33f89c2d0e56)]
+[scriptable, uuid(d30a2f61-86e2-434e-837f-4f1985efa865)]
interface nsIWorkerScope : nsIWorkerGlobalScope
{
- void postMessage(in DOMString aMessage,
- [optional] in nsIWorkerMessagePort aMessagePort);
+ void postMessage(/* in JSObject aMessage */);
attribute nsIDOMEventListener onmessage;
};
[scriptable, uuid(b90b7561-b5e2-4545-84b0-280dbaaa94ea)]
interface nsIAbstractWorker : nsIDOMEventTarget
{
attribute nsIDOMEventListener onerror;
};
-[scriptable, uuid(3d2ca558-31f7-4893-aa6d-1db9a3cb5bb9)]
+[scriptable, uuid(daf945c3-8d29-4724-8939-dd383f7d27a7)]
interface nsIWorker : nsIAbstractWorker
{
- void postMessage(in DOMString aMessage,
- [optional] in nsIWorkerMessagePort aMessagePort);
+ void postMessage(/* in JSObject aMessage */);
attribute nsIDOMEventListener onmessage;
void terminate();
};
--- a/dom/src/threads/Makefile.in
+++ b/dom/src/threads/Makefile.in
@@ -56,16 +56,17 @@ REQUIRES = \
js \
layout \
locale \
necko \
plugin \
pref \
string \
thebes \
+ uconv \
widget \
xpcom \
xpconnect \
$(NULL)
CPPSRCS = \
nsDOMThreadService.cpp \
nsDOMWorker.cpp \
@@ -77,16 +78,17 @@ CPPSRCS = \
nsDOMWorkerSecurityManager.cpp \
nsDOMWorkerTimeout.cpp \
nsDOMWorkerXHR.cpp \
nsDOMWorkerXHRProxy.cpp \
$(NULL)
LOCAL_INCLUDES = \
-I$(topsrcdir)/dom/src/base \
+ -I$(topsrcdir)/dom/src/json \
-I$(topsrcdir)/content/base/src \
-I$(topsrcdir)/content/events/src \
$(NULL)
ifdef ENABLE_TESTS
DIRS += test
endif
--- a/dom/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -42,19 +42,21 @@
#include "nsIEventTarget.h"
#include "nsIJSRuntimeService.h"
#include "nsIXPConnect.h"
#ifdef MOZ_SHARK
#include "jsdbgapi.h"
#endif
#include "nsAutoLock.h"
+#include "nsAXPCNativeCallContext.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfoID.h"
#include "nsGlobalWindow.h"
+#include "nsJSON.h"
#include "nsJSUtils.h"
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
#include "nsDOMThreadService.h"
#include "nsDOMWorkerEvents.h"
#include "nsDOMWorkerNavigator.h"
#include "nsDOMWorkerPool.h"
@@ -408,16 +410,123 @@ JSFunctionSpec gDOMWorkerFunctions[] = {
{ "startShark", js_StartShark, 0, 0, 0 },
{ "stopShark", js_StopShark, 0, 0, 0 },
{ "connectShark", js_ConnectShark, 0, 0, 0 },
{ "disconnectShark", js_DisconnectShark, 0, 0, 0 },
#endif
{ nsnull, nsnull, 0, 0, 0 }
};
+static JSBool
+WriteCallback(const jschar* aBuffer,
+ uint32 aLength,
+ void* aData)
+{
+ nsJSONWriter* writer = static_cast<nsJSONWriter*>(aData);
+
+ nsresult rv = writer->Write((const PRUnichar*)aBuffer, (PRUint32)aLength);
+ return NS_SUCCEEDED(rv) ? JS_TRUE : JS_FALSE;
+}
+
+static nsresult
+GetStringForArgument(nsAString& aString,
+ PRBool* aIsJSON,
+ PRBool* aIsPrimitive)
+{
+ NS_ASSERTION(aIsJSON && aIsPrimitive, "Null pointer!");
+
+ nsIXPConnect* xpc = nsContentUtils::XPConnect();
+ NS_ENSURE_TRUE(xpc, NS_ERROR_UNEXPECTED);
+
+ nsAXPCNativeCallContext* cc;
+ nsresult rv = xpc->GetCurrentNativeCallContext(&cc);
+ NS_ENSURE_SUCCESS(rv, rv);
+ NS_ENSURE_TRUE(cc, NS_ERROR_UNEXPECTED);
+
+ PRUint32 argc;
+ rv = cc->GetArgc(&argc);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (!argc) {
+ return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
+ }
+
+ jsval* argv;
+ rv = cc->GetArgvPtr(&argv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ JSContext* cx;
+ rv = cc->GetJSContext(&cx);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ JSAutoRequest ar(cx);
+
+ if (JSVAL_IS_STRING(argv[0])) {
+ aString.Assign(nsDependentJSString(JSVAL_TO_STRING(argv[0])));
+ *aIsJSON = *aIsPrimitive = PR_FALSE;
+ return NS_OK;
+ }
+
+ nsAutoJSValHolder jsonVal;
+
+ JSBool ok = jsonVal.Hold(cx);
+ NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
+
+ if (JSVAL_IS_PRIMITIVE(argv[0])) {
+ // Only objects can be serialized through JSON, currently, so if we've been
+ // given a primitive we set it as a property on a dummy object before
+ // sending it to the serializer.
+ JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
+ NS_ENSURE_TRUE(obj, NS_ERROR_OUT_OF_MEMORY);
+
+ jsonVal = obj;
+
+ ok = JS_DefineProperty(cx, obj, JSON_PRIMITIVE_PROPNAME, argv[0], NULL,
+ NULL, JSPROP_ENUMERATE);
+ NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
+
+ *aIsPrimitive = PR_TRUE;
+ }
+ else {
+ jsonVal = argv[0];
+
+ *aIsPrimitive = PR_FALSE;
+ }
+
+ JSType type;
+ jsval* vp = jsonVal.ToJSValPtr();
+
+ // This may change vp if there is a 'toJSON' function on the object.
+ ok = JS_TryJSON(cx, vp);
+ if (!(ok && !JSVAL_IS_PRIMITIVE(*vp) &&
+ (type = JS_TypeOfValue(cx, *vp)) != JSTYPE_FUNCTION &&
+ type != JSTYPE_XML)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // Make sure to hold the new vp in case it changed.
+ jsonVal = *vp;
+
+ nsJSONWriter writer;
+
+ ok = JS_Stringify(cx, jsonVal.ToJSValPtr(), NULL, &WriteCallback, &writer);
+ if (!ok) {
+ return NS_ERROR_XPC_BAD_CONVERT_JS;
+ }
+
+ NS_ENSURE_TRUE(writer.DidWrite(), NS_ERROR_UNEXPECTED);
+
+ writer.FlushBuffer();
+
+ aString.Assign(writer.mOutputString);
+ *aIsJSON = PR_TRUE;
+
+ return NS_OK;
+}
+
class nsDOMWorkerScope : public nsIWorkerScope,
public nsIDOMEventTarget,
public nsIXPCScriptable,
public nsIClassInfo
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIWORKERGLOBALSCOPE
@@ -504,30 +613,31 @@ nsDOMWorkerScope::GetNavigator(nsIWorker
NS_ENSURE_TRUE(mNavigator, NS_ERROR_OUT_OF_MEMORY);
}
NS_ADDREF(*_retval = mNavigator);
return NS_OK;
}
NS_IMETHODIMP
-nsDOMWorkerScope::PostMessage(const nsAString& aMessage,
- nsIWorkerMessagePort* aMessagePort)
+nsDOMWorkerScope::PostMessage(/* JSObject aMessage */)
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
if (mWorker->IsCanceled()) {
return NS_ERROR_ABORT;
}
- if (aMessagePort) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
+ nsString message;
+ PRBool isJSON, isPrimitive;
- return mWorker->PostMessageInternal(aMessage, PR_FALSE);
+ nsresult rv = GetStringForArgument(message, &isJSON, &isPrimitive);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return mWorker->PostMessageInternal(message, isJSON, isPrimitive, PR_FALSE);
}
NS_IMETHODIMP
nsDOMWorkerScope::GetOnmessage(nsIDOMEventListener** aOnmessage)
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
NS_ENSURE_ARG_POINTER(aOnmessage);
@@ -1001,26 +1111,30 @@ nsDOMWorker::Resume()
NS_ASSERTION(mSuspended, "Not suspended!");
mSuspended = PR_FALSE;
ResumeFeatures();
}
nsresult
nsDOMWorker::PostMessageInternal(const nsAString& aMessage,
+ PRBool aIsJSON,
+ PRBool aIsPrimitive,
PRBool aToInner)
{
nsRefPtr<nsDOMWorkerMessageEvent> message = new nsDOMWorkerMessageEvent();
NS_ENSURE_TRUE(message, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = message->InitMessageEvent(NS_LITERAL_STRING("message"),
PR_FALSE, PR_FALSE, aMessage,
EmptyString(), nsnull);
NS_ENSURE_SUCCESS(rv, rv);
+ message->SetJSONData(aIsJSON, aIsPrimitive);
+
nsRefPtr<nsDOMFireEventRunnable> runnable =
new nsDOMFireEventRunnable(this, message, aToInner);
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
// If aToInner is true then we want to target the runnable at this worker's
// thread. Otherwise we need to target the parent's thread.
nsDOMWorker* target = aToInner ? this : mParent;
@@ -1319,28 +1433,29 @@ nsDOMWorker::GetParent()
nsRefPtr<nsDOMWorker> parent(mParent);
return parent.forget();
}
/**
* See nsIWorker
*/
NS_IMETHODIMP
-nsDOMWorker::PostMessage(const nsAString& aMessage,
- nsIWorkerMessagePort* aMessagePort)
+nsDOMWorker::PostMessage(/* JSObject aMessage */)
{
if (mTerminated) {
return NS_OK;
}
- if (aMessagePort) {
- return NS_ERROR_NOT_IMPLEMENTED;
- }
+ nsString message;
+ PRBool isJSON, isPrimitive;
- return PostMessageInternal(aMessage, PR_TRUE);
+ nsresult rv = GetStringForArgument(message, &isJSON, &isPrimitive);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return PostMessageInternal(message, isJSON, isPrimitive, PR_TRUE);
}
/**
* See nsIWorker
*/
NS_IMETHODIMP
nsDOMWorker::GetOnerror(nsIDOMEventListener** aOnerror)
{
--- a/dom/src/threads/nsDOMWorker.h
+++ b/dom/src/threads/nsDOMWorker.h
@@ -143,16 +143,18 @@ public:
nsDOMWorkerScope* GetInnerScope() {
return mInnerScope;
}
private:
~nsDOMWorker();
nsresult PostMessageInternal(const nsAString& aMessage,
+ PRBool aIsJSON,
+ PRBool aIsPrimitive,
PRBool aToInner);
PRBool CompileGlobalObject(JSContext* aCx);
PRUint32 NextTimeoutId() {
return mNextTimeoutId++;
}
--- a/dom/src/threads/nsDOMWorkerEvents.cpp
+++ b/dom/src/threads/nsDOMWorkerEvents.cpp
@@ -34,17 +34,20 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDOMWorkerEvents.h"
#include "nsIXMLHttpRequest.h"
+#include "nsIXPConnect.h"
+#include "nsAXPCNativeCallContext.h"
+#include "nsContentUtils.h"
#include "nsThreadUtils.h"
#include "nsDOMWorkerMessageHandler.h"
#include "nsDOMWorkerXHR.h"
#include "nsDOMWorkerXHRProxy.h"
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDOMWorkerPrivateEvent,
NS_IDOMWORKERPRIVATEEVENT_IID)
@@ -235,18 +238,80 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsDOMWorker
NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerMessageEvent, nsIDOMEvent,
nsIWorkerMessageEvent)
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerMessageEvent)
NS_IMETHODIMP
nsDOMWorkerMessageEvent::GetData(nsAString& aData)
{
- aData.Assign(mData);
- return NS_OK;
+ if (!mIsJSON) {
+ aData.Assign(mData);
+ return NS_OK;
+ }
+
+ nsIXPConnect* xpc = nsContentUtils::XPConnect();
+ NS_ENSURE_TRUE(xpc, NS_ERROR_UNEXPECTED);
+
+ nsAXPCNativeCallContext* cc;
+ nsresult rv = xpc->GetCurrentNativeCallContext(&cc);
+ NS_ENSURE_SUCCESS(rv, rv);
+ NS_ENSURE_TRUE(cc, NS_ERROR_UNEXPECTED);
+
+ jsval* retval;
+ rv = cc->GetRetValPtr(&retval);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (mCachedJSVal) {
+ *retval = mCachedJSVal;
+ return cc->SetReturnValueWasSet(PR_TRUE);
+ }
+
+ JSContext* cx;
+ rv = cc->GetJSContext(&cx);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ JSAutoRequest ar(cx);
+
+ JSBool ok = mCachedJSVal.Hold(cx);
+ NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
+
+ JSONParser* parser = JS_BeginJSONParse(cx, mCachedJSVal.ToJSValPtr());
+ NS_ENSURE_TRUE(parser, NS_ERROR_UNEXPECTED);
+
+ // This is slightly sneaky, but now that JS_BeginJSONParse succeeded we always
+ // need call JS_FinishJSONParse even if JS_ConsumeJSONText fails. We'll report
+ // an error if either failed, though.
+ ok = JS_ConsumeJSONText(cx, parser, (jschar*)mData.get(),
+ (uint32)mData.Length());
+
+ // Note the '&& ok' after the call here!
+ ok = JS_FinishJSONParse(cx, parser) && ok;
+ if (!ok) {
+ mCachedJSVal = JSVAL_NULL;
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ NS_ASSERTION(mCachedJSVal.ToJSObject(), "Bad JSON result!");
+
+ if (mIsPrimitive) {
+ jsval primitive;
+
+ ok = JS_GetProperty(cx, mCachedJSVal.ToJSObject(), JSON_PRIMITIVE_PROPNAME,
+ &primitive);
+ if (!ok) {
+ mCachedJSVal = JSVAL_NULL;
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ mCachedJSVal = primitive;
+ }
+
+ *retval = mCachedJSVal;
+ return cc->SetReturnValueWasSet(PR_TRUE);
}
NS_IMETHODIMP
nsDOMWorkerMessageEvent::GetOrigin(nsAString& aOrigin)
{
aOrigin.Assign(mOrigin);
return NS_OK;
}
--- a/dom/src/threads/nsDOMWorkerEvents.h
+++ b/dom/src/threads/nsDOMWorkerEvents.h
@@ -41,16 +41,18 @@
#include "nsIClassInfo.h"
#include "nsIDOMEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMProgressEvent.h"
#include "nsIDOMWorkers.h"
#include "nsIRunnable.h"
+#include "jsapi.h"
+#include "nsAutoJSValHolder.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsStringGlue.h"
#include "nsDOMWorkerMacros.h"
class nsDOMWorkerXHRProxy;
class nsIXMLHttpRequest;
@@ -181,18 +183,30 @@ class nsDOMWorkerMessageEvent : public n
public nsIWorkerMessageEvent
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_NSIDOMEVENT(nsDOMWorkerEvent::)
NS_DECL_NSIWORKERMESSAGEEVENT
NS_DECL_NSICLASSINFO_GETINTERFACES
+ nsDOMWorkerMessageEvent()
+ : mIsJSON(PR_FALSE), mIsPrimitive(PR_FALSE) { }
+
+ void SetJSONData(PRBool aIsJSON, PRBool aIsPrimitive) {
+ mIsJSON = aIsJSON;
+ mIsPrimitive = aIsPrimitive;
+ }
+
protected:
nsString mData;
+ PRBool mIsJSON;
+ PRBool mIsPrimitive;
+ nsAutoJSValHolder mCachedJSVal;
+
nsString mOrigin;
nsCOMPtr<nsISupports> mSource;
};
class nsDOMWorkerProgressEvent : public nsDOMWorkerEvent,
public nsIDOMProgressEvent
{
public:
--- a/dom/src/threads/nsDOMWorkerMacros.h
+++ b/dom/src/threads/nsDOMWorkerMacros.h
@@ -124,9 +124,12 @@ NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(_
// Don't know why nsISupports.idl defines this out...
#define NS_FORWARD_NSISUPPORTS(_to) \
NS_IMETHOD QueryInterface(const nsIID& uuid, void** result) { \
return _to QueryInterface(uuid, result); \
} \
NS_IMETHOD_(nsrefcnt) AddRef(void) { return _to AddRef(); } \
NS_IMETHOD_(nsrefcnt) Release(void) { return _to Release(); }
+#define JSON_PRIMITIVE_PROPNAME \
+ "primitive"
+
#endif /* __NSDOMWORKERMACROS_H__ */
--- a/dom/src/threads/test/Makefile.in
+++ b/dom/src/threads/test/Makefile.in
@@ -51,16 +51,18 @@ include $(topsrcdir)/config/rules.mk
errorPropagation_worker1.js \
errorPropagation_worker2.js \
test_importScripts.html \
importScripts_worker.js \
importScripts_worker_imported1.js \
importScripts_worker_imported2.js \
importScripts_worker_imported3.js \
importScripts_worker_imported4.js \
+ test_json.html \
+ json_worker.js \
test_longThread.html \
longThread_worker.js \
test_navigator.html \
navigator_worker.js \
test_recursion.html \
recursion_worker.js \
test_regExpStatics.html \
regExpStatics_worker.js \
new file mode 100644
--- /dev/null
+++ b/dom/src/threads/test/json_worker.js
@@ -0,0 +1,203 @@
+var messages = [
+ {
+ type: "object",
+ array: false,
+ exception: false,
+ shouldCompare: false,
+ shouldEqual: false,
+ value: { foo: "bar" }
+ },
+ {
+ type: "object",
+ array: true,
+ exception: false,
+ shouldCompare: false,
+ shouldEqual: false,
+ value: [9, 8, 7]
+ },
+ {
+ type: "object",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: null
+ },
+ {
+ type: "undefined",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: undefined,
+ compareValue: undefined
+ },
+ {
+ type: "string",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: "Hello"
+ },
+ {
+ type: "string",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: JSON.stringify({ foo: "bar" })
+ },
+ {
+ type: "number",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: 1
+ },
+ {
+ type: "number",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: 0
+ },
+ {
+ type: "number",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: -1
+ },
+ {
+ type: "number",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: 238573459843702923492399923049
+ },
+ {
+ type: "number",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: -238573459843702923492399923049
+ },
+ {
+ type: "number",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: 0.25
+ },
+ {
+ type: "number",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: -0.25
+ },
+ {
+ type: "boolean",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: true
+ },
+ {
+ type: "boolean",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: false
+ },
+
+ /*
+ // Uncomment these once bug 465371 is fixed!
+ {
+ type: "function",
+ array: false,
+ exception: true,
+ shouldCompare: false,
+ shouldEqual: false,
+ value: function (foo) { return "Bad!"; }
+ },
+ {
+ type: "xml",
+ array: false,
+ exception: true,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: <funtimes></funtimes>
+ },
+ */
+ {
+ type: "object",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: NaN,
+ compareValue: null
+ },
+ {
+ type: "object",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: Infinity,
+ compareValue: null
+ },
+ {
+ type: "object",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: -Infinity,
+ compareValue: null
+ },
+ {
+ type: "string",
+ array: false,
+ exception: false,
+ shouldCompare: true,
+ shouldEqual: true,
+ value: "testFinished"
+ }
+];
+
+for (var index = 0; index < messages.length; index++) {
+ var message = messages[index];
+ if (message.hasOwnProperty("compareValue")) {
+ continue;
+ }
+ message.compareValue = message.value;
+}
+
+var onmessage = function(event) {
+ for (var index = 0; index < messages.length; index++) {
+ var exception = false;
+
+ try {
+ postMessage(messages[index].value);
+ }
+ catch (e) {
+ exception = true;
+ }
+
+ if (messages[index].exception != exception) {
+ throw "Exception inconsistency!";
+ }
+ }
+}
new file mode 100644
--- /dev/null
+++ b/dom/src/threads/test/test_json.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker JSON messages
+-->
+<head>
+ <title>Test for DOM Worker Navigator</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script src="json_worker.js" language="javascript"></script>
+<script class="testbody" language="javascript">
+
+ ok(messages.length, "No messages to test!");
+
+ var worker = new Worker("json_worker.js");
+
+ var index = 0;
+ worker.onmessage = function(event) {
+ var key = messages[index++];
+
+ // Loop for the ones we shouldn't receive.
+ while (key.exception) {
+ key = messages[index++];
+ }
+
+ is(typeof event.data, key.type,
+ "Bad type! " + messages.indexOf(key));
+ is(event.data instanceof Array, key.array,
+ "Array mismatch! " + messages.indexOf(key));
+
+ if (key.shouldCompare) {
+ ok(event.data == key.compareValue,
+ "Values don't compare! " + messages.indexOf(key));
+ }
+
+ if (key.shouldEqual) {
+ ok(event.data === key.compareValue,
+ "Values don't equal!" + messages.indexOf(key));
+ }
+
+ if (event.data == "testFinished") {
+ is(index, messages.length, "Didn't see the right number of messages!");
+ SimpleTest.finish();
+ }
+ };
+
+ worker.onerror = function(event) {
+ ok(false, "Worker had an error: " + event.data);
+ SimpleTest.finish();
+ }
+
+ worker.postMessage("start");
+
+ SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/src/threads/test/test_xhrAbort.html
+++ b/dom/src/threads/test/test_xhrAbort.html
@@ -19,17 +19,17 @@ Tests of DOM Worker Threads XHR(Bug 4504
<script language="javascript" src="xhrAbort_worker.js"></script>
<script class="testbody" language="javascript">
function postMessage(data) {
var worker = new Worker("xhrAbort_worker.js");
worker.onmessage = function(event) {
- is (data, event.data, "Got different results!");
+ is (data.toString(), event.data.toString(), "Got different results!");
SimpleTest.finish();
};
worker.onerror = function(event) {
ok(false, "Worker had an error: " + event.data);
SimpleTest.finish();
}
--- a/js/src/xpconnect/public/nsAutoJSValHolder.h
+++ b/js/src/xpconnect/public/nsAutoJSValHolder.h
@@ -122,16 +122,20 @@ public:
* Explicit JSObject* conversion.
*/
JSObject* ToJSObject() const {
return JSVAL_IS_OBJECT(mVal)
? JSVAL_TO_OBJECT(mVal)
: NULL;
}
+ jsval* ToJSValPtr() {
+ return &mVal;
+ }
+
/**
* Pretend to be a jsval.
*/
operator jsval() const { return mVal; }
nsAutoJSValHolder &operator=(JSObject* aOther) {
#ifdef DEBUG
if (aOther) {