mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 620935 - Make console object available in Web Workers, r=ehsan, r=bz
This commit is contained in:
parent
8f1e800bba
commit
21fbd9fcfe
@ -34710,41 +34710,8 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
|||||||
|
|
||||||
var consoleTimer = {};
|
var consoleTimer = {};
|
||||||
|
|
||||||
var workerConsole = {
|
|
||||||
log: function log() {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
globalScope.postMessage({
|
|
||||||
action: 'console_log',
|
|
||||||
data: args
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
error: function error() {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
globalScope.postMessage({
|
|
||||||
action: 'console_error',
|
|
||||||
data: args
|
|
||||||
});
|
|
||||||
throw 'pdf.js execution error';
|
|
||||||
},
|
|
||||||
|
|
||||||
time: function time(name) {
|
|
||||||
consoleTimer[name] = Date.now();
|
|
||||||
},
|
|
||||||
|
|
||||||
timeEnd: function timeEnd(name) {
|
|
||||||
var time = consoleTimer[name];
|
|
||||||
if (!time) {
|
|
||||||
error('Unkown timer name ' + name);
|
|
||||||
}
|
|
||||||
this.log('Timer:', name, Date.now() - time);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Worker thread?
|
// Worker thread?
|
||||||
if (typeof window === 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
globalScope.console = workerConsole;
|
|
||||||
|
|
||||||
// Add a logger so we can pass warnings on to the main thread, errors will
|
// Add a logger so we can pass warnings on to the main thread, errors will
|
||||||
// throw an exception which will be forwarded on automatically.
|
// throw an exception which will be forwarded on automatically.
|
||||||
PDFJS.LogManager.addLogger({
|
PDFJS.LogManager.addLogger({
|
||||||
|
@ -214,19 +214,22 @@ ConsoleAPI.prototype = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue a call to a console method. See the CALL_DELAY constant.
|
* Queue a call to a console method. See the CALL_DELAY constant.
|
||||||
|
* This method is the entry point for the console.* for workers.
|
||||||
*
|
*
|
||||||
* @param string aMethod
|
* @param string aMethod
|
||||||
* The console method the code has invoked.
|
* The console method the code has invoked.
|
||||||
* @param object aArguments
|
* @param object aArguments
|
||||||
* The arguments passed to the console method.
|
* The arguments passed to the console method.
|
||||||
|
* @param array aStack
|
||||||
|
* The stack of the console method. Used by console.* for workers.
|
||||||
*/
|
*/
|
||||||
queueCall: function CA_queueCall(aMethod, aArguments)
|
queueCall: function CA_queueCall(aMethod, aArguments, aStack = null)
|
||||||
{
|
{
|
||||||
let window = this._window.get();
|
let window = this._window.get();
|
||||||
let metaForCall = {
|
let metaForCall = {
|
||||||
private: PrivateBrowsingUtils.isWindowPrivate(window),
|
private: PrivateBrowsingUtils.isWindowPrivate(window),
|
||||||
timeStamp: Date.now(),
|
timeStamp: Date.now(),
|
||||||
stack: this.getStackTrace(aMethod != "trace" ? 1 : null),
|
stack: (aStack ? aStack : this.getStackTrace(aMethod != "trace" ? 1 : null)),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (aMethod == "time" || aMethod == "timeEnd") {
|
if (aMethod == "time" || aMethod == "timeEnd") {
|
||||||
|
@ -1528,6 +1528,12 @@ DOMInterfaces = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'WorkerConsole': {
|
||||||
|
'headerFile': 'mozilla/dom/workers/bindings/Console.h',
|
||||||
|
'workers': True,
|
||||||
|
'implicitJSContext': [ 'trace', 'time', 'timeEnd' ],
|
||||||
|
},
|
||||||
|
|
||||||
'WorkerLocation': {
|
'WorkerLocation': {
|
||||||
'headerFile': 'mozilla/dom/workers/bindings/Location.h',
|
'headerFile': 'mozilla/dom/workers/bindings/Location.h',
|
||||||
'workers': True,
|
'workers': True,
|
||||||
|
@ -281,7 +281,7 @@ public:
|
|||||||
virtual ~JSStackFrame();
|
virtual ~JSStackFrame();
|
||||||
|
|
||||||
static already_AddRefed<nsIStackFrame>
|
static already_AddRefed<nsIStackFrame>
|
||||||
CreateStack(JSContext* cx);
|
CreateStack(JSContext* aCx, int32_t aMaxDepth = -1);
|
||||||
static already_AddRefed<nsIStackFrame>
|
static already_AddRefed<nsIStackFrame>
|
||||||
CreateStackFrameLocation(uint32_t aLanguage,
|
CreateStackFrameLocation(uint32_t aLanguage,
|
||||||
const char* aFilename,
|
const char* aFilename,
|
||||||
@ -495,11 +495,14 @@ NS_IMETHODIMP JSStackFrame::ToString(nsACString& _retval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */ already_AddRefed<nsIStackFrame>
|
/* static */ already_AddRefed<nsIStackFrame>
|
||||||
JSStackFrame::CreateStack(JSContext* cx)
|
JSStackFrame::CreateStack(JSContext* aCx, int32_t aMaxDepth)
|
||||||
{
|
{
|
||||||
static const unsigned MAX_FRAMES = 100;
|
static const unsigned MAX_FRAMES = 100;
|
||||||
|
if (aMaxDepth < 0) {
|
||||||
|
aMaxDepth = MAX_FRAMES;
|
||||||
|
}
|
||||||
|
|
||||||
JS::StackDescription* desc = JS::DescribeStack(cx, MAX_FRAMES);
|
JS::StackDescription* desc = JS::DescribeStack(aCx, aMaxDepth);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -530,9 +533,9 @@ JSStackFrame::CreateStackFrameLocation(uint32_t aLanguage,
|
|||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIStackFrame>
|
already_AddRefed<nsIStackFrame>
|
||||||
CreateStack(JSContext* cx)
|
CreateStack(JSContext* aCx, int32_t aMaxDepth)
|
||||||
{
|
{
|
||||||
return JSStackFrame::CreateStack(cx);
|
return JSStackFrame::CreateStack(aCx, aMaxDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIStackFrame>
|
already_AddRefed<nsIStackFrame>
|
||||||
|
@ -36,8 +36,10 @@ GetCurrentJSStack();
|
|||||||
// Internal stuff not intended to be widely used.
|
// Internal stuff not intended to be widely used.
|
||||||
namespace exceptions {
|
namespace exceptions {
|
||||||
|
|
||||||
|
// aMaxDepth can be used to define a maximal depth for the stack trace. If the
|
||||||
|
// value is -1, a default maximal depth will be selected.
|
||||||
already_AddRefed<nsIStackFrame>
|
already_AddRefed<nsIStackFrame>
|
||||||
CreateStack(JSContext* cx);
|
CreateStack(JSContext* aCx, int32_t aMaxDepth = -1);
|
||||||
|
|
||||||
already_AddRefed<nsIStackFrame>
|
already_AddRefed<nsIStackFrame>
|
||||||
CreateStackFrameLocation(uint32_t aLanguage,
|
CreateStackFrameLocation(uint32_t aLanguage,
|
||||||
|
35
dom/webidl/WorkerConsole.webidl
Normal file
35
dom/webidl/WorkerConsole.webidl
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=2 et sw=2 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/. */
|
||||||
|
|
||||||
|
interface WorkerConsole {
|
||||||
|
void log(any... data);
|
||||||
|
void info(any... data);
|
||||||
|
void warn(any... data);
|
||||||
|
void error(any... data);
|
||||||
|
void _exception(any... data);
|
||||||
|
void debug(any... data);
|
||||||
|
void trace();
|
||||||
|
void dir(optional any data);
|
||||||
|
void group(any... data);
|
||||||
|
void groupCollapsed(any... data);
|
||||||
|
void groupEnd(any... data);
|
||||||
|
void time(optional any time);
|
||||||
|
void timeEnd(optional any time);
|
||||||
|
void profile(any... data);
|
||||||
|
void profileEnd(any... data);
|
||||||
|
void assert(boolean condition, any... data);
|
||||||
|
void ___noSuchMethod__();
|
||||||
|
};
|
||||||
|
|
||||||
|
// This dictionary is used internally to send the stack trace from the worker to
|
||||||
|
// the main thread Console API implementation.
|
||||||
|
dictionary WorkerConsoleStack {
|
||||||
|
DOMString filename = "";
|
||||||
|
unsigned long lineNumber = 0;
|
||||||
|
DOMString functionName = "";
|
||||||
|
unsigned long language = 0;
|
||||||
|
};
|
||||||
|
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
interface WorkerGlobalScope : EventTarget {
|
interface WorkerGlobalScope : EventTarget {
|
||||||
readonly attribute WorkerGlobalScope self;
|
readonly attribute WorkerGlobalScope self;
|
||||||
|
readonly attribute WorkerConsole console;
|
||||||
readonly attribute WorkerLocation location;
|
readonly attribute WorkerLocation location;
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
@ -428,6 +428,7 @@ WEBIDL_FILES = [
|
|||||||
'WheelEvent.webidl',
|
'WheelEvent.webidl',
|
||||||
'WifiOptions.webidl',
|
'WifiOptions.webidl',
|
||||||
'Worker.webidl',
|
'Worker.webidl',
|
||||||
|
'WorkerConsole.webidl',
|
||||||
'WorkerGlobalScope.webidl',
|
'WorkerGlobalScope.webidl',
|
||||||
'WorkerLocation.webidl',
|
'WorkerLocation.webidl',
|
||||||
'WorkerNavigator.webidl',
|
'WorkerNavigator.webidl',
|
||||||
|
561
dom/workers/Console.cpp
Normal file
561
dom/workers/Console.cpp
Normal file
@ -0,0 +1,561 @@
|
|||||||
|
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||||
|
/* 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 "Console.h"
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jsfriendapi.h"
|
||||||
|
#include "js/OldDebugAPI.h"
|
||||||
|
|
||||||
|
#include "nsJSUtils.h"
|
||||||
|
#include "WorkerRunnable.h"
|
||||||
|
#include "nsComponentManagerUtils.h"
|
||||||
|
#include "nsIDOMGlobalPropertyInitializer.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/WorkerConsoleBinding.h"
|
||||||
|
#include "mozilla/dom/Exceptions.h"
|
||||||
|
|
||||||
|
#define CONSOLE_TAG JS_SCTAG_USER_MIN
|
||||||
|
|
||||||
|
// From dom/base/ConsoleAPI.js
|
||||||
|
#define DEFAULT_MAX_STACKTRACE_DEPTH 200
|
||||||
|
|
||||||
|
using namespace mozilla::dom::exceptions;
|
||||||
|
|
||||||
|
BEGIN_WORKERS_NAMESPACE
|
||||||
|
|
||||||
|
class ConsoleProxy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLProxy)
|
||||||
|
|
||||||
|
bool
|
||||||
|
Init(JSContext* aCx, nsPIDOMWindow* aWindow)
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
// Console API:
|
||||||
|
nsCOMPtr<nsISupports> cInstance =
|
||||||
|
do_CreateInstance("@mozilla.org/console-api;1");
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi =
|
||||||
|
do_QueryInterface(cInstance);
|
||||||
|
NS_ENSURE_TRUE(gpi, false);
|
||||||
|
|
||||||
|
// We don't do anything with the return value.
|
||||||
|
JS::Rooted<JS::Value> prop_val(aCx);
|
||||||
|
if (NS_FAILED(gpi->Init(aWindow, &prop_val))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mXpcwrappedjs = do_QueryInterface(cInstance);
|
||||||
|
NS_ENSURE_TRUE(mXpcwrappedjs, false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIXPConnectWrappedJS*
|
||||||
|
GetWrappedJS() const
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
return mXpcwrappedjs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseWrappedJS()
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
mXpcwrappedjs = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsCOMPtr<nsIXPConnectWrappedJS> mXpcwrappedjs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Console API in workers uses the Structured Clone Algorithm to move any value
|
||||||
|
* from the worker thread to the main-thread. Some object cannot be moved and,
|
||||||
|
* in these cases, we convert them to strings.
|
||||||
|
* It's not the best, but at least we are able to show something.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This method is called by the Structured Clone Algorithm when some data has
|
||||||
|
// to be read.
|
||||||
|
static JSObject*
|
||||||
|
ConsoleStructuredCloneCallbacksRead(JSContext* aCx,
|
||||||
|
JSStructuredCloneReader* /* unused */,
|
||||||
|
uint32_t aTag, uint32_t aData,
|
||||||
|
void* aClosure)
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
if (aTag != CONSOLE_TAG) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<nsString>* strings = static_cast<nsTArray<nsString>*>(aClosure);
|
||||||
|
if (strings->Length() <= aData) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> value(aCx);
|
||||||
|
if (!xpc::StringToJsval(aCx, strings->ElementAt(aData), &value)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> obj(aCx);
|
||||||
|
if (!JS_ValueToObject(aCx, value, &obj)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method is called by the Structured Clone Algorithm when some data has
|
||||||
|
// to be written.
|
||||||
|
static bool
|
||||||
|
ConsoleStructuredCloneCallbacksWrite(JSContext* aCx,
|
||||||
|
JSStructuredCloneWriter* aWriter,
|
||||||
|
JS::Handle<JSObject*> aObj,
|
||||||
|
void* aClosure)
|
||||||
|
{
|
||||||
|
JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aObj));
|
||||||
|
JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, value));
|
||||||
|
if (!jsString) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsDependentJSString string;
|
||||||
|
if (!string.init(aCx, jsString)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<nsString>* strings = static_cast<nsTArray<nsString>*>(aClosure);
|
||||||
|
|
||||||
|
if (!JS_WriteUint32Pair(aWriter, CONSOLE_TAG, strings->Length())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
strings->AppendElement(string);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ConsoleStructuredCloneCallbacksError(JSContext* /* aCx */,
|
||||||
|
uint32_t /* aErrorId */)
|
||||||
|
{
|
||||||
|
NS_WARNING("Failed to clone data for the Console API in workers.");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSStructuredCloneCallbacks gConsoleCallbacks = {
|
||||||
|
ConsoleStructuredCloneCallbacksRead,
|
||||||
|
ConsoleStructuredCloneCallbacksWrite,
|
||||||
|
ConsoleStructuredCloneCallbacksError
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConsoleStackData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConsoleStackData()
|
||||||
|
: mLineNumber(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
nsCString mFilename;
|
||||||
|
uint32_t mLineNumber;
|
||||||
|
nsCString mFunctionName;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConsoleRunnable MOZ_FINAL : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ConsoleRunnable(WorkerConsole* aConsole,
|
||||||
|
WorkerPrivate* aWorkerPrivate)
|
||||||
|
: mConsole(aConsole)
|
||||||
|
, mWorkerPrivate(aWorkerPrivate)
|
||||||
|
, mMethod(nullptr)
|
||||||
|
{
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Dispatch(JSContext* aCx,
|
||||||
|
const char* aMethod,
|
||||||
|
JS::Handle<JS::Value> aArguments,
|
||||||
|
nsTArray<ConsoleStackData>& aStackData)
|
||||||
|
{
|
||||||
|
mMethod = aMethod;
|
||||||
|
mStackData.SwapElements(aStackData);
|
||||||
|
|
||||||
|
if (!mArguments.write(aCx, aArguments, &gConsoleCallbacks, &mStrings)) {
|
||||||
|
JS_ClearPendingException(aCx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
AutoSyncLoopHolder syncLoop(mWorkerPrivate);
|
||||||
|
|
||||||
|
mSyncLoopTarget = syncLoop.EventTarget();
|
||||||
|
|
||||||
|
if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
|
||||||
|
JS_ReportError(aCx,
|
||||||
|
"Failed to dispatch to main thread for the "
|
||||||
|
"Console API (method %s)!", mMethod);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return syncLoop.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
RunConsole();
|
||||||
|
|
||||||
|
nsRefPtr<MainThreadStopSyncLoopRunnable> response =
|
||||||
|
new MainThreadStopSyncLoopRunnable(mWorkerPrivate,
|
||||||
|
mSyncLoopTarget.forget(),
|
||||||
|
true);
|
||||||
|
if (!response->Dispatch(nullptr)) {
|
||||||
|
NS_WARNING("Failed to dispatch response!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RunConsole()
|
||||||
|
{
|
||||||
|
// This class is used to clear any exception at the end of this method.
|
||||||
|
class ClearException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClearException(JSContext* aCx)
|
||||||
|
: mCx(aCx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~ClearException()
|
||||||
|
{
|
||||||
|
JS_ClearPendingException(mCx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JSContext* mCx;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Walk up to our containing page
|
||||||
|
WorkerPrivate* wp = mWorkerPrivate;
|
||||||
|
while (wp->GetParent()) {
|
||||||
|
wp = wp->GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoPushJSContext cx(wp->ParentJSContext());
|
||||||
|
JSAutoRequest ar(cx);
|
||||||
|
ClearException ce(cx);
|
||||||
|
|
||||||
|
nsRefPtr<ConsoleProxy> proxy = mConsole->GetProxy();
|
||||||
|
if (!proxy) {
|
||||||
|
nsPIDOMWindow* window = wp->GetWindow();
|
||||||
|
NS_ENSURE_TRUE_VOID(window);
|
||||||
|
|
||||||
|
proxy = new ConsoleProxy();
|
||||||
|
if (!proxy->Init(cx, window)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mConsole->SetProxy(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> consoleObj(cx, proxy->GetWrappedJS()->GetJSObject());
|
||||||
|
NS_ENSURE_TRUE_VOID(consoleObj);
|
||||||
|
|
||||||
|
JSAutoCompartment ac(cx, consoleObj);
|
||||||
|
|
||||||
|
// 3 args for the queueCall.
|
||||||
|
nsDependentCString method(mMethod);
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> methodValue(cx);
|
||||||
|
if (!ByteStringToJsval(cx, method, &methodValue)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> argumentsValue(cx);
|
||||||
|
if (!mArguments.read(cx, &argumentsValue, &gConsoleCallbacks, &mStrings)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> stackValue(cx);
|
||||||
|
{
|
||||||
|
JS::Rooted<JSObject*> stackObj(cx,
|
||||||
|
JS_NewArrayObject(cx, mStackData.Length(), nullptr));
|
||||||
|
if (!stackObj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < mStackData.Length(); ++i) {
|
||||||
|
WorkerConsoleStack stack;
|
||||||
|
|
||||||
|
CopyUTF8toUTF16(mStackData[i].mFilename, stack.mFilename);
|
||||||
|
|
||||||
|
CopyUTF8toUTF16(mStackData[i].mFunctionName, stack.mFunctionName);
|
||||||
|
|
||||||
|
stack.mLineNumber = mStackData[i].mLineNumber;
|
||||||
|
|
||||||
|
stack.mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> value(cx);
|
||||||
|
if (!stack.ToObject(cx, JS::NullPtr(), &value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!JS_DefineElement(cx, stackObj, i, value, nullptr, nullptr, 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stackValue = JS::ObjectValue(*stackObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::AutoValueVector argv(cx);
|
||||||
|
if (!argv.resize(3)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[0] = methodValue;
|
||||||
|
argv[1] = argumentsValue;
|
||||||
|
argv[2] = stackValue;
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> ret(cx);
|
||||||
|
JS_CallFunctionName(cx, consoleObj, "queueCall", argv.length(),
|
||||||
|
argv.begin(), ret.address());
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerConsole* mConsole;
|
||||||
|
WorkerPrivate* mWorkerPrivate;
|
||||||
|
nsCOMPtr<nsIEventTarget> mSyncLoopTarget;
|
||||||
|
|
||||||
|
const char* mMethod;
|
||||||
|
JSAutoStructuredCloneBuffer mArguments;
|
||||||
|
nsTArray<ConsoleStackData> mStackData;
|
||||||
|
|
||||||
|
nsTArray<nsString> mStrings;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TeardownRunnable : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TeardownRunnable(ConsoleProxy* aProxy)
|
||||||
|
: mProxy(aProxy)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
mProxy->ReleaseWrappedJS();
|
||||||
|
mProxy = nullptr;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<ConsoleProxy> mProxy;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WorkerConsole)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WorkerConsole, AddRef)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WorkerConsole, Release)
|
||||||
|
|
||||||
|
/* static */ already_AddRefed<WorkerConsole>
|
||||||
|
WorkerConsole::Create()
|
||||||
|
{
|
||||||
|
nsRefPtr<WorkerConsole> console = new WorkerConsole();
|
||||||
|
return console.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject*
|
||||||
|
WorkerConsole::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||||
|
{
|
||||||
|
return WorkerConsoleBinding_workers::Wrap(aCx, aScope, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerConsole::WorkerConsole()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(WorkerConsole);
|
||||||
|
SetIsDOMBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerConsole::~WorkerConsole()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(WorkerConsole);
|
||||||
|
|
||||||
|
if (mProxy) {
|
||||||
|
nsRefPtr<TeardownRunnable> runnable = new TeardownRunnable(mProxy);
|
||||||
|
mProxy = nullptr;
|
||||||
|
|
||||||
|
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
|
||||||
|
NS_ERROR("Failed to dispatch teardown runnable!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerConsole::SetProxy(ConsoleProxy* aProxy)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!mProxy);
|
||||||
|
mProxy = aProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerConsole::Method(JSContext* aCx, const char* aMethodName,
|
||||||
|
const Sequence<JS::Value>& aData,
|
||||||
|
uint32_t aStackLevel)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIStackFrame> stack = CreateStack(aCx, aStackLevel);
|
||||||
|
if (!stack) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// nsIStackFrame is not thread-safe so we take what we need and we store in
|
||||||
|
// an array of ConsoleStackData objects.
|
||||||
|
nsTArray<ConsoleStackData> stackData;
|
||||||
|
while (stack) {
|
||||||
|
ConsoleStackData& data = *stackData.AppendElement();
|
||||||
|
|
||||||
|
if (NS_FAILED(stack->GetFilename(data.mFilename))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t lineNumber;
|
||||||
|
if (NS_FAILED(stack->GetLineNumber(&lineNumber))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.mLineNumber = lineNumber;
|
||||||
|
|
||||||
|
if (NS_FAILED(stack->GetName(data.mFunctionName))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIStackFrame> caller;
|
||||||
|
if (NS_FAILED(stack->GetCaller(getter_AddRefs(caller)))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.swap(caller);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> arguments(aCx,
|
||||||
|
JS_NewArrayObject(aCx, aData.Length(), nullptr));
|
||||||
|
if (!arguments) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < aData.Length(); ++i) {
|
||||||
|
if (!JS_DefineElement(aCx, arguments, i, aData[i], nullptr, nullptr,
|
||||||
|
JSPROP_ENUMERATE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JS::Rooted<JS::Value> argumentsValue(aCx, JS::ObjectValue(*arguments));
|
||||||
|
|
||||||
|
WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
|
||||||
|
MOZ_ASSERT(worker);
|
||||||
|
|
||||||
|
nsRefPtr<ConsoleRunnable> runnable = new ConsoleRunnable(this, worker);
|
||||||
|
runnable->Dispatch(aCx, aMethodName, argumentsValue, stackData);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define METHOD(name, jsName) \
|
||||||
|
void \
|
||||||
|
WorkerConsole::name(JSContext* aCx, \
|
||||||
|
const Sequence<JS::Value>& aData) \
|
||||||
|
{ \
|
||||||
|
Method(aCx, jsName, aData, 1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(Log, "log")
|
||||||
|
METHOD(Info, "info")
|
||||||
|
METHOD(Warn, "warn")
|
||||||
|
METHOD(Error, "error")
|
||||||
|
METHOD(Exception, "exception")
|
||||||
|
METHOD(Debug, "debug")
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerConsole::Trace(JSContext* aCx)
|
||||||
|
{
|
||||||
|
Sequence<JS::Value> data;
|
||||||
|
Method(aCx, "trace", data, DEFAULT_MAX_STACKTRACE_DEPTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerConsole::Dir(JSContext* aCx,
|
||||||
|
const Optional<JS::Handle<JS::Value>>& aValue)
|
||||||
|
{
|
||||||
|
Sequence<JS::Value> data;
|
||||||
|
|
||||||
|
if (aValue.WasPassed()) {
|
||||||
|
data.AppendElement(aValue.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
Method(aCx, "dir", data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(Group, "group")
|
||||||
|
METHOD(GroupCollapsed, "groupCollapsed")
|
||||||
|
METHOD(GroupEnd, "groupEnd")
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerConsole::Time(JSContext* aCx,
|
||||||
|
const Optional<JS::Handle<JS::Value>>& aTimer)
|
||||||
|
{
|
||||||
|
Sequence<JS::Value> data;
|
||||||
|
|
||||||
|
if (aTimer.WasPassed()) {
|
||||||
|
data.AppendElement(aTimer.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
Method(aCx, "time", data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerConsole::TimeEnd(JSContext* aCx,
|
||||||
|
const Optional<JS::Handle<JS::Value>>& aTimer)
|
||||||
|
{
|
||||||
|
Sequence<JS::Value> data;
|
||||||
|
|
||||||
|
if (aTimer.WasPassed()) {
|
||||||
|
data.AppendElement(aTimer.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
Method(aCx, "timeEnd", data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(Profile, "profile")
|
||||||
|
METHOD(ProfileEnd, "profileEnd")
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerConsole::Assert(JSContext* aCx, bool aCondition,
|
||||||
|
const Sequence<JS::Value>& aData)
|
||||||
|
{
|
||||||
|
if (!aCondition) {
|
||||||
|
Method(aCx, "assert", aData, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerConsole::__noSuchMethod__()
|
||||||
|
{
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef METHOD
|
||||||
|
|
||||||
|
END_WORKERS_NAMESPACE
|
112
dom/workers/Console.h
Normal file
112
dom/workers/Console.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||||
|
/* 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_dom_workers_Console_h
|
||||||
|
#define mozilla_dom_workers_Console_h
|
||||||
|
|
||||||
|
#include "Workers.h"
|
||||||
|
#include "WorkerPrivate.h"
|
||||||
|
#include "nsWrapperCache.h"
|
||||||
|
|
||||||
|
BEGIN_WORKERS_NAMESPACE
|
||||||
|
|
||||||
|
class ConsoleProxy;
|
||||||
|
class ConsoleStackData;
|
||||||
|
|
||||||
|
class WorkerConsole MOZ_FINAL : public nsWrapperCache
|
||||||
|
{
|
||||||
|
WorkerConsole();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WorkerConsole)
|
||||||
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WorkerConsole)
|
||||||
|
|
||||||
|
static already_AddRefed<WorkerConsole>
|
||||||
|
Create();
|
||||||
|
|
||||||
|
virtual JSObject*
|
||||||
|
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
nsISupports* GetParentObject() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
~WorkerConsole();
|
||||||
|
|
||||||
|
ConsoleProxy*
|
||||||
|
GetProxy() const
|
||||||
|
{
|
||||||
|
return mProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetProxy(ConsoleProxy* aProxy);
|
||||||
|
|
||||||
|
// WebIDL methods
|
||||||
|
|
||||||
|
void
|
||||||
|
Log(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
Info(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
Warn(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
Error(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
Exception(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
Debug(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
Trace(JSContext* aCx);
|
||||||
|
|
||||||
|
void
|
||||||
|
Dir(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aValue);
|
||||||
|
|
||||||
|
void
|
||||||
|
Group(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupCollapsed(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupEnd(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
Time(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aTimer);
|
||||||
|
|
||||||
|
void
|
||||||
|
TimeEnd(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aTimer);
|
||||||
|
|
||||||
|
void
|
||||||
|
Profile(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
ProfileEnd(JSContext* aCx, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
Assert(JSContext* aCx, bool aCondition, const Sequence<JS::Value>& aData);
|
||||||
|
|
||||||
|
void
|
||||||
|
__noSuchMethod__();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void
|
||||||
|
Method(JSContext* aCx, const char* aMethodName,
|
||||||
|
const Sequence<JS::Value>& aData, uint32_t aMaxStackDepth);
|
||||||
|
|
||||||
|
nsRefPtr<ConsoleProxy> mProxy;
|
||||||
|
};
|
||||||
|
|
||||||
|
END_WORKERS_NAMESPACE
|
||||||
|
|
||||||
|
#endif // mozilla_dom_workers_Console_h
|
@ -15,6 +15,7 @@
|
|||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "Console.h"
|
||||||
#include "Location.h"
|
#include "Location.h"
|
||||||
#include "Navigator.h"
|
#include "Navigator.h"
|
||||||
#include "Principal.h"
|
#include "Principal.h"
|
||||||
@ -77,6 +78,19 @@ WorkerGlobalScope::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
|||||||
MOZ_CRASH("We should never get here!");
|
MOZ_CRASH("We should never get here!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WorkerConsole*
|
||||||
|
WorkerGlobalScope::Console()
|
||||||
|
{
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
if (!mConsole) {
|
||||||
|
mConsole = WorkerConsole::Create();
|
||||||
|
MOZ_ASSERT(mConsole);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mConsole;
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<WorkerLocation>
|
already_AddRefed<WorkerLocation>
|
||||||
WorkerGlobalScope::Location()
|
WorkerGlobalScope::Location()
|
||||||
{
|
{
|
||||||
|
@ -20,12 +20,14 @@ class Function;
|
|||||||
BEGIN_WORKERS_NAMESPACE
|
BEGIN_WORKERS_NAMESPACE
|
||||||
|
|
||||||
class WorkerPrivate;
|
class WorkerPrivate;
|
||||||
|
class WorkerConsole;
|
||||||
class WorkerLocation;
|
class WorkerLocation;
|
||||||
class WorkerNavigator;
|
class WorkerNavigator;
|
||||||
|
|
||||||
class WorkerGlobalScope : public nsDOMEventTargetHelper,
|
class WorkerGlobalScope : public nsDOMEventTargetHelper,
|
||||||
public nsIGlobalObject
|
public nsIGlobalObject
|
||||||
{
|
{
|
||||||
|
nsRefPtr<WorkerConsole> mConsole;
|
||||||
nsRefPtr<WorkerLocation> mLocation;
|
nsRefPtr<WorkerLocation> mLocation;
|
||||||
nsRefPtr<WorkerNavigator> mNavigator;
|
nsRefPtr<WorkerNavigator> mNavigator;
|
||||||
|
|
||||||
@ -58,6 +60,9 @@ public:
|
|||||||
return nsRefPtr<WorkerGlobalScope>(this).forget();
|
return nsRefPtr<WorkerGlobalScope>(this).forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WorkerConsole*
|
||||||
|
Console();
|
||||||
|
|
||||||
already_AddRefed<WorkerLocation>
|
already_AddRefed<WorkerLocation>
|
||||||
Location();
|
Location();
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ EXPORTS.mozilla.dom.workers += [
|
|||||||
|
|
||||||
# Stuff needed for the bindings, not really public though.
|
# Stuff needed for the bindings, not really public though.
|
||||||
EXPORTS.mozilla.dom.workers.bindings += [
|
EXPORTS.mozilla.dom.workers.bindings += [
|
||||||
|
'Console.h',
|
||||||
'FileReaderSync.h',
|
'FileReaderSync.h',
|
||||||
'Location.h',
|
'Location.h',
|
||||||
'MessagePort.h',
|
'MessagePort.h',
|
||||||
@ -32,6 +33,7 @@ EXPORTS.mozilla.dom.workers.bindings += [
|
|||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
'ChromeWorkerScope.cpp',
|
'ChromeWorkerScope.cpp',
|
||||||
|
'Console.cpp',
|
||||||
'File.cpp',
|
'File.cpp',
|
||||||
'FileReaderSync.cpp',
|
'FileReaderSync.cpp',
|
||||||
'Location.cpp',
|
'Location.cpp',
|
||||||
|
104
dom/workers/test/console_worker.js
Normal file
104
dom/workers/test/console_worker.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
onmessage = function(event) {
|
||||||
|
// TEST: does console exist?
|
||||||
|
postMessage({event: 'console exists', status: !!console, last : false});
|
||||||
|
|
||||||
|
postMessage({event: 'trace without function', status: true, last : false});
|
||||||
|
|
||||||
|
for (var i = 0; i < 10; ++i) {
|
||||||
|
console.what('1', 123, 321);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < 10; ++i) {
|
||||||
|
console.log(i, i, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
function trace1() {
|
||||||
|
function trace2() {
|
||||||
|
function trace3() {
|
||||||
|
console.trace("trace " + i);
|
||||||
|
}
|
||||||
|
trace3();
|
||||||
|
}
|
||||||
|
trace2();
|
||||||
|
}
|
||||||
|
trace1();
|
||||||
|
|
||||||
|
foobar585956c = function(a) {
|
||||||
|
console.trace();
|
||||||
|
return a+"c";
|
||||||
|
};
|
||||||
|
|
||||||
|
function foobar585956b(a) {
|
||||||
|
return foobar585956c(a+"b");
|
||||||
|
}
|
||||||
|
|
||||||
|
function foobar585956a(omg) {
|
||||||
|
return foobar585956b(omg + "a");
|
||||||
|
}
|
||||||
|
|
||||||
|
function foobar646025(omg) {
|
||||||
|
console.log(omg, "o", "d");
|
||||||
|
}
|
||||||
|
|
||||||
|
function startTimer(timer) {
|
||||||
|
console.time(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopTimer(timer) {
|
||||||
|
console.timeEnd(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGroups() {
|
||||||
|
console.groupCollapsed("a", "group");
|
||||||
|
console.group("b", "group");
|
||||||
|
console.groupEnd("b", "group");
|
||||||
|
}
|
||||||
|
|
||||||
|
foobar585956a('omg');
|
||||||
|
foobar646025('omg');
|
||||||
|
testGroups();
|
||||||
|
startTimer('foo');
|
||||||
|
setTimeout(function() {
|
||||||
|
stopTimer('foo');
|
||||||
|
nextSteps(event);
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextSteps(event) {
|
||||||
|
|
||||||
|
function namelessTimer() {
|
||||||
|
console.time();
|
||||||
|
console.timeEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
namelessTimer();
|
||||||
|
|
||||||
|
var str = "Test Message."
|
||||||
|
console.foobar(str); // if this throws, we don't execute following funcs
|
||||||
|
console.log(str);
|
||||||
|
console.info(str);
|
||||||
|
console.warn(str);
|
||||||
|
console.error(str);
|
||||||
|
console.exception(str);
|
||||||
|
console.assert(true, str);
|
||||||
|
console.assert(false, str);
|
||||||
|
console.profile(str);
|
||||||
|
console.profileEnd(str);
|
||||||
|
postMessage({event: '4 messages', status: true, last : false});
|
||||||
|
|
||||||
|
// Recursive:
|
||||||
|
if (event.data == true) {
|
||||||
|
var worker = new Worker('console_worker.js');
|
||||||
|
worker.onmessage = function(event) {
|
||||||
|
postMessage(event.data);
|
||||||
|
}
|
||||||
|
worker.postMessage(false);
|
||||||
|
} else {
|
||||||
|
postMessage({event: 'bye bye', status: true, last : true});
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ support-files =
|
|||||||
closeOnGC_worker.js
|
closeOnGC_worker.js
|
||||||
close_worker.js
|
close_worker.js
|
||||||
content_worker.js
|
content_worker.js
|
||||||
|
console_worker.js
|
||||||
csp_worker.js
|
csp_worker.js
|
||||||
errorPropagation_iframe.html
|
errorPropagation_iframe.html
|
||||||
errorPropagation_worker.js
|
errorPropagation_worker.js
|
||||||
@ -20,6 +21,7 @@ support-files =
|
|||||||
importScripts_worker_imported4.js
|
importScripts_worker_imported4.js
|
||||||
instanceof_worker.js
|
instanceof_worker.js
|
||||||
json_worker.js
|
json_worker.js
|
||||||
|
jsversion_worker.js
|
||||||
loadEncoding_worker.js
|
loadEncoding_worker.js
|
||||||
location_worker.js
|
location_worker.js
|
||||||
longThread_worker.js
|
longThread_worker.js
|
||||||
@ -59,7 +61,6 @@ support-files =
|
|||||||
xhr_implicit_cancel_worker.js
|
xhr_implicit_cancel_worker.js
|
||||||
xhr_worker.js
|
xhr_worker.js
|
||||||
url_exceptions_worker.js
|
url_exceptions_worker.js
|
||||||
jsversion_worker.js
|
|
||||||
urlSearchParams_worker.js
|
urlSearchParams_worker.js
|
||||||
subdir/relativeLoad_sub_worker.js
|
subdir/relativeLoad_sub_worker.js
|
||||||
subdir/relativeLoad_sub_worker2.js
|
subdir/relativeLoad_sub_worker2.js
|
||||||
@ -73,6 +74,7 @@ support-files =
|
|||||||
[test_clearTimeouts.html]
|
[test_clearTimeouts.html]
|
||||||
[test_close.html]
|
[test_close.html]
|
||||||
[test_closeOnGC.html]
|
[test_closeOnGC.html]
|
||||||
|
[test_console.html]
|
||||||
[test_contentWorker.html]
|
[test_contentWorker.html]
|
||||||
[test_csp.html]
|
[test_csp.html]
|
||||||
[test_csp.html^headers^]
|
[test_csp.html^headers^]
|
||||||
@ -85,6 +87,7 @@ support-files =
|
|||||||
[test_importScripts.html]
|
[test_importScripts.html]
|
||||||
[test_instanceof.html]
|
[test_instanceof.html]
|
||||||
[test_json.html]
|
[test_json.html]
|
||||||
|
[test_jsversion.html]
|
||||||
[test_loadEncoding.html]
|
[test_loadEncoding.html]
|
||||||
[test_loadError.html]
|
[test_loadError.html]
|
||||||
[test_location.html]
|
[test_location.html]
|
||||||
@ -125,4 +128,3 @@ support-files =
|
|||||||
skip-if = (os == "win") || (os == "mac")
|
skip-if = (os == "win") || (os == "mac")
|
||||||
[test_url_exceptions.html]
|
[test_url_exceptions.html]
|
||||||
[test_urlSearchParams.html]
|
[test_urlSearchParams.html]
|
||||||
[test_jsversion.html]
|
|
||||||
|
44
dom/workers/test/test_console.html
Normal file
44
dom/workers/test/test_console.html
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
Tests of DOM Worker Console
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for DOM Worker Console</title>
|
||||||
|
<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 class="testbody" language="javascript">
|
||||||
|
var worker = new Worker("console_worker.js");
|
||||||
|
|
||||||
|
worker.onmessage = function(event) {
|
||||||
|
is(event.target, worker, "Worker and target match!");
|
||||||
|
ok(event.data.status, event.data.event);
|
||||||
|
|
||||||
|
if (!event.data.status || event.data.last)
|
||||||
|
SimpleTest.finish();
|
||||||
|
};
|
||||||
|
|
||||||
|
worker.onerror = function(event) {
|
||||||
|
ok(false, "Worker had an error: " + event.message);
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.postMessage(true);
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user