mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-06 07:17:30 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
2440
dom/console/Console.cpp
Normal file
2440
dom/console/Console.cpp
Normal file
File diff suppressed because it is too large
Load diff
404
dom/console/Console.h
Normal file
404
dom/console/Console.h
Normal file
|
|
@ -0,0 +1,404 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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/. */
|
||||
|
||||
#ifndef mozilla_dom_Console_h
|
||||
#define mozilla_dom_Console_h
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/JSObjectHolder.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
class nsIConsoleAPIStorage;
|
||||
class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AnyCallback;
|
||||
class ConsoleCallData;
|
||||
class ConsoleRunnable;
|
||||
class ConsoleCallDataRunnable;
|
||||
class ConsoleProfileRunnable;
|
||||
struct ConsoleStackEntry;
|
||||
|
||||
class Console final : public nsIObserver
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Console, nsIObserver)
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static already_AddRefed<Console>
|
||||
Create(nsPIDOMWindowInner* aWindow, ErrorResult& aRv);
|
||||
|
||||
// WebIDL methods
|
||||
nsPIDOMWindowInner* GetParentObject() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
static void
|
||||
Log(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Info(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Warn(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Error(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Exception(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Debug(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Table(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Trace(const GlobalObject& aGlobal);
|
||||
|
||||
static void
|
||||
Dir(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Dirxml(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Group(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
GroupCollapsed(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
GroupEnd(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Time(const GlobalObject& aGlobal, const JS::Handle<JS::Value> aTime);
|
||||
|
||||
static void
|
||||
TimeEnd(const GlobalObject& aGlobal, const JS::Handle<JS::Value> aTime);
|
||||
|
||||
static void
|
||||
TimeStamp(const GlobalObject& aGlobal, const JS::Handle<JS::Value> aData);
|
||||
|
||||
static void
|
||||
Profile(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
ProfileEnd(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Assert(const GlobalObject& aGlobal, bool aCondition,
|
||||
const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Count(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Clear(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
NoopMethod(const GlobalObject& aGlobal);
|
||||
|
||||
void
|
||||
ClearStorage();
|
||||
|
||||
void
|
||||
RetrieveConsoleEvents(JSContext* aCx, nsTArray<JS::Value>& aEvents,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
SetConsoleEventHandler(AnyCallback* aHandler);
|
||||
|
||||
private:
|
||||
explicit Console(nsPIDOMWindowInner* aWindow);
|
||||
~Console();
|
||||
|
||||
void
|
||||
Initialize(ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Shutdown();
|
||||
|
||||
enum MethodName
|
||||
{
|
||||
MethodLog,
|
||||
MethodInfo,
|
||||
MethodWarn,
|
||||
MethodError,
|
||||
MethodException,
|
||||
MethodDebug,
|
||||
MethodTable,
|
||||
MethodTrace,
|
||||
MethodDir,
|
||||
MethodDirxml,
|
||||
MethodGroup,
|
||||
MethodGroupCollapsed,
|
||||
MethodGroupEnd,
|
||||
MethodTime,
|
||||
MethodTimeEnd,
|
||||
MethodTimeStamp,
|
||||
MethodAssert,
|
||||
MethodCount,
|
||||
MethodClear
|
||||
};
|
||||
|
||||
static already_AddRefed<Console>
|
||||
GetConsole(const GlobalObject& aGlobal);
|
||||
|
||||
static Console*
|
||||
GetConsoleInternal(const GlobalObject& aGlobal, ErrorResult &aRv);
|
||||
|
||||
static void
|
||||
ProfileMethod(const GlobalObject& aGlobal, const nsAString& aAction,
|
||||
const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
ProfileMethodInternal(JSContext* aCx, const nsAString& aAction,
|
||||
const Sequence<JS::Value>& aData);
|
||||
|
||||
static void
|
||||
Method(const GlobalObject& aGlobal, MethodName aName,
|
||||
const nsAString& aString, const Sequence<JS::Value>& aData);
|
||||
|
||||
void
|
||||
MethodInternal(JSContext* aCx, MethodName aName,
|
||||
const nsAString& aString, const Sequence<JS::Value>& aData);
|
||||
|
||||
// This method must receive aCx and aArguments in the same JSCompartment.
|
||||
void
|
||||
ProcessCallData(JSContext* aCx,
|
||||
ConsoleCallData* aData,
|
||||
const Sequence<JS::Value>& aArguments);
|
||||
|
||||
void
|
||||
StoreCallData(ConsoleCallData* aData);
|
||||
|
||||
void
|
||||
UnstoreCallData(ConsoleCallData* aData);
|
||||
|
||||
// Read in Console.cpp how this method is used.
|
||||
void
|
||||
ReleaseCallData(ConsoleCallData* aCallData);
|
||||
|
||||
// aCx and aArguments must be in the same JS compartment.
|
||||
void
|
||||
NotifyHandler(JSContext* aCx,
|
||||
const Sequence<JS::Value>& aArguments,
|
||||
ConsoleCallData* aData) const;
|
||||
|
||||
// PopulateConsoleNotificationInTheTargetScope receives aCx and aArguments in
|
||||
// the same JS compartment and populates the ConsoleEvent object (aValue) in
|
||||
// the aTargetScope.
|
||||
// aTargetScope can be:
|
||||
// - the system-principal scope when we want to dispatch the ConsoleEvent to
|
||||
// nsIConsoleAPIStorage (See the comment in Console.cpp about the use of
|
||||
// xpc::PrivilegedJunkScope()
|
||||
// - the mConsoleEventNotifier->Callable() scope when we want to notify this
|
||||
// handler about a new ConsoleEvent.
|
||||
// - It can be the global from the JSContext when RetrieveConsoleEvents is
|
||||
// called.
|
||||
bool
|
||||
PopulateConsoleNotificationInTheTargetScope(JSContext* aCx,
|
||||
const Sequence<JS::Value>& aArguments,
|
||||
JSObject* aTargetScope,
|
||||
JS::MutableHandle<JS::Value> aValue,
|
||||
ConsoleCallData* aData) const;
|
||||
|
||||
// If the first JS::Value of the array is a string, this method uses it to
|
||||
// format a string. The supported sequences are:
|
||||
// %s - string
|
||||
// %d,%i - integer
|
||||
// %f - double
|
||||
// %o,%O - a JS object.
|
||||
// %c - style string.
|
||||
// The output is an array where any object is a separated item, the rest is
|
||||
// unified in a format string.
|
||||
// Example if the input is:
|
||||
// "string: %s, integer: %d, object: %o, double: %d", 's', 1, window, 0.9
|
||||
// The output will be:
|
||||
// [ "string: s, integer: 1, object: ", window, ", double: 0.9" ]
|
||||
//
|
||||
// The aStyles array is populated with the style strings that the function
|
||||
// finds based the format string. The index of the styles matches the indexes
|
||||
// of elements that need the custom styling from aSequence. For elements with
|
||||
// no custom styling the array is padded with null elements.
|
||||
bool
|
||||
ProcessArguments(JSContext* aCx, const Sequence<JS::Value>& aData,
|
||||
Sequence<JS::Value>& aSequence,
|
||||
Sequence<nsString>& aStyles) const;
|
||||
|
||||
void
|
||||
MakeFormatString(nsCString& aFormat, int32_t aInteger, int32_t aMantissa,
|
||||
char aCh) const;
|
||||
|
||||
// Stringify and Concat all the JS::Value in a single string using ' ' as
|
||||
// separator.
|
||||
void
|
||||
ComposeGroupName(JSContext* aCx, const Sequence<JS::Value>& aData,
|
||||
nsAString& aName) const;
|
||||
|
||||
// StartTimer is called on the owning thread and populates aTimerLabel and
|
||||
// aTimerValue. It returns false if a JS exception is thrown or if
|
||||
// the max number of timers is reached.
|
||||
// * aCx - the JSContext rooting aName.
|
||||
// * aName - this is (should be) the name of the timer as JS::Value.
|
||||
// * aTimestamp - the monotonicTimer for this context (taken from
|
||||
// window->performance.now() or from Now() -
|
||||
// workerPrivate->NowBaseTimeStamp() in workers.
|
||||
// * aTimerLabel - This label will be populated with the aName converted to a
|
||||
// string.
|
||||
// * aTimerValue - the StartTimer value stored into (or taken from)
|
||||
// mTimerRegistry.
|
||||
bool
|
||||
StartTimer(JSContext* aCx, const JS::Value& aName,
|
||||
DOMHighResTimeStamp aTimestamp,
|
||||
nsAString& aTimerLabel,
|
||||
DOMHighResTimeStamp* aTimerValue);
|
||||
|
||||
// CreateStartTimerValue generates a ConsoleTimerStart dictionary exposed as
|
||||
// JS::Value. If aTimerStatus is false, it generates a ConsoleTimerError
|
||||
// instead. It's called only after the execution StartTimer on the owning
|
||||
// thread.
|
||||
// * aCx - this is the context that will root the returned value.
|
||||
// * aTimerLabel - this label must be what StartTimer received as aTimerLabel.
|
||||
// * aTimerValue - this is what StartTimer received as aTimerValue
|
||||
// * aTimerStatus - the return value of StartTimer.
|
||||
JS::Value
|
||||
CreateStartTimerValue(JSContext* aCx, const nsAString& aTimerLabel,
|
||||
DOMHighResTimeStamp aTimerValue,
|
||||
bool aTimerStatus) const;
|
||||
|
||||
// StopTimer follows the same pattern as StartTimer: it runs on the
|
||||
// owning thread and populates aTimerLabel and aTimerDuration, used by
|
||||
// CreateStopTimerValue. It returns false if a JS exception is thrown or if
|
||||
// the aName timer doesn't exist in the mTimerRegistry.
|
||||
// * aCx - the JSContext rooting aName.
|
||||
// * aName - this is (should be) the name of the timer as JS::Value.
|
||||
// * aTimestamp - the monotonicTimer for this context (taken from
|
||||
// window->performance.now() or from Now() -
|
||||
// workerPrivate->NowBaseTimeStamp() in workers.
|
||||
// * aTimerLabel - This label will be populated with the aName converted to a
|
||||
// string.
|
||||
// * aTimerDuration - the difference between aTimestamp and when the timer
|
||||
// started (see StartTimer).
|
||||
bool
|
||||
StopTimer(JSContext* aCx, const JS::Value& aName,
|
||||
DOMHighResTimeStamp aTimestamp,
|
||||
nsAString& aTimerLabel,
|
||||
double* aTimerDuration);
|
||||
|
||||
// This method generates a ConsoleTimerEnd dictionary exposed as JS::Value, or
|
||||
// a ConsoleTimerError dictionary if aTimerStatus is false. See StopTimer.
|
||||
// * aCx - this is the context that will root the returned value.
|
||||
// * aTimerLabel - this label must be what StopTimer received as aTimerLabel.
|
||||
// * aTimerDuration - this is what StopTimer received as aTimerDuration
|
||||
// * aTimerStatus - the return value of StopTimer.
|
||||
JS::Value
|
||||
CreateStopTimerValue(JSContext* aCx, const nsAString& aTimerLabel,
|
||||
double aTimerDuration,
|
||||
bool aTimerStatus) const;
|
||||
|
||||
// The method populates a Sequence from an array of JS::Value.
|
||||
bool
|
||||
ArgumentsToValueList(const Sequence<JS::Value>& aData,
|
||||
Sequence<JS::Value>& aSequence) const;
|
||||
|
||||
// This method follows the same pattern as StartTimer: its runs on the owning
|
||||
// thread and populate aCountLabel, used by CreateCounterValue. Returns
|
||||
// MAX_PAGE_COUNTERS in case of error, otherwise the incremented counter
|
||||
// value.
|
||||
// * aCx - the JSContext rooting aData.
|
||||
// * aFrame - the first frame of ConsoleCallData.
|
||||
// * aData - the arguments received by the console.count() method.
|
||||
// * aCountLabel - the label that will be populated by this method.
|
||||
uint32_t
|
||||
IncreaseCounter(JSContext* aCx, const ConsoleStackEntry& aFrame,
|
||||
const Sequence<JS::Value>& aData,
|
||||
nsAString& aCountLabel);
|
||||
|
||||
// This method generates a ConsoleCounter dictionary as JS::Value. If
|
||||
// aCountValue is == MAX_PAGE_COUNTERS it generates a ConsoleCounterError
|
||||
// instead. See IncreaseCounter.
|
||||
// * aCx - this is the context that will root the returned value.
|
||||
// * aCountLabel - this label must be what IncreaseCounter received as
|
||||
// aTimerLabel.
|
||||
// * aCountValue - the return value of IncreaseCounter.
|
||||
JS::Value
|
||||
CreateCounterValue(JSContext* aCx, const nsAString& aCountLabel,
|
||||
uint32_t aCountValue) const;
|
||||
|
||||
bool
|
||||
ShouldIncludeStackTrace(MethodName aMethodName) const;
|
||||
|
||||
JSObject*
|
||||
GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal);
|
||||
|
||||
void
|
||||
AssertIsOnOwningThread() const;
|
||||
|
||||
bool
|
||||
IsShuttingDown() const;
|
||||
|
||||
// All these nsCOMPtr are touched on main thread only.
|
||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||
nsCOMPtr<nsIConsoleAPIStorage> mStorage;
|
||||
RefPtr<JSObjectHolder> mSandbox;
|
||||
|
||||
// Touched on the owner thread.
|
||||
nsDataHashtable<nsStringHashKey, DOMHighResTimeStamp> mTimerRegistry;
|
||||
nsDataHashtable<nsStringHashKey, uint32_t> mCounterRegistry;
|
||||
|
||||
nsTArray<RefPtr<ConsoleCallData>> mCallDataStorage;
|
||||
|
||||
// This array is used in a particular corner-case where:
|
||||
// 1. we are in a worker thread
|
||||
// 2. we have more than STORAGE_MAX_EVENTS
|
||||
// 3. but the main-thread ConsoleCallDataRunnable of the first one is still
|
||||
// running (this means that something very bad is happening on the
|
||||
// main-thread).
|
||||
// When this happens we want to keep the ConsoleCallData alive for traceing
|
||||
// its JSValues also if 'officially' this ConsoleCallData must be removed from
|
||||
// the storage.
|
||||
nsTArray<RefPtr<ConsoleCallData>> mCallDataStoragePending;
|
||||
|
||||
RefPtr<AnyCallback> mConsoleEventNotifier;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRThread* mOwningThread;
|
||||
#endif
|
||||
|
||||
uint64_t mOuterID;
|
||||
uint64_t mInnerID;
|
||||
|
||||
enum {
|
||||
eUnknown,
|
||||
eInitialized,
|
||||
eShuttingDown
|
||||
} mStatus;
|
||||
|
||||
friend class ConsoleCallData;
|
||||
friend class ConsoleRunnable;
|
||||
friend class ConsoleCallDataRunnable;
|
||||
friend class ConsoleProfileRunnable;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_Console_h */
|
||||
2
dom/console/ConsoleAPI.manifest
Normal file
2
dom/console/ConsoleAPI.manifest
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
component {96cf7855-dfa9-4c6d-8276-f9705b4890f2} ConsoleAPIStorage.js
|
||||
contract @mozilla.org/consoleAPI-storage;1 {96cf7855-dfa9-4c6d-8276-f9705b4890f2}
|
||||
161
dom/console/ConsoleAPIStorage.js
Normal file
161
dom/console/ConsoleAPIStorage.js
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var Cu = Components.utils;
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// This constant tells how many messages to process in a single timer execution.
|
||||
const MESSAGES_IN_INTERVAL = 1500
|
||||
|
||||
const STORAGE_MAX_EVENTS = 1000;
|
||||
|
||||
var _consoleStorage = new Map();
|
||||
|
||||
const CONSOLEAPISTORAGE_CID = Components.ID('{96cf7855-dfa9-4c6d-8276-f9705b4890f2}');
|
||||
|
||||
/**
|
||||
* The ConsoleAPIStorage is meant to cache window.console API calls for later
|
||||
* reuse by other components when needed. For example, the Web Console code can
|
||||
* display the cached messages when it opens for the active tab.
|
||||
*
|
||||
* ConsoleAPI messages are stored as they come from the ConsoleAPI code, with
|
||||
* all their properties. They are kept around until the inner window object that
|
||||
* created the messages is destroyed. Messages are indexed by the inner window
|
||||
* ID.
|
||||
*
|
||||
* Usage:
|
||||
* Cu.import("resource://gre/modules/ConsoleAPIStorage.jsm");
|
||||
*
|
||||
* // Get the cached events array for the window you want (use the inner
|
||||
* // window ID).
|
||||
* let events = ConsoleAPIStorage.getEvents(innerWindowID);
|
||||
* events.forEach(function(event) { ... });
|
||||
*
|
||||
* // Clear the events for the given inner window ID.
|
||||
* ConsoleAPIStorage.clearEvents(innerWindowID);
|
||||
*/
|
||||
function ConsoleAPIStorageService() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
ConsoleAPIStorageService.prototype = {
|
||||
classID : CONSOLEAPISTORAGE_CID,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleAPIStorage,
|
||||
Ci.nsIObserver]),
|
||||
classInfo: XPCOMUtils.generateCI({
|
||||
classID: CONSOLEAPISTORAGE_CID,
|
||||
contractID: '@mozilla.org/consoleAPI-storage;1',
|
||||
interfaces: [Ci.nsIConsoleAPIStorage, Ci.nsIObserver],
|
||||
flags: Ci.nsIClassInfo.SINGLETON
|
||||
}),
|
||||
|
||||
observe: function CS_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
if (aTopic == "xpcom-shutdown") {
|
||||
Services.obs.removeObserver(this, "xpcom-shutdown");
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
Services.obs.removeObserver(this, "memory-pressure");
|
||||
}
|
||||
else if (aTopic == "inner-window-destroyed") {
|
||||
let innerWindowID = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
this.clearEvents(innerWindowID + "");
|
||||
}
|
||||
else if (aTopic == "memory-pressure") {
|
||||
this.clearEvents();
|
||||
}
|
||||
},
|
||||
|
||||
/** @private */
|
||||
init: function CS_init()
|
||||
{
|
||||
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
Services.obs.addObserver(this, "memory-pressure", false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the events array by inner window ID or all events from all windows.
|
||||
*
|
||||
* @param string [aId]
|
||||
* Optional, the inner window ID for which you want to get the array of
|
||||
* cached events.
|
||||
* @returns array
|
||||
* The array of cached events for the given window. If no |aId| is
|
||||
* given this function returns all of the cached events, from any
|
||||
* window.
|
||||
*/
|
||||
getEvents: function CS_getEvents(aId)
|
||||
{
|
||||
if (aId != null) {
|
||||
return (_consoleStorage.get(aId) || []).slice(0);
|
||||
}
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let [id, events] of _consoleStorage) {
|
||||
result.push.apply(result, events);
|
||||
}
|
||||
|
||||
return result.sort(function(a, b) {
|
||||
return a.timeStamp - b.timeStamp;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Record an event associated with the given window ID.
|
||||
*
|
||||
* @param string aId
|
||||
* The ID of the inner window for which the event occurred or "jsm" for
|
||||
* messages logged from JavaScript modules..
|
||||
* @param string aOuterId
|
||||
* This ID is used as 3rd parameters for the console-api-log-event
|
||||
* notification.
|
||||
* @param object aEvent
|
||||
* A JavaScript object you want to store.
|
||||
*/
|
||||
recordEvent: function CS_recordEvent(aId, aOuterId, aEvent)
|
||||
{
|
||||
if (!_consoleStorage.has(aId)) {
|
||||
_consoleStorage.set(aId, []);
|
||||
}
|
||||
|
||||
let storage = _consoleStorage.get(aId);
|
||||
storage.push(aEvent);
|
||||
|
||||
// truncate
|
||||
if (storage.length > STORAGE_MAX_EVENTS) {
|
||||
storage.shift();
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(aEvent, "console-api-log-event", aOuterId);
|
||||
Services.obs.notifyObservers(aEvent, "console-storage-cache-event", aId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear storage data for the given window.
|
||||
*
|
||||
* @param string [aId]
|
||||
* Optional, the inner window ID for which you want to clear the
|
||||
* messages. If this is not specified all of the cached messages are
|
||||
* cleared, from all window objects.
|
||||
*/
|
||||
clearEvents: function CS_clearEvents(aId)
|
||||
{
|
||||
if (aId != null) {
|
||||
_consoleStorage.delete(aId);
|
||||
}
|
||||
else {
|
||||
_consoleStorage.clear();
|
||||
Services.obs.notifyObservers(null, "console-storage-reset", null);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ConsoleAPIStorageService]);
|
||||
190
dom/console/ConsoleReportCollector.cpp
Normal file
190
dom/console/ConsoleReportCollector.cpp
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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/. */
|
||||
|
||||
#include "mozilla/ConsoleReportCollector.h"
|
||||
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
NS_IMPL_ISUPPORTS(ConsoleReportCollector, nsIConsoleReportCollector)
|
||||
|
||||
ConsoleReportCollector::ConsoleReportCollector()
|
||||
: mMutex("mozilla::ConsoleReportCollector")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ConsoleReportCollector::AddConsoleReport(uint32_t aErrorFlags,
|
||||
const nsACString& aCategory,
|
||||
nsContentUtils::PropertiesFile aPropertiesFile,
|
||||
const nsACString& aSourceFileURI,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
const nsACString& aMessageName,
|
||||
const nsTArray<nsString>& aStringParams)
|
||||
{
|
||||
// any thread
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
mPendingReports.AppendElement(PendingReport(aErrorFlags, aCategory,
|
||||
aPropertiesFile, aSourceFileURI,
|
||||
aLineNumber, aColumnNumber,
|
||||
aMessageName, aStringParams));
|
||||
}
|
||||
|
||||
void
|
||||
ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument,
|
||||
ReportAction aAction)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsTArray<PendingReport> reports;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (aAction == ReportAction::Forget) {
|
||||
mPendingReports.SwapElements(reports);
|
||||
} else {
|
||||
reports = mPendingReports;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < reports.Length(); ++i) {
|
||||
PendingReport& report = reports[i];
|
||||
|
||||
// It would be nice if we did not have to do this since ReportToConsole()
|
||||
// just turns around and converts it back to a spec.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (!report.mSourceFileURI.IsEmpty()) {
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), report.mSourceFileURI);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert back from nsTArray<nsString> to the char16_t** format required
|
||||
// by our l10n libraries and ReportToConsole. (bug 1219762)
|
||||
UniquePtr<const char16_t*[]> params;
|
||||
uint32_t paramsLength = report.mStringParams.Length();
|
||||
if (paramsLength > 0) {
|
||||
params = MakeUnique<const char16_t*[]>(paramsLength);
|
||||
for (uint32_t j = 0; j < paramsLength; ++j) {
|
||||
params[j] = report.mStringParams[j].get();
|
||||
}
|
||||
}
|
||||
|
||||
nsContentUtils::ReportToConsole(report.mErrorFlags, report.mCategory,
|
||||
aDocument, report.mPropertiesFile,
|
||||
report.mMessageName.get(),
|
||||
params.get(),
|
||||
paramsLength, uri, EmptyString(),
|
||||
report.mLineNumber, report.mColumnNumber);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConsoleReportCollector::FlushConsoleReports(nsIConsoleReportCollector* aCollector)
|
||||
{
|
||||
MOZ_ASSERT(aCollector);
|
||||
|
||||
nsTArray<PendingReport> reports;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mPendingReports.SwapElements(reports);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < reports.Length(); ++i) {
|
||||
PendingReport& report = reports[i];
|
||||
aCollector->AddConsoleReport(report.mErrorFlags, report.mCategory,
|
||||
report.mPropertiesFile, report.mSourceFileURI,
|
||||
report.mLineNumber, report.mColumnNumber,
|
||||
report.mMessageName, report.mStringParams);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConsoleReportCollector::FlushReportsByWindowId(uint64_t aWindowId,
|
||||
ReportAction aAction)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsTArray<PendingReport> reports;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
if (aAction == ReportAction::Forget) {
|
||||
mPendingReports.SwapElements(reports);
|
||||
} else {
|
||||
reports = mPendingReports;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIConsoleService> consoleService =
|
||||
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
if (!consoleService) {
|
||||
NS_WARNING("GetConsoleService failed");
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
for (uint32_t i = 0; i < reports.Length(); ++i) {
|
||||
PendingReport& report = reports[i];
|
||||
|
||||
nsXPIDLString errorText;
|
||||
if (!report.mStringParams.IsEmpty()) {
|
||||
rv = nsContentUtils::FormatLocalizedString(report.mPropertiesFile,
|
||||
report.mMessageName.get(),
|
||||
report.mStringParams,
|
||||
errorText);
|
||||
} else {
|
||||
rv = nsContentUtils::GetLocalizedString(report.mPropertiesFile,
|
||||
report.mMessageName.get(),
|
||||
errorText);
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptError> errorObject =
|
||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = errorObject->InitWithWindowID(errorText,
|
||||
NS_ConvertUTF8toUTF16(report.mSourceFileURI),
|
||||
EmptyString(),
|
||||
report.mLineNumber,
|
||||
report.mColumnNumber,
|
||||
report.mErrorFlags,
|
||||
report.mCategory,
|
||||
aWindowId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
consoleService->LogMessage(errorObject);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConsoleReportCollector::ClearConsoleReports()
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
mPendingReports.Clear();
|
||||
}
|
||||
|
||||
ConsoleReportCollector::~ConsoleReportCollector()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
84
dom/console/ConsoleReportCollector.h
Normal file
84
dom/console/ConsoleReportCollector.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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/. */
|
||||
|
||||
#ifndef mozilla_ConsoleReportCollector_h
|
||||
#define mozilla_ConsoleReportCollector_h
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsIConsoleReportCollector.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ConsoleReportCollector final : public nsIConsoleReportCollector
|
||||
{
|
||||
public:
|
||||
ConsoleReportCollector();
|
||||
|
||||
void
|
||||
AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory,
|
||||
nsContentUtils::PropertiesFile aPropertiesFile,
|
||||
const nsACString& aSourceFileURI,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
const nsACString& aMessageName,
|
||||
const nsTArray<nsString>& aStringParams) override;
|
||||
|
||||
void
|
||||
FlushConsoleReports(nsIDocument* aDocument,
|
||||
ReportAction aAction = ReportAction::Forget) override;
|
||||
|
||||
void
|
||||
FlushConsoleReports(nsIConsoleReportCollector* aCollector) override;
|
||||
|
||||
void
|
||||
FlushReportsByWindowId(uint64_t aWindowId,
|
||||
ReportAction aAction = ReportAction::Forget) override;
|
||||
|
||||
void
|
||||
ClearConsoleReports() override;
|
||||
|
||||
private:
|
||||
~ConsoleReportCollector();
|
||||
|
||||
struct PendingReport
|
||||
{
|
||||
PendingReport(uint32_t aErrorFlags, const nsACString& aCategory,
|
||||
nsContentUtils::PropertiesFile aPropertiesFile,
|
||||
const nsACString& aSourceFileURI, uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber, const nsACString& aMessageName,
|
||||
const nsTArray<nsString>& aStringParams)
|
||||
: mErrorFlags(aErrorFlags)
|
||||
, mCategory(aCategory)
|
||||
, mPropertiesFile(aPropertiesFile)
|
||||
, mSourceFileURI(aSourceFileURI)
|
||||
, mLineNumber(aLineNumber)
|
||||
, mColumnNumber(aColumnNumber)
|
||||
, mMessageName(aMessageName)
|
||||
, mStringParams(aStringParams)
|
||||
{ }
|
||||
|
||||
const uint32_t mErrorFlags;
|
||||
const nsCString mCategory;
|
||||
const nsContentUtils::PropertiesFile mPropertiesFile;
|
||||
const nsCString mSourceFileURI;
|
||||
const uint32_t mLineNumber;
|
||||
const uint32_t mColumnNumber;
|
||||
const nsCString mMessageName;
|
||||
const nsTArray<nsString> mStringParams;
|
||||
};
|
||||
|
||||
Mutex mMutex;
|
||||
|
||||
// protected by mMutex
|
||||
nsTArray<PendingReport> mPendingReports;
|
||||
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ConsoleReportCollector_h
|
||||
45
dom/console/moz.build
Normal file
45
dom/console/moz.build
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# -*- Mode: python; 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/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIConsoleAPIStorage.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom'
|
||||
|
||||
EXPORTS += [
|
||||
'nsIConsoleReportCollector.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'ConsoleReportCollector.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Console.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'Console.cpp',
|
||||
'ConsoleReportCollector.cpp',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'ConsoleAPI.manifest',
|
||||
'ConsoleAPIStorage.js',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/docshell/base',
|
||||
'/dom/base',
|
||||
'/dom/workers',
|
||||
'/js/xpconnect/src',
|
||||
]
|
||||
|
||||
MOCHITEST_MANIFESTS += [ 'tests/mochitest.ini' ]
|
||||
MOCHITEST_CHROME_MANIFESTS += [ 'tests/chrome.ini' ]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
47
dom/console/nsIConsoleAPIStorage.idl
Normal file
47
dom/console/nsIConsoleAPIStorage.idl
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(9e32a7b6-c4d1-4d9a-87b9-1ef6b75c27a9)]
|
||||
interface nsIConsoleAPIStorage : nsISupports
|
||||
{
|
||||
/**
|
||||
* Get the events array by inner window ID or all events from all windows.
|
||||
*
|
||||
* @param string [aId]
|
||||
* Optional, the inner window ID for which you want to get the array of
|
||||
* cached events.
|
||||
* @returns array
|
||||
* The array of cached events for the given window. If no |aId| is
|
||||
* given this function returns all of the cached events, from any
|
||||
* window.
|
||||
*/
|
||||
jsval getEvents([optional] in DOMString aId);
|
||||
|
||||
/**
|
||||
* Record an event associated with the given window ID.
|
||||
*
|
||||
* @param string aId
|
||||
* The ID of the inner window for which the event occurred or "jsm" for
|
||||
* messages logged from JavaScript modules..
|
||||
* @param string aOuterId
|
||||
* This ID is used as 3rd parameters for the console-api-log-event
|
||||
* notification.
|
||||
* @param object aEvent
|
||||
* A JavaScript object you want to store.
|
||||
*/
|
||||
void recordEvent(in DOMString aId, in DOMString aOuterId, in jsval aEvent);
|
||||
|
||||
/**
|
||||
* Clear storage data for the given window.
|
||||
*
|
||||
* @param string [aId]
|
||||
* Optional, the inner window ID for which you want to clear the
|
||||
* messages. If this is not specified all of the cached messages are
|
||||
* cleared, from all window objects.
|
||||
*/
|
||||
void clearEvents([optional] in DOMString aId);
|
||||
};
|
||||
115
dom/console/nsIConsoleReportCollector.h
Normal file
115
dom/console/nsIConsoleReportCollector.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=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/. */
|
||||
|
||||
#ifndef nsIConsoleReportCollector_h
|
||||
#define nsIConsoleReportCollector_h
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
|
||||
class nsACString;
|
||||
class nsIDocument;
|
||||
class nsString;
|
||||
|
||||
#define NS_NSICONSOLEREPORTCOLLECTOR_IID \
|
||||
{0xdd98a481, 0xd2c4, 0x4203, {0x8d, 0xfa, 0x85, 0xbf, 0xd7, 0xdc, 0xd7, 0x05}}
|
||||
|
||||
// An interface for saving reports until we can flush them to the correct
|
||||
// window at a later time.
|
||||
class NS_NO_VTABLE nsIConsoleReportCollector : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NSICONSOLEREPORTCOLLECTOR_IID)
|
||||
|
||||
// Add a pending report to be later displayed on the console. This may be
|
||||
// called from any thread.
|
||||
//
|
||||
// aErrorFlags A nsIScriptError flags value.
|
||||
// aCategory Name of module reporting error.
|
||||
// aPropertiesFile Properties file containing localized message.
|
||||
// aSourceFileURI The URI of the script generating the error. Must be a URI
|
||||
// spec.
|
||||
// aLineNumber The line number where the error was generated. May be 0 if
|
||||
// the line number is not known.
|
||||
// aColumnNumber The column number where the error was generated. May be 0
|
||||
// if the line number is not known.
|
||||
// aMessageName The name of the localized message contained in the
|
||||
// properties file.
|
||||
// aStringParams An array of nsString parameters to use when localizing the
|
||||
// message.
|
||||
virtual void
|
||||
AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory,
|
||||
nsContentUtils::PropertiesFile aPropertiesFile,
|
||||
const nsACString& aSourceFileURI, uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber, const nsACString& aMessageName,
|
||||
const nsTArray<nsString>& aStringParams) = 0;
|
||||
|
||||
// A version of AddConsoleReport() that accepts the message parameters
|
||||
// as variable nsString arguments (or really, any sort of const nsAString).
|
||||
// All other args the same as AddConsoleReport().
|
||||
template<typename... Params>
|
||||
void
|
||||
AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory,
|
||||
nsContentUtils::PropertiesFile aPropertiesFile,
|
||||
const nsACString& aSourceFileURI, uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber, const nsACString& aMessageName,
|
||||
Params&&... aParams)
|
||||
{
|
||||
nsTArray<nsString> params;
|
||||
mozilla::dom::StringArrayAppender::Append(params, sizeof...(Params),
|
||||
mozilla::Forward<Params>(aParams)...);
|
||||
AddConsoleReport(aErrorFlags, aCategory, aPropertiesFile, aSourceFileURI,
|
||||
aLineNumber, aColumnNumber, aMessageName, params);
|
||||
}
|
||||
|
||||
// An enum calss to indicate whether should free the pending reports or not.
|
||||
// Forget Free the pending reports.
|
||||
// Save Keep the pending reports.
|
||||
enum class ReportAction {
|
||||
Forget,
|
||||
Save
|
||||
};
|
||||
|
||||
// Flush all pending reports to the console. Main thread only.
|
||||
//
|
||||
// aDocument An optional document representing where to flush the
|
||||
// reports. If provided, then the corresponding window's
|
||||
// web console will get the reports. Otherwise the reports
|
||||
// go to the browser console.
|
||||
// aAction An action to determine whether to reserve the pending
|
||||
// reports. Defalut action is to forget the report.
|
||||
virtual void
|
||||
FlushConsoleReports(nsIDocument* aDocument,
|
||||
ReportAction aAction = ReportAction::Forget) = 0;
|
||||
|
||||
// Flush all pending reports to another collector. May be called from any
|
||||
// thread.
|
||||
//
|
||||
// aCollector A required collector object that will effectively take
|
||||
// ownership of our currently console reports.
|
||||
virtual void
|
||||
FlushConsoleReports(nsIConsoleReportCollector* aCollector) = 0;
|
||||
|
||||
// Flush all pending reports to the console accroding to window ID. Main
|
||||
// thread only.
|
||||
//
|
||||
// aWindowId A window ID representing where to flush the reports and it's
|
||||
// typically the inner window ID.
|
||||
//
|
||||
// aAction An action to decide whether free the pending reports or not.
|
||||
virtual void
|
||||
FlushReportsByWindowId(uint64_t aWindowId,
|
||||
ReportAction aAction = ReportAction::Forget) = 0;
|
||||
|
||||
// Clear all pending reports.
|
||||
virtual void
|
||||
ClearConsoleReports() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIConsoleReportCollector, NS_NSICONSOLEREPORTCOLLECTOR_IID)
|
||||
|
||||
#endif // nsIConsoleReportCollector_h
|
||||
6
dom/console/tests/chrome.ini
Normal file
6
dom/console/tests/chrome.ini
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[DEFAULT]
|
||||
skip-if = os == 'android'
|
||||
support-files =
|
||||
file_empty.html
|
||||
|
||||
[test_console.xul]
|
||||
1
dom/console/tests/file_empty.html
Normal file
1
dom/console/tests/file_empty.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html><body></body></html>
|
||||
11
dom/console/tests/mochitest.ini
Normal file
11
dom/console/tests/mochitest.ini
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
file_empty.html
|
||||
|
||||
[test_bug659625.html]
|
||||
[test_bug978522.html]
|
||||
[test_bug979109.html]
|
||||
[test_bug989665.html]
|
||||
[test_consoleEmptyStack.html]
|
||||
[test_console_binding.html]
|
||||
[test_console_proto.html]
|
||||
92
dom/console/tests/test_bug659625.html
Normal file
92
dom/console/tests/test_bug659625.html
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=659625
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 659625</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=659625">Mozilla Bug 659625</a>
|
||||
<script type="application/javascript">
|
||||
const { Cc, Ci } = SpecialPowers;
|
||||
let consoleStorage = Cc["@mozilla.org/consoleAPI-storage;1"];
|
||||
let storage = consoleStorage.getService(Ci.nsIConsoleAPIStorage);
|
||||
|
||||
let clearAndCheckStorage = () => {
|
||||
console.clear();
|
||||
ok(storage.getEvents().length === 1,
|
||||
"Only one event remains in consoleAPIStorage");
|
||||
ok(storage.getEvents()[0].level === "clear",
|
||||
"Remaining event has level 'clear'");
|
||||
}
|
||||
|
||||
storage.clearEvents();
|
||||
ok(storage.getEvents().length === 0,
|
||||
"Console is empty when test is starting");
|
||||
clearAndCheckStorage();
|
||||
|
||||
console.log("log");
|
||||
console.debug("debug");
|
||||
console.warn("warn");
|
||||
console.error("error");
|
||||
console.exception("exception");
|
||||
ok(storage.getEvents().length === 6,
|
||||
"5 new console events have been registered for logging variants");
|
||||
clearAndCheckStorage();
|
||||
|
||||
console.trace();
|
||||
ok(storage.getEvents().length === 2,
|
||||
"1 new console event registered for trace");
|
||||
clearAndCheckStorage();
|
||||
|
||||
console.dir({});
|
||||
ok(storage.getEvents().length === 2,
|
||||
"1 new console event registered for dir");
|
||||
clearAndCheckStorage();
|
||||
|
||||
console.count("count-label");
|
||||
console.count("count-label");
|
||||
ok(storage.getEvents().length === 3,
|
||||
"2 new console events registered for 2 count calls");
|
||||
clearAndCheckStorage();
|
||||
|
||||
console.group("group-label")
|
||||
console.log("group-log");
|
||||
ok(storage.getEvents().length === 3,
|
||||
"2 new console events registered for group + log");
|
||||
clearAndCheckStorage();
|
||||
|
||||
console.groupCollapsed("group-collapsed")
|
||||
console.log("group-collapsed-log");
|
||||
ok(storage.getEvents().length === 3,
|
||||
"2 new console events registered for groupCollapsed + log");
|
||||
clearAndCheckStorage();
|
||||
|
||||
console.group("closed-group-label")
|
||||
console.log("group-log");
|
||||
console.groupEnd()
|
||||
ok(storage.getEvents().length === 4,
|
||||
"3 new console events registered for group/groupEnd");
|
||||
clearAndCheckStorage();
|
||||
|
||||
console.time("time-label");
|
||||
console.timeEnd();
|
||||
ok(storage.getEvents().length === 3,
|
||||
"2 new console events registered for time/timeEnd");
|
||||
clearAndCheckStorage();
|
||||
|
||||
console.timeStamp("timestamp-label");
|
||||
ok(storage.getEvents().length === 2,
|
||||
"1 new console event registered for timeStamp");
|
||||
clearAndCheckStorage();
|
||||
|
||||
// Check that console.clear() clears previous clear messages
|
||||
clearAndCheckStorage();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
32
dom/console/tests/test_bug978522.html
Normal file
32
dom/console/tests/test_bug978522.html
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=978522
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 978522 - basic support</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=978522">Mozilla Bug 978522</a>
|
||||
<script type="application/javascript">
|
||||
|
||||
console.log('%s', {
|
||||
toString: function() {
|
||||
console.log('%s', {
|
||||
toString: function() {
|
||||
ok(true, "Still alive \\o/");
|
||||
SimpleTest.finish();
|
||||
return "hello world";
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
32
dom/console/tests/test_bug979109.html
Normal file
32
dom/console/tests/test_bug979109.html
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=979109
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 979109</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=979109">Mozilla Bug 979109</a>
|
||||
<script type="application/javascript">
|
||||
|
||||
console.warn("%", "a");
|
||||
console.warn("%%", "a");
|
||||
console.warn("%123", "a");
|
||||
console.warn("%123.", "a");
|
||||
console.warn("%123.123", "a");
|
||||
console.warn("%123.123o", "a");
|
||||
console.warn("%123.123s", "a");
|
||||
console.warn("%123.123d", "a");
|
||||
console.warn("%123.123f", "a");
|
||||
console.warn("%123.123z", "a");
|
||||
console.warn("%.", "a");
|
||||
console.warn("%.123", "a");
|
||||
ok(true, "Still alive \\o/");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
21
dom/console/tests/test_bug989665.html
Normal file
21
dom/console/tests/test_bug989665.html
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=989665
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 989665</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=989665">Mozilla Bug 989665</a>
|
||||
<script type="application/javascript">
|
||||
|
||||
w = new Worker("data:text/javascript;charset=UTF-8, console.log('%s', {toString: function() { throw 3 }}); ");
|
||||
ok(true, "This test should not crash.");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
35
dom/console/tests/test_console.xul
Normal file
35
dom/console/tests/test_console.xul
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<window title="Test for URL API"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<iframe id="iframe" />
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
ok("console" in window, "Console exists");
|
||||
window.console.log(42);
|
||||
ok("table" in console, "Console has the 'table' method.");
|
||||
window.console = 42;
|
||||
is(window.console, 42, "Console is replacable");
|
||||
|
||||
var frame = document.getElementById("iframe");
|
||||
ok(frame, "Frame must exist");
|
||||
frame.src="http://mochi.test:8888/tests/dom/console/test/file_empty.html";
|
||||
frame.onload = function() {
|
||||
ok("console" in frame.contentWindow, "Console exists in the iframe");
|
||||
frame.contentWindow.console.log(42);
|
||||
frame.contentWindow.console = 42;
|
||||
is(frame.contentWindow.console, 42, "Console is replacable in the iframe");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
]]></script>
|
||||
</window>
|
||||
27
dom/console/tests/test_consoleEmptyStack.html
Normal file
27
dom/console/tests/test_consoleEmptyStack.html
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Test for empty stack in console</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.setTimeout(console.log.bind(console), 0, "xyz");
|
||||
|
||||
window.addEventListener("fake", console.log.bind(console, "xyz"));
|
||||
|
||||
window.addEventListener("fake", function() {
|
||||
ok(true, "Still alive");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
window.dispatchEvent(new Event("fake"));
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
42
dom/console/tests/test_console_binding.html
Normal file
42
dom/console/tests/test_console_binding.html
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test Console binding</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
|
||||
function consoleListener() {
|
||||
SpecialPowers.addObserver(this, "console-api-log-event", false);
|
||||
}
|
||||
|
||||
var order = 0;
|
||||
consoleListener.prototype = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "console-api-log-event") {
|
||||
var obj = aSubject.wrappedJSObject;
|
||||
if (order+1 == parseInt(obj.arguments[0])) {
|
||||
ok(true, "Message received: " + obj.arguments[0]);
|
||||
order++;
|
||||
}
|
||||
|
||||
if (order == 3) {
|
||||
SpecialPowers.removeObserver(this, "console-api-log-event");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var cl = new consoleListener();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
[1,2,3].forEach(console.log);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
17
dom/console/tests/test_console_proto.html
Normal file
17
dom/console/tests/test_console_proto.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for console.__proto__</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
|
||||
isnot(Object.getPrototypeOf(console), Object.prototype, "Foo");
|
||||
is(Object.getPrototypeOf(Object.getPrototypeOf(console)), Object.prototype, "Boo");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue