Bug 1425574 - Fill the feature gap between Console.jsm and Console API - part 1 - Console.createInstance(), r=smaug

This commit is contained in:
Andrea Marchesini 2018-01-04 19:19:43 +01:00
Родитель 08ad867b55
Коммит d820259403
9 изменённых файлов: 349 добавлений и 15 удалений

Просмотреть файл

@ -153,6 +153,10 @@ DOMInterfaces = {
'nativeType': 'mozilla::dom::Console',
},
'ConsoleInstance': {
'implicitJSContext': ['clear', 'count', 'groupEnd', 'time', 'timeEnd'],
},
'ConvolverNode': {
'implicitJSContext': [ 'buffer' ],
},

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/Console.h"
#include "mozilla/dom/ConsoleInstance.h"
#include "mozilla/dom/ConsoleBinding.h"
#include "mozilla/dom/BlobBinding.h"
@ -950,13 +951,6 @@ METHOD(Debug, "debug")
METHOD(Table, "table")
METHOD(Trace, "trace")
/* static */ void
Console::Clear(const GlobalObject& aGlobal)
{
const Sequence<JS::Value> data;
Method(aGlobal, MethodClear, NS_LITERAL_STRING("clear"), data);
}
// Displays an interactive listing of all the properties of an object.
METHOD(Dir, "dir");
METHOD(Dirxml, "dirxml");
@ -964,6 +958,15 @@ METHOD(Dirxml, "dirxml");
METHOD(Group, "group")
METHOD(GroupCollapsed, "groupCollapsed")
#undef METHOD
/* static */ void
Console::Clear(const GlobalObject& aGlobal)
{
const Sequence<JS::Value> data;
Method(aGlobal, MethodClear, NS_LITERAL_STRING("clear"), data);
}
/* static */ void
Console::GroupEnd(const GlobalObject& aGlobal)
{
@ -987,15 +990,27 @@ Console::TimeEnd(const GlobalObject& aGlobal, const nsAString& aLabel)
Console::StringMethod(const GlobalObject& aGlobal, const nsAString& aLabel,
MethodName aMethodName, const nsAString& aMethodString)
{
JSContext* cx = aGlobal.Context();
RefPtr<Console> console = GetConsole(aGlobal);
if (!console) {
return;
}
ClearException ce(cx);
console->StringMethodInternal(aGlobal.Context(), aLabel, aMethodName,
aMethodString);
}
void
Console::StringMethodInternal(JSContext* aCx, const nsAString& aLabel,
MethodName aMethodName,
const nsAString& aMethodString)
{
ClearException ce(aCx);
Sequence<JS::Value> data;
SequenceRooter<JS::Value> rooter(cx, &data);
SequenceRooter<JS::Value> rooter(aCx, &data);
JS::Rooted<JS::Value> value(cx);
if (!dom::ToJSValue(cx, aLabel, &value)) {
JS::Rooted<JS::Value> value(aCx);
if (!dom::ToJSValue(aCx, aLabel, &value)) {
return;
}
@ -1003,7 +1018,7 @@ Console::StringMethod(const GlobalObject& aGlobal, const nsAString& aLabel,
return;
}
Method(aGlobal, aMethodName, aMethodString, data);
MethodInternal(aCx, aMethodName, aMethodString, data);
}
/* static */ void
@ -2537,5 +2552,13 @@ Console::MonotonicTimer(JSContext* aCx, MethodName aMethodName,
return true;
}
/* static */ already_AddRefed<ConsoleInstance>
Console::CreateInstance(const GlobalObject& aGlobal,
const ConsoleInstanceOptions& aOptions)
{
RefPtr<ConsoleInstance> console = new ConsoleInstance(aOptions);
return console.forget();
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -27,9 +27,11 @@ namespace dom {
class AnyCallback;
class ConsoleCallData;
class ConsoleInstance;
class ConsoleRunnable;
class ConsoleCallDataRunnable;
class ConsoleProfileRunnable;
struct ConsoleInstanceOptions;
struct ConsoleTimerError;
struct ConsoleStackEntry;
@ -114,6 +116,10 @@ public:
static void
Clear(const GlobalObject& aGlobal);
static already_AddRefed<ConsoleInstance>
CreateInstance(const GlobalObject& aGlobal,
const ConsoleInstanceOptions& aOptions);
void
ClearStorage();
@ -183,6 +189,10 @@ private:
StringMethod(const GlobalObject& aGlobal, const nsAString& aLabel,
MethodName aMethodName, const nsAString& aMethodString);
void
StringMethodInternal(JSContext* aCx, const nsAString& aLabel,
MethodName aMethodName, const nsAString& aMethodString);
// This method must receive aCx and aArguments in the same JSCompartment.
void
ProcessCallData(JSContext* aCx,
@ -417,6 +427,7 @@ private:
mozilla::TimeStamp mCreationTimeStamp;
friend class ConsoleCallData;
friend class ConsoleInstance;
friend class ConsoleRunnable;
friend class ConsoleCallDataRunnable;
friend class ConsoleProfileRunnable;

Просмотреть файл

@ -0,0 +1,134 @@
/* -*- 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/dom/ConsoleInstance.h"
#include "mozilla/dom/ConsoleBinding.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ConsoleInstance, mConsole)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ConsoleInstance)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ConsoleInstance)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ConsoleInstance)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_END
ConsoleInstance::ConsoleInstance(const ConsoleInstanceOptions& aOptions)
: mConsole(new Console(nullptr))
{}
ConsoleInstance::~ConsoleInstance()
{}
JSObject*
ConsoleInstance::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return ConsoleInstanceBinding::Wrap(aCx, this, aGivenProto);
}
#define METHOD(name, string) \
void \
ConsoleInstance::name(JSContext* aCx, const Sequence<JS::Value>& aData) \
{ \
mConsole->MethodInternal(aCx, Console::Method##name, \
NS_LITERAL_STRING(string), aData); \
}
METHOD(Log, "log")
METHOD(Info, "info")
METHOD(Warn, "warn")
METHOD(Error, "error")
METHOD(Exception, "exception")
METHOD(Debug, "debug")
METHOD(Table, "table")
METHOD(Trace, "trace")
METHOD(Dir, "dir");
METHOD(Dirxml, "dirxml");
METHOD(Group, "group")
METHOD(GroupCollapsed, "groupCollapsed")
#undef METHOD
void
ConsoleInstance::GroupEnd(JSContext* aCx)
{
const Sequence<JS::Value> data;
mConsole->MethodInternal(aCx, Console::MethodGroupEnd,
NS_LITERAL_STRING("groupEnd"), data);
}
void
ConsoleInstance::Time(JSContext* aCx, const nsAString& aLabel)
{
mConsole->StringMethodInternal(aCx, aLabel, Console::MethodTime,
NS_LITERAL_STRING("time"));
}
void
ConsoleInstance::TimeEnd(JSContext* aCx, const nsAString& aLabel)
{
mConsole->StringMethodInternal(aCx, aLabel, Console::MethodTimeEnd,
NS_LITERAL_STRING("timeEnd"));
}
void
ConsoleInstance::TimeStamp(JSContext* aCx, const JS::Handle<JS::Value> aData)
{
ClearException ce(aCx);
Sequence<JS::Value> data;
SequenceRooter<JS::Value> rooter(aCx, &data);
if (aData.isString() && !data.AppendElement(aData, fallible)) {
return;
}
mConsole->MethodInternal(aCx, Console::MethodTimeStamp,
NS_LITERAL_STRING("timeStamp"), data);
}
void
ConsoleInstance::Profile(JSContext* aCx, const Sequence<JS::Value>& aData)
{
mConsole->ProfileMethodInternal(aCx, NS_LITERAL_STRING("profile"), aData);
}
void
ConsoleInstance::ProfileEnd(JSContext* aCx, const Sequence<JS::Value>& aData)
{
mConsole->ProfileMethodInternal(aCx, NS_LITERAL_STRING("profileEnd"), aData);
}
void
ConsoleInstance::Assert(JSContext* aCx, bool aCondition,
const Sequence<JS::Value>& aData)
{
if (!aCondition) {
mConsole->MethodInternal(aCx, Console::MethodAssert,
NS_LITERAL_STRING("assert"), aData);
}
}
void
ConsoleInstance::Count(JSContext* aCx, const nsAString& aLabel)
{
mConsole->StringMethodInternal(aCx, aLabel, Console::MethodCount,
NS_LITERAL_STRING("count"));
}
void
ConsoleInstance::Clear(JSContext* aCx)
{
const Sequence<JS::Value> data;
mConsole->MethodInternal(aCx, Console::MethodClear,
NS_LITERAL_STRING("clear"), data);
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,106 @@
/* -*- 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_ConsoleInstance_h
#define mozilla_dom_ConsoleInstance_h
#include "mozilla/dom/Console.h"
namespace mozilla {
namespace dom {
class ConsoleInstance final : public nsISupports
, public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ConsoleInstance)
explicit ConsoleInstance(const ConsoleInstanceOptions& aOptions);
// WebIDL methods
JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
nsPIDOMWindowInner* GetParentObject() const
{
return nullptr;
}
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
Table(JSContext* aCx, const Sequence<JS::Value>& aData);
void
Trace(JSContext* aCx, const Sequence<JS::Value>& aData);
void
Dir(JSContext* aCx, const Sequence<JS::Value>& aData);
void
Dirxml(JSContext* aCx, const Sequence<JS::Value>& aData);
void
Group(JSContext* aCx, const Sequence<JS::Value>& aData);
void
GroupCollapsed(JSContext* aCx, const Sequence<JS::Value>& aData);
void
GroupEnd(JSContext* aCx);
void
Time(JSContext* aCx, const nsAString& aLabel);
void
TimeEnd(JSContext* aCx, const nsAString& aLabel);
void
TimeStamp(JSContext* aCx, const JS::Handle<JS::Value> aData);
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
Count(JSContext* aCx, const nsAString& aLabel);
void
Clear(JSContext* aCx);
private:
~ConsoleInstance();
RefPtr<Console> mConsole;
};
} // dom namespace
} // mozilla namespace
#endif // mozilla_dom_ConsoleInstance_h

Просмотреть файл

@ -23,10 +23,12 @@ EXPORTS.mozilla += [
EXPORTS.mozilla.dom += [
'Console.h',
'ConsoleInstance.h',
]
UNIFIED_SOURCES += [
'Console.cpp',
'ConsoleInstance.cpp',
'ConsoleReportCollector.cpp',
]

Просмотреть файл

@ -7,5 +7,6 @@ this.EXPORTED_SYMBOLS = [ "ConsoleTest" ];
this.ConsoleTest = {
go: function() {
console.log("Hello world!");
console.createInstance().log("Hello world!");
}
};

Просмотреть файл

@ -22,6 +22,8 @@ function consoleListener() {
}
consoleListener.prototype = {
count: 0,
observe: function(aSubject, aTopic, aData) {
if (aTopic == "console-api-log-event") {
var obj = aSubject.wrappedJSObject;
@ -29,8 +31,12 @@ consoleListener.prototype = {
is(obj.ID, "jsm", "ID and InnerID are correctly set.");
is (obj.arguments[0], "Hello world!", "Message matches");
SpecialPowers.removeObserver(this, "console-api-log-event");
SimpleTest.finish();
// We want to see 2 messages, the first is generated by console.log,
// the second one from createInstance().log();
if (++this.count == 2) {
SpecialPowers.removeObserver(this, "console-api-log-event");
SimpleTest.finish();
}
}
}
}

Просмотреть файл

@ -12,6 +12,10 @@
ClassString="Console",
ProtoObjectHack]
namespace console {
// NOTE: if you touch this namespace, remember to update the ConsoleInstance
// interface as well!
// Logging
void assert(optional boolean condition = false, any... data);
void clear();
@ -45,6 +49,9 @@ namespace console {
[ChromeOnly]
const boolean IS_NATIVE_CONSOLE = true;
[ChromeOnly, NewObject]
ConsoleInstance createInstance(optional ConsoleInstanceOptions options);
};
// This is used to propagate console events to the observers.
@ -109,3 +116,43 @@ dictionary ConsoleCounter {
dictionary ConsoleCounterError {
DOMString error = "maxCountersExceeded";
};
[ChromeOnly,
Exposed=(Window,Worker,WorkerDebugger,Worklet,System)]
// This is basically a copy of the console namespace.
interface ConsoleInstance {
// Logging
void assert(optional boolean condition = false, any... data);
void clear();
void count(optional DOMString label = "default");
void debug(any... data);
void error(any... data);
void info(any... data);
void log(any... data);
void table(any... data); // FIXME: The spec is still unclear about this.
void trace(any... data);
void warn(any... data);
void dir(any... data); // FIXME: This doesn't follow the spec yet.
void dirxml(any... data);
// Grouping
void group(any... data);
void groupCollapsed(any... data);
void groupEnd();
// Timing
void time(optional DOMString label = "default");
void timeEnd(optional DOMString label = "default");
// Mozilla only or Webcompat methods
void _exception(any... data);
void timeStamp(optional any data);
void profile(any... data);
void profileEnd(any... data);
};
dictionary ConsoleInstanceOptions {
// TODO
};