зеркало из https://github.com/mozilla/gecko-dev.git
Bug 550275 - 'Implement the HTML5 structured clone algorithm'. Make Web Workers use the new clones. r=jst
This commit is contained in:
Родитель
e47beee477
Коммит
f8db2a1523
|
@ -128,16 +128,6 @@ static const char* sPrefsToWatch[] = {
|
|||
// The length of time the close handler is allowed to run in milliseconds.
|
||||
static PRUint32 gWorkerCloseHandlerTimeoutMS = 10000;
|
||||
|
||||
static int sStringFinalizerIndex = -1;
|
||||
|
||||
static void
|
||||
StringFinalizer(JSContext* aCx,
|
||||
JSString* aStr)
|
||||
{
|
||||
NS_ASSERTION(aStr, "Null string!");
|
||||
nsStringBuffer::FromData(JS_GetStringChars(aStr))->Release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple class to automatically destroy a JSContext to make error handling
|
||||
* easier.
|
||||
|
@ -720,7 +710,6 @@ nsDOMThreadService::Init()
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(!gDOMThreadService, "Only one instance should ever be created!");
|
||||
NS_ASSERTION(sStringFinalizerIndex == -1, "String finalizer already set!");
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
|
@ -732,9 +721,6 @@ nsDOMThreadService::Init()
|
|||
|
||||
obs.forget(&gObserverService);
|
||||
|
||||
sStringFinalizerIndex = JS_AddExternalStringFinalizer(StringFinalizer);
|
||||
NS_ENSURE_TRUE(sStringFinalizerIndex != -1, NS_ERROR_FAILURE);
|
||||
|
||||
RegisterPrefCallbacks();
|
||||
|
||||
mThreadPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID, &rv);
|
||||
|
@ -1249,38 +1235,6 @@ nsDOMThreadService::WorkerSecurityManager()
|
|||
return gWorkerSecurityManager;
|
||||
}
|
||||
|
||||
// static
|
||||
jsval
|
||||
nsDOMThreadService::ShareStringAsJSVal(JSContext* aCx,
|
||||
const nsAString& aString)
|
||||
{
|
||||
NS_ASSERTION(sStringFinalizerIndex != -1, "Bad index!");
|
||||
NS_ASSERTION(aCx, "Null context!");
|
||||
|
||||
PRUint32 length = aString.Length();
|
||||
if (!length) {
|
||||
JSAtom* atom = aCx->runtime->atomState.emptyAtom;
|
||||
return ATOM_KEY(atom);
|
||||
}
|
||||
|
||||
nsStringBuffer* buf = nsStringBuffer::FromString(aString);
|
||||
if (!buf) {
|
||||
NS_WARNING("Can't share this string buffer!");
|
||||
return JSVAL_VOID;
|
||||
}
|
||||
|
||||
JSString* str =
|
||||
JS_NewExternalString(aCx, reinterpret_cast<jschar*>(buf->Data()), length,
|
||||
sStringFinalizerIndex);
|
||||
if (str) {
|
||||
buf->AddRef();
|
||||
return STRING_TO_JSVAL(str);
|
||||
}
|
||||
|
||||
NS_WARNING("JS_NewExternalString failed!");
|
||||
return JSVAL_VOID;
|
||||
}
|
||||
|
||||
/**
|
||||
* See nsIEventTarget
|
||||
*/
|
||||
|
|
|
@ -108,9 +108,6 @@ public:
|
|||
static nsIThreadJSContextStack* ThreadJSContextStack();
|
||||
static nsIXPCSecurityManager* WorkerSecurityManager();
|
||||
|
||||
static jsval ShareStringAsJSVal(JSContext* aCx,
|
||||
const nsAString& aString);
|
||||
|
||||
void CancelWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
|
||||
void SuspendWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
|
||||
void ResumeWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
|
||||
|
|
|
@ -401,105 +401,6 @@ JSFunctionSpec gDOMWorkerFunctions[] = {
|
|||
{ 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(JSContext* aCx,
|
||||
jsval aVal,
|
||||
PRBool* aIsJSON,
|
||||
PRBool* aIsPrimitive,
|
||||
nsAutoJSValHolder& _retval)
|
||||
{
|
||||
NS_ASSERTION(aIsJSON && aIsPrimitive, "Null pointer!");
|
||||
|
||||
if (JSVAL_IS_STRING(aVal)) {
|
||||
if (!JS_MakeStringImmutable(aCx, JSVAL_TO_STRING(aVal))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aIsJSON = *aIsPrimitive = PR_FALSE;
|
||||
_retval = aVal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoJSValHolder jsonVal;
|
||||
|
||||
JSBool ok = jsonVal.Hold(aCx);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(aVal)) {
|
||||
// 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(aCx, NULL, NULL, NULL);
|
||||
NS_ENSURE_TRUE(obj, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
jsonVal = obj;
|
||||
|
||||
ok = JS_DefineProperty(aCx, obj, JSON_PRIMITIVE_PROPNAME, aVal, NULL,
|
||||
NULL, JSPROP_ENUMERATE);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
|
||||
|
||||
*aIsPrimitive = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
jsonVal = aVal;
|
||||
|
||||
*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(aCx, vp);
|
||||
if (!(ok && !JSVAL_IS_PRIMITIVE(*vp) &&
|
||||
(type = JS_TypeOfValue(aCx, *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(aCx, jsonVal.ToJSValPtr(), NULL, JSVAL_NULL, WriteCallback,
|
||||
&writer);
|
||||
if (!ok) {
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(writer.DidWrite(), NS_ERROR_UNEXPECTED);
|
||||
|
||||
writer.FlushBuffer();
|
||||
|
||||
_retval = nsDOMThreadService::ShareStringAsJSVal(aCx, writer.mOutputString);
|
||||
if (!JSVAL_IS_STRING(_retval)) {
|
||||
// Yuck, we can't share.
|
||||
const jschar* buf =
|
||||
reinterpret_cast<const jschar*>(writer.mOutputString.get());
|
||||
JSString* str = JS_NewUCStringCopyN(aCx, buf, writer.mOutputString.Length());
|
||||
if (!str) {
|
||||
JS_ReportOutOfMemory(aCx);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
_retval = STRING_TO_JSVAL(str);
|
||||
}
|
||||
|
||||
*aIsJSON = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDOMWorkerScope::nsDOMWorkerScope(nsDOMWorker* aWorker)
|
||||
: mWorker(aWorker),
|
||||
mWrappedNative(nsnull),
|
||||
|
@ -1506,11 +1407,10 @@ nsDOMWorker::PostMessageInternal(PRBool aToInner)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRBool isJSON, isPrimitive;
|
||||
rv = GetStringForArgument(cx, argv[0], &isJSON, &isPrimitive, val);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(JSVAL_IS_STRING(val), "Bad jsval!");
|
||||
rv = nsContentUtils::CreateStructuredClone(cx, argv[0], val.ToJSValPtr());
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMWorkerMessageEvent> message = new nsDOMWorkerMessageEvent();
|
||||
NS_ENSURE_TRUE(message, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -1520,7 +1420,7 @@ nsDOMWorker::PostMessageInternal(PRBool aToInner)
|
|||
nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = message->SetJSONData(cx, val, isJSON, isPrimitive);
|
||||
rv = message->SetJSVal(cx, val);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<nsDOMFireEventRunnable> runnable =
|
||||
|
|
|
@ -264,16 +264,9 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsDOMWorkerMessageEvent, nsIDOMEvent,
|
|||
NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerMessageEvent)
|
||||
|
||||
nsresult
|
||||
nsDOMWorkerMessageEvent::SetJSONData(JSContext* aCx,
|
||||
jsval aData,
|
||||
PRBool aIsJSON,
|
||||
PRBool aIsPrimitive)
|
||||
nsDOMWorkerMessageEvent::SetJSVal(JSContext* aCx,
|
||||
jsval aData)
|
||||
{
|
||||
NS_ASSERTION(JSVAL_IS_STRING(aData), "Bad jsval!");
|
||||
|
||||
mIsJSON = aIsJSON ? PR_TRUE : PR_FALSE;
|
||||
mIsPrimitive = aIsPrimitive ? PR_TRUE : PR_FALSE;
|
||||
|
||||
if (!mDataVal.Hold(aCx)) {
|
||||
NS_WARNING("Failed to hold jsval!");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -294,80 +287,27 @@ nsDOMWorkerMessageEvent::GetData(nsAString& aData)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(cc, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (!mDataValWasReparented) {
|
||||
if (JSVAL_IS_OBJECT(mDataVal) && !JSVAL_IS_NULL(mDataVal)) {
|
||||
JSContext* cx;
|
||||
rv = cc->GetJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv =
|
||||
nsContentUtils::ReparentClonedObjectToScope(cx,
|
||||
JSVAL_TO_OBJECT(mDataVal),
|
||||
JS_GetGlobalObject(cx));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mDataValWasReparented = PR_TRUE;
|
||||
}
|
||||
|
||||
jsval* retval;
|
||||
rv = cc->GetRetValPtr(&retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mIsJSON) {
|
||||
cc->SetReturnValueWasSet(PR_TRUE);
|
||||
*retval = mDataVal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mHaveCachedJSVal) {
|
||||
cc->SetReturnValueWasSet(PR_TRUE);
|
||||
*retval = mCachedJSVal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mHaveAttemptedConversion) {
|
||||
// Don't try to convert again if the first time around we saw an error.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mHaveAttemptedConversion = 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);
|
||||
|
||||
NS_ASSERTION(JSVAL_IS_STRING(mDataVal), "Bad jsval!");
|
||||
JSString* str = JSVAL_TO_STRING(mDataVal);
|
||||
|
||||
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, JS_GetStringChars(str),
|
||||
JS_GetStringLength(str));
|
||||
|
||||
// Note the '&& ok' after the call here!
|
||||
ok = JS_FinishJSONParse(cx, parser, JSVAL_NULL) && 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;
|
||||
}
|
||||
|
||||
// We no longer need to hold this copy of the data around.
|
||||
mDataVal.Release();
|
||||
|
||||
// Now that everything has succeeded we'll set this flag so that we return the
|
||||
// cached jsval in the future.
|
||||
mHaveCachedJSVal = PR_TRUE;
|
||||
|
||||
*retval = mCachedJSVal;
|
||||
cc->SetReturnValueWasSet(PR_TRUE);
|
||||
*retval = mDataVal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -210,26 +210,17 @@ public:
|
|||
NS_DECL_NSIWORKERMESSAGEEVENT
|
||||
NS_DECL_NSICLASSINFO_GETINTERFACES
|
||||
|
||||
nsDOMWorkerMessageEvent()
|
||||
: mIsJSON(PR_FALSE), mIsPrimitive(PR_FALSE), mHaveCachedJSVal(PR_FALSE),
|
||||
mHaveAttemptedConversion(PR_FALSE) { }
|
||||
nsDOMWorkerMessageEvent() : mDataValWasReparented(PR_FALSE) { }
|
||||
|
||||
nsresult SetJSONData(JSContext* aCx,
|
||||
jsval aData,
|
||||
PRBool aIsJSON,
|
||||
PRBool aIsPrimitive);
|
||||
nsresult SetJSVal(JSContext* aCx,
|
||||
jsval aData);
|
||||
|
||||
protected:
|
||||
nsString mOrigin;
|
||||
nsCOMPtr<nsISupports> mSource;
|
||||
|
||||
nsAutoJSValHolder mDataVal;
|
||||
nsAutoJSValHolder mCachedJSVal;
|
||||
|
||||
PRPackedBool mIsJSON;
|
||||
PRPackedBool mIsPrimitive;
|
||||
PRPackedBool mHaveCachedJSVal;
|
||||
PRPackedBool mHaveAttemptedConversion;
|
||||
PRBool mDataValWasReparented;
|
||||
};
|
||||
|
||||
class nsDOMWorkerProgressEvent : public nsDOMWorkerEvent,
|
||||
|
|
|
@ -1,177 +1,212 @@
|
|||
var cyclicalObject = {};
|
||||
cyclicalObject.foo = cyclicalObject;
|
||||
|
||||
var cyclicalArray = [];
|
||||
cyclicalArray.push(cyclicalArray);
|
||||
|
||||
function makeCrazyNested(obj, count) {
|
||||
var innermostobj;
|
||||
for (var i = 0; i < count; i++) {
|
||||
obj.foo = { bar: 5 }
|
||||
innermostobj = obj.foo;
|
||||
obj = innermostobj;
|
||||
}
|
||||
return innermostobj;
|
||||
}
|
||||
|
||||
var crazyNestedObject = {};
|
||||
makeCrazyNested(crazyNestedObject, 100);
|
||||
|
||||
var crazyCyclicalObject = {};
|
||||
var innermost = makeCrazyNested(crazyCyclicalObject, 1000);
|
||||
innermost.baz = crazyCyclicalObject;
|
||||
|
||||
var objectWithSaneGetter = { };
|
||||
objectWithSaneGetter.__defineGetter__("foo", function() { return 5; });
|
||||
|
||||
// We don't walk prototype chains for cloning so this won't actually do much...
|
||||
function objectWithSaneGetter2() { }
|
||||
objectWithSaneGetter2.prototype = {
|
||||
get foo() {
|
||||
return 5;
|
||||
}
|
||||
};
|
||||
|
||||
var objectWithThrowingGetter = { };
|
||||
objectWithThrowingGetter.__defineGetter__("foo", function() { throw "bad"; });
|
||||
|
||||
var messages = [
|
||||
{
|
||||
type: "object",
|
||||
array: false,
|
||||
exception: false,
|
||||
shouldCompare: false,
|
||||
shouldEqual: false,
|
||||
value: { foo: "bar" }
|
||||
value: { },
|
||||
jsonValue: '{}'
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: {foo: "bar"},
|
||||
jsonValue: '{"foo":"bar"}'
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: {foo: "bar", foo2: {bee: "bop"}},
|
||||
jsonValue: '{"foo":"bar","foo2":{"bee":"bop"}}'
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: {foo: "bar", foo2: {bee: "bop"}, foo3: "baz"},
|
||||
jsonValue: '{"foo":"bar","foo2":{"bee":"bop"},"foo3":"baz"}'
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: {foo: "bar", foo2: [1,2,3]},
|
||||
jsonValue: '{"foo":"bar","foo2":[1,2,3]}'
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: cyclicalObject,
|
||||
exception: true
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: [null, 2, false, cyclicalObject],
|
||||
exception: true
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: cyclicalArray,
|
||||
exception: true
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: {foo: 1, bar: cyclicalArray},
|
||||
exception: true
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: crazyNestedObject,
|
||||
jsonValue: JSON.stringify(crazyNestedObject)
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: crazyCyclicalObject,
|
||||
exception: true
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: objectWithSaneGetter,
|
||||
jsonValue: '{"foo":5}'
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: new objectWithSaneGetter2(),
|
||||
jsonValue: '{}'
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
value: objectWithThrowingGetter,
|
||||
exception: true
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
array: true,
|
||||
exception: false,
|
||||
shouldCompare: false,
|
||||
shouldEqual: false,
|
||||
value: [9, 8, 7]
|
||||
value: [9, 8, 7],
|
||||
jsonValue: '[9,8,7]'
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
array: true,
|
||||
value: [9, false, 10.5, {foo: "bar"}],
|
||||
jsonValue: '[9,false,10.5,{"foo":"bar"}]'
|
||||
},
|
||||
{
|
||||
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
|
||||
value: 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" })
|
||||
value: JSON.stringify({ foo: "bar" }),
|
||||
compareValue: '{"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,
|
||||
value: function (foo) { return "Bad!"; },
|
||||
compareValue: null
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
array: false,
|
||||
exception: false,
|
||||
shouldCompare: true,
|
||||
shouldEqual: true,
|
||||
value: Infinity,
|
||||
compareValue: null
|
||||
type: "number",
|
||||
isNaN: true,
|
||||
value: NaN
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
array: false,
|
||||
exception: false,
|
||||
shouldCompare: true,
|
||||
shouldEqual: true,
|
||||
value: -Infinity,
|
||||
compareValue: null
|
||||
type: "number",
|
||||
isInfinity: true,
|
||||
value: Infinity
|
||||
},
|
||||
{
|
||||
type: "number",
|
||||
isNegativeInfinity: true,
|
||||
value: -Infinity
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
array: false,
|
||||
exception: false,
|
||||
shouldCompare: true,
|
||||
shouldEqual: true,
|
||||
value: "testFinished"
|
||||
}
|
||||
|
@ -182,22 +217,26 @@ for (var index = 0; index < messages.length; index++) {
|
|||
if (message.hasOwnProperty("compareValue")) {
|
||||
continue;
|
||||
}
|
||||
message.compareValue = message.value;
|
||||
if (message.hasOwnProperty("shouldEqual") ||
|
||||
message.hasOwnProperty("shouldCompare")) {
|
||||
message.compareValue = message.value;
|
||||
}
|
||||
}
|
||||
|
||||
var onmessage = function(event) {
|
||||
function onmessage(event) {
|
||||
for (var index = 0; index < messages.length; index++) {
|
||||
var exception = false;
|
||||
var exception = undefined;
|
||||
|
||||
try {
|
||||
postMessage(messages[index].value);
|
||||
}
|
||||
catch (e) {
|
||||
exception = true;
|
||||
exception = e;
|
||||
}
|
||||
|
||||
if (messages[index].exception != exception) {
|
||||
throw "Exception inconsistency!";
|
||||
if ((exception !== undefined && !messages[index].exception) ||
|
||||
(exception === undefined && messages[index].exception)) {
|
||||
throw "Exception inconsistency [" + index + "]: " + exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,19 +31,38 @@ Tests of DOM Worker JSON messages
|
|||
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));
|
||||
is(typeof event.data, key.type, "Bad type! " + messages.indexOf(key));
|
||||
|
||||
if (key.shouldCompare) {
|
||||
if (key.array) {
|
||||
is(event.data instanceof Array, key.array,
|
||||
"Array mismatch! " + messages.indexOf(key));
|
||||
}
|
||||
|
||||
if (key.isNaN) {
|
||||
ok(isNaN(event.data), "Should be NaN!" + messages.indexOf(key));
|
||||
}
|
||||
|
||||
if (key.isInfinity) {
|
||||
is(event.data, Infinity, "Should be Infinity!" + messages.indexOf(key));
|
||||
}
|
||||
|
||||
if (key.isNegativeInfinity) {
|
||||
is(event.data, -Infinity, "Should be -Infinity!" + messages.indexOf(key));
|
||||
}
|
||||
|
||||
if (key.shouldCompare || key.shouldEqual) {
|
||||
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));
|
||||
"Values don't equal! " + messages.indexOf(key));
|
||||
}
|
||||
|
||||
if (key.jsonValue) {
|
||||
is(JSON.stringify(event.data), key.jsonValue,
|
||||
"Object stringification inconsistent!" + messages.indexOf(key));
|
||||
}
|
||||
|
||||
if (event.data == "testFinished") {
|
||||
|
@ -53,7 +72,7 @@ Tests of DOM Worker JSON messages
|
|||
};
|
||||
|
||||
worker.onerror = function(event) {
|
||||
ok(false, "Worker had an error: " + event.data);
|
||||
ok(false, "Worker had an error: " + event.message);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче