Auto merge of #13185 - nox:namespaces, r=jdm,Ms2ger

Make console a namespace (fixes #13010)

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13185)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-09-10 07:33:25 -05:00 committed by GitHub
commit 84f3cf22bf
16 changed files with 223 additions and 120 deletions

View file

@ -26,6 +26,7 @@ from WebIDL import (
)
from Configuration import (
MakeNativeName,
MemberIsUnforgeable,
getModuleFromObject,
getTypesFromCallback,
@ -80,7 +81,7 @@ def toStringBool(arg):
def toBindingNamespace(arg):
return re.sub("((_workers)?$)", "Binding\\1", arg)
return re.sub("((_workers)?$)", "Binding\\1", MakeNativeName(arg))
def stripTrailingWhitespace(text):
@ -96,9 +97,6 @@ def innerSequenceType(type):
return type.inner.inner if type.nullable() else type.inner
def MakeNativeName(name):
return name[0].upper() + name[1:]
builtinNames = {
IDLType.Tags.bool: 'bool',
IDLType.Tags.int8: 'i8',
@ -1811,7 +1809,8 @@ class CGImports(CGWrapper):
def isImportable(type):
if not type.isType():
assert type.isInterface() or type.isDictionary() or type.isEnum()
assert (type.isInterface() or type.isDictionary() or
type.isEnum() or type.isNamespace())
return True
return not (type.builtin or type.isSequence() or type.isUnion())
@ -1830,7 +1829,7 @@ class CGImports(CGWrapper):
if t.isCallback():
return t.callback.identifier
return t.identifier
assert t.isInterface() or t.isDictionary() or t.isEnum()
assert t.isInterface() or t.isDictionary() or t.isEnum() or t.isNamespace()
return t.identifier
def removeWrapperAndNullableTypes(types):
@ -1881,7 +1880,7 @@ class CGImports(CGWrapper):
# Importing these types in the same module that defines them is an error.
if t in dictionaries or t in enums:
continue
if t.isInterface():
if t.isInterface() or t.isNamespace():
descriptor = descriptorProvider.getDescriptor(getIdentifier(t).name)
extras += [descriptor.path]
if descriptor.interface.parent:
@ -2060,6 +2059,17 @@ class CGInterfaceObjectJSClass(CGThing):
self.descriptor = descriptor
def define(self):
if self.descriptor.interface.isNamespace():
classString = self.descriptor.interface.getExtendedAttribute("ClassString")
if classString:
classString = classString[0]
else:
classString = "Object"
return """\
static NAMESPACE_OBJECT_CLASS: NamespaceObjectClass = unsafe {
NamespaceObjectClass::new(%s)
};
""" % str_to_const_array(classString)
if self.descriptor.interface.ctor():
constructorBehavior = "InterfaceConstructorBehavior::call(%s)" % CONSTRUCT_HOOK_NAME
else:
@ -2659,6 +2669,28 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
def definition_body(self):
name = self.descriptor.interface.identifier.name
if self.descriptor.interface.isNamespace():
if self.descriptor.interface.getExtendedAttribute("ProtoObjectHack"):
proto = "JS_GetObjectPrototype(cx, global)"
else:
proto = "JS_NewPlainObject(cx)"
if self.properties.static_methods.length():
methods = self.properties.static_methods.variableName()
else:
methods = "&[]"
return CGGeneric("""\
rooted!(in(cx) let proto = %(proto)s);
assert!(!proto.is_null());
rooted!(in(cx) let mut namespace = ptr::null_mut());
create_namespace_object(cx, global, proto.handle(), &NAMESPACE_OBJECT_CLASS,
%(methods)s, %(name)s, namespace.handle_mut());
assert!(!namespace.is_null());
assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
(*cache)[PrototypeList::Constructor::%(id)s as usize] = namespace.get();
<*mut JSObject>::post_barrier((*cache).as_mut_ptr().offset(PrototypeList::Constructor::%(id)s as isize),
ptr::null_mut(),
namespace.get());
""" % {"id": MakeNativeName(name), "methods": methods, "name": str_to_const_array(name), "proto": proto})
if self.descriptor.interface.isCallback():
assert not self.descriptor.interface.ctor() and self.descriptor.interface.hasConstants()
return CGGeneric("""\
@ -2873,7 +2905,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
Argument('MutableHandleObject', 'rval')]
CGAbstractMethod.__init__(self, descriptor, name,
'void', args, pub=pub, unsafe=True)
self.id = idPrefix + "::" + self.descriptor.name
self.id = idPrefix + "::" + MakeNativeName(self.descriptor.name)
def definition_body(self):
return CGGeneric("""
@ -3016,7 +3048,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
return CGAbstractMethod.define(self)
def definition_body(self):
if self.descriptor.interface.isCallback():
if self.descriptor.interface.isCallback() or self.descriptor.interface.isNamespace():
function = "GetConstructorObject"
else:
function = "GetProtoObject"
@ -3047,7 +3079,7 @@ class CGCallGenerator(CGThing):
exception from the native code, or None if no error reporting is needed.
"""
def __init__(self, errorResult, arguments, argsPre, returnType,
extendedAttributes, descriptorProvider, nativeMethodName,
extendedAttributes, descriptor, nativeMethodName,
static, object="this"):
CGThing.__init__(self)
@ -3055,7 +3087,7 @@ class CGCallGenerator(CGThing):
isFallible = errorResult is not None
result = getRetvalDeclarationForType(returnType, descriptorProvider)
result = getRetvalDeclarationForType(returnType, descriptor)
if isFallible:
result = CGWrapper(result, pre="Result<", post=", Error>")
@ -3076,7 +3108,7 @@ class CGCallGenerator(CGThing):
call = CGGeneric(nativeMethodName)
if static:
call = CGWrapper(call, pre="%s::" % descriptorProvider.interface.identifier.name)
call = CGWrapper(call, pre="%s::" % MakeNativeName(descriptor.interface.identifier.name))
else:
call = CGWrapper(call, pre="%s." % object)
call = CGList([call, CGWrapper(args, pre="(", post=")")])
@ -5454,6 +5486,8 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
'dom::bindings::js::OptionalRootedReference',
'dom::bindings::js::Root',
'dom::bindings::js::RootedReference',
'dom::bindings::namespace::NamespaceObjectClass',
'dom::bindings::namespace::create_namespace_object',
'dom::bindings::reflector::MutReflectable',
'dom::bindings::reflector::Reflectable',
'dom::bindings::utils::DOMClass',
@ -5561,7 +5595,7 @@ class CGDescriptor(CGThing):
return name
cgThings = []
if not descriptor.interface.isCallback():
if not descriptor.interface.isCallback() and not descriptor.interface.isNamespace():
cgThings.append(CGGetProtoObjectMethod(descriptor))
reexports.append('GetProtoObject')
if (descriptor.interface.hasInterfaceObject() and
@ -5622,7 +5656,7 @@ class CGDescriptor(CGThing):
if not descriptor.interface.isCallback():
cgThings.append(CGInterfaceObjectJSClass(descriptor))
if not descriptor.interface.isCallback():
if not descriptor.interface.isCallback() and not descriptor.interface.isNamespace():
cgThings.append(CGPrototypeJSClass(descriptor))
# If there are no constant members, don't make a module for constants
@ -5679,7 +5713,7 @@ class CGDescriptor(CGThing):
reexports.append('Wrap')
haveUnscopables = False
if not descriptor.interface.isCallback():
if not descriptor.interface.isCallback() and not descriptor.interface.isNamespace():
if unscopableNames:
haveUnscopables = True
cgThings.append(
@ -5706,7 +5740,7 @@ class CGDescriptor(CGThing):
cgThings, public=True),
post='\n')
reexports = ', '.join(map(lambda name: reexportedName(name), reexports))
self.cgRoot = CGList([CGGeneric('pub use self::%sBinding::{%s};' % (descriptor.name, reexports)),
self.cgRoot = CGList([CGGeneric('pub use self::%s::{%s};' % (toBindingNamespace(descriptor.name), reexports)),
cgThings], '\n')
def define(self):
@ -6760,10 +6794,12 @@ class GlobalGenRoots():
@staticmethod
def PrototypeList(config):
# Prototype ID enum.
interfaces = config.getDescriptors(isCallback=False)
interfaces = config.getDescriptors(isCallback=False, isNamespace=False)
protos = [d.name for d in interfaces]
constructors = [d.name for d in config.getDescriptors(hasInterfaceObject=True)
if d.shouldHaveGetConstructorObjectMethod()]
constructors = sorted([MakeNativeName(d.name)
for d in config.getDescriptors(hasInterfaceObject=True)
if d.shouldHaveGetConstructorObjectMethod()])
proxies = [d.name for d in config.getDescriptors(proxy=True)]
return CGList([
@ -6800,10 +6836,13 @@ class GlobalGenRoots():
@staticmethod
def InterfaceTypes(config):
descriptors = [d.name for d in config.getDescriptors(register=True,
descriptors = sorted([MakeNativeName(d.name)
for d in config.getDescriptors(register=True,
isCallback=False,
isIteratorInterface=False)]
curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors])
isIteratorInterface=False)])
curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(),
MakeNativeName(name)))
for name in descriptors])
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
return curr
@ -6814,7 +6853,7 @@ class GlobalGenRoots():
return getModuleFromObject(d).split('::')[-1]
descriptors = config.getDescriptors(register=True, isIteratorInterface=False)
descriptors = (set(d.name + "Binding" for d in descriptors) |
descriptors = (set(toBindingNamespace(d.name) for d in descriptors) |
set(leafModule(d) for d in config.callbacks) |
set(leafModule(d) for d in config.getDictionaries()))
curr = CGList([CGGeneric("pub mod %s;\n" % name) for name in sorted(descriptors)])

View file

@ -4,7 +4,7 @@
import os
from WebIDL import IDLExternalInterface, IDLInterface, IDLWrapperType, WebIDLError
from WebIDL import IDLExternalInterface, IDLWrapperType, WebIDLError
class Configuration:
@ -30,10 +30,9 @@ class Configuration:
raise WebIDLError("Servo does not support external interfaces.",
[thing.location])
# Some toplevel things are sadly types, and those have an
# isInterface that doesn't mean the same thing as IDLObject's
# isInterface()...
if not isinstance(thing, IDLInterface):
assert not thing.isType()
if not thing.isInterface() and not thing.isNamespace():
continue
iface = thing
@ -83,6 +82,8 @@ class Configuration:
getter = lambda x: x.interface.hasInterfaceObject()
elif key == 'isCallback':
getter = lambda x: x.interface.isCallback()
elif key == 'isNamespace':
getter = lambda x: x.interface.isNamespace()
elif key == 'isJSImplemented':
getter = lambda x: x.interface.isJSImplemented()
elif key == 'isGlobal':
@ -210,7 +211,7 @@ class Descriptor(DescriptorProvider):
if self.interface.isIteratorInterface():
pathDefault = 'dom::bindings::iterable::IterableIterator'
else:
pathDefault = 'dom::types::%s' % typeName
pathDefault = 'dom::types::%s' % MakeNativeName(typeName)
self.concreteType = typeName
self.register = desc.get('register', True)
@ -223,6 +224,7 @@ class Descriptor(DescriptorProvider):
# If we're concrete, we need to crawl our ancestor interfaces and mark
# them as having a concrete descendant.
self.concrete = (not self.interface.isCallback() and
not self.interface.isNamespace() and
not self.interface.getExtendedAttribute("Abstract"))
self.hasUnforgeableMembers = (self.concrete and
any(MemberIsUnforgeable(m, self) for m in
@ -381,7 +383,7 @@ class Descriptor(DescriptorProvider):
def shouldHaveGetConstructorObjectMethod(self):
assert self.interface.hasInterfaceObject()
return self.interface.isCallback() or self.hasDescendants()
return self.interface.isCallback() or self.interface.isNamespace() or self.hasDescendants()
def isExposedConditionally(self):
return self.interface.isExposedConditionally()
@ -396,6 +398,12 @@ class Descriptor(DescriptorProvider):
# Some utility methods
def MakeNativeName(name):
return name[0].upper() + name[1:]
def getModuleFromObject(object):
return ('dom::bindings::codegen::Bindings::' +
os.path.basename(object.location.filename()).split('.webidl')[0] + 'Binding')

View file

@ -13,6 +13,7 @@ use dom::bindings::conversions::root_from_object;
use dom::bindings::error::ErrorInfo;
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflectable, Reflector};
use dom::console::TimerSet;
use dom::window::{self, ScriptHelpers};
use dom::workerglobalscope::WorkerGlobalScope;
use ipc_channel::ipc::IpcSender;
@ -271,6 +272,14 @@ impl<'a> GlobalRef<'a> {
}
}
/// Returns the global's timers for the Console API.
pub fn console_timers(&self) -> &TimerSet {
match *self {
GlobalRef::Window(ref window) => window.console_timers(),
GlobalRef::Worker(ref worker) => worker.console_timers(),
}
}
/// Returns a wrapper for runnables to ensure they are cancelled if the global
/// is being destroyed.
pub fn get_runnable_wrapper(&self) -> RunnableWrapper {

View file

@ -257,7 +257,8 @@ pub unsafe fn create_named_constructors(
}
}
unsafe fn create_object(
/// Create a new object with a unique type.
pub unsafe fn create_object(
cx: *mut JSContext,
proto: HandleObject,
class: &'static JSClass,
@ -316,7 +317,9 @@ pub unsafe fn is_exposed_in(object: HandleObject, globals: Globals) -> bool {
globals.contains(dom_class.global)
}
unsafe fn define_on_global_object(
/// Define a property with a given name on the global object. Should be called
/// through the resolve hook.
pub unsafe fn define_on_global_object(
cx: *mut JSContext,
global: HandleObject,
name: &[u8],

View file

@ -140,6 +140,7 @@ pub mod inheritance;
pub mod interface;
pub mod iterable;
pub mod js;
pub mod namespace;
pub mod num;
pub mod proxyhandler;
pub mod refcounted;

View file

@ -0,0 +1,42 @@
/* 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/. */
//! Machinery to initialise namespace objects.
use dom::bindings::guard::Guard;
use dom::bindings::interface::{create_object, define_on_global_object};
use js::jsapi::{HandleObject, JSClass, JSContext, JSFunctionSpec, MutableHandleObject};
use libc;
use std::ptr;
/// The class of a namespace object.
#[derive(Copy, Clone)]
pub struct NamespaceObjectClass(JSClass);
unsafe impl Sync for NamespaceObjectClass {}
impl NamespaceObjectClass {
/// Create a new `NamespaceObjectClass` structure.
pub const unsafe fn new(name: &'static [u8]) -> Self {
NamespaceObjectClass(JSClass {
name: name as *const _ as *const libc::c_char,
flags: 0,
cOps: ptr::null_mut(),
reserved: [ptr::null_mut(); 3],
})
}
}
/// Create a new namespace object.
pub unsafe fn create_namespace_object(
cx: *mut JSContext,
global: HandleObject,
proto: HandleObject,
class: &'static NamespaceObjectClass,
methods: &[Guard<&'static [JSFunctionSpec]>],
name: &[u8],
rval: MutableHandleObject) {
create_object(cx, proto, &class.0, methods, &[], &[], rval);
define_on_global_object(cx, global, name, rval.handle());
}

View file

@ -5,7 +5,7 @@
//! The `ByteString` struct.
use std::ascii::AsciiExt;
use std::borrow::{ToOwned, Cow};
use std::borrow::{Borrow, Cow, ToOwned};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops;
@ -180,6 +180,13 @@ impl DOMString {
}
}
impl Borrow<str> for DOMString {
#[inline]
fn borrow(&self) -> &str {
&self.0
}
}
impl Default for DOMString {
fn default() -> Self {
DOMString(String::new())

View file

@ -4,39 +4,17 @@
use devtools_traits::{ConsoleMessage, LogLevel, ScriptToDevtoolsControlMsg};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::ConsoleBinding;
use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use time::{Timespec, get_time};
// https://developer.mozilla.org/en-US/docs/Web/API/Console
#[dom_struct]
pub struct Console {
reflector_: Reflector,
timers: DOMRefCell<HashMap<DOMString, u64>>,
}
pub struct Console(());
impl Console {
fn new_inherited() -> Console {
Console {
reflector_: Reflector::new(),
timers: DOMRefCell::new(HashMap::new()),
}
}
pub fn new(global: GlobalRef) -> Root<Console> {
reflect_dom_object(box Console::new_inherited(),
global,
ConsoleBinding::Wrap)
}
fn send_to_devtools(&self, level: LogLevel, message: DOMString) {
let global = self.global();
let global = global.r();
fn send_to_devtools(global: GlobalRef, level: LogLevel, message: DOMString) {
if let Some(chan) = global.devtools_chan() {
let console_message = prepare_message(level, message);
let devtools_message = ScriptToDevtoolsControlMsg::ConsoleAPI(
@ -48,83 +26,73 @@ impl Console {
}
}
impl ConsoleMethods for Console {
impl Console {
// https://developer.mozilla.org/en-US/docs/Web/API/Console/log
fn Log(&self, messages: Vec<DOMString>) {
pub fn Log(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
self.send_to_devtools(LogLevel::Log, message);
Self::send_to_devtools(global, LogLevel::Log, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console
fn Debug(&self, messages: Vec<DOMString>) {
pub fn Debug(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
self.send_to_devtools(LogLevel::Debug, message);
Self::send_to_devtools(global, LogLevel::Debug, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/info
fn Info(&self, messages: Vec<DOMString>) {
pub fn Info(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
self.send_to_devtools(LogLevel::Info, message);
Self::send_to_devtools(global, LogLevel::Info, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/warn
fn Warn(&self, messages: Vec<DOMString>) {
pub fn Warn(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
self.send_to_devtools(LogLevel::Warn, message);
Self::send_to_devtools(global, LogLevel::Warn, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/error
fn Error(&self, messages: Vec<DOMString>) {
pub fn Error(global: GlobalRef, messages: Vec<DOMString>) {
for message in messages {
println!("{}", message);
self.send_to_devtools(LogLevel::Error, message);
Self::send_to_devtools(global, LogLevel::Error, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/assert
fn Assert(&self, condition: bool, message: Option<DOMString>) {
pub fn Assert(global: GlobalRef, condition: bool, message: Option<DOMString>) {
if !condition {
let message = message.unwrap_or_else(|| DOMString::from("no message"));
println!("Assertion failed: {}", message);
self.send_to_devtools(LogLevel::Error, message);
Self::send_to_devtools(global, LogLevel::Error, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/time
fn Time(&self, label: DOMString) {
let mut timers = self.timers.borrow_mut();
if timers.contains_key(&label) {
// Timer already started
return;
}
if timers.len() >= 10000 {
// Too many timers on page
return;
}
timers.insert(label.clone(), timestamp_in_ms(get_time()));
pub fn Time(global: GlobalRef, label: DOMString) {
if let Ok(()) = global.console_timers().time(label.clone()) {
let message = DOMString::from(format!("{}: timer started", label));
println!("{}", message);
self.send_to_devtools(LogLevel::Log, message);
Self::send_to_devtools(global, LogLevel::Log, message);
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd
fn TimeEnd(&self, label: DOMString) {
let mut timers = self.timers.borrow_mut();
if let Some(start) = timers.remove(&label) {
pub fn TimeEnd(global: GlobalRef, label: DOMString) {
if let Ok(delta) = global.console_timers().time_end(&label) {
let message = DOMString::from(
format!("{}: {}ms", label, timestamp_in_ms(get_time()) - start)
format!("{}: {}ms", label, delta)
);
println!("{}", message);
self.send_to_devtools(LogLevel::Log, message);
Self::send_to_devtools(global, LogLevel::Log, message);
};
}
}
@ -143,3 +111,32 @@ fn prepare_message(logLevel: LogLevel, message: DOMString) -> ConsoleMessage {
columnNumber: 1,
}
}
#[derive(HeapSizeOf, JSTraceable)]
pub struct TimerSet(DOMRefCell<HashMap<DOMString, u64>>);
impl TimerSet {
pub fn new() -> Self {
TimerSet(DOMRefCell::new(Default::default()))
}
fn time(&self, label: DOMString) -> Result<(), ()> {
let mut timers = self.0.borrow_mut();
if timers.len() >= 10000 {
return Err(());
}
match timers.entry(label) {
Entry::Vacant(entry) => {
entry.insert(timestamp_in_ms(get_time()));
Ok(())
},
Entry::Occupied(_) => Err(()),
}
}
fn time_end(&self, label: &str) -> Result<u64, ()> {
self.0.borrow_mut().remove(label).ok_or(()).map(|start| {
timestamp_in_ms(get_time()) - start
})
}
}

View file

@ -9,8 +9,10 @@
* © Copyright 2014 Mozilla Foundation.
*/
[Exposed=(Window,Worker)]
interface Console {
[ClassString="Console",
Exposed=(Window,Worker),
ProtoObjectHack]
namespace console {
// These should be DOMString message, DOMString message2, ...
void log(DOMString... messages);
void debug(DOMString... messages);

View file

@ -161,7 +161,6 @@ partial interface Window {
// Proprietary extensions.
partial interface Window {
readonly attribute Console console;
void debug(DOMString arg);
void gc();
void trap();

View file

@ -24,10 +24,3 @@ partial interface WorkerGlobalScope { // not obsolete
};
WorkerGlobalScope implements WindowTimers;
WorkerGlobalScope implements WindowBase64;
// Proprietary
[Exposed=Worker]
partial interface WorkerGlobalScope {
[Replaceable]
readonly attribute Console console;
};

View file

@ -25,7 +25,7 @@ use dom::bindings::str::DOMString;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::utils::{GlobalStaticData, WindowProxyHandler};
use dom::browsingcontext::BrowsingContext;
use dom::console::Console;
use dom::console::TimerSet;
use dom::crypto::Crypto;
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
use dom::document::Document;
@ -157,7 +157,6 @@ pub struct Window {
history_traversal_task_source: HistoryTraversalTaskSource,
#[ignore_heap_size_of = "task sources are hard"]
file_reading_task_source: FileReadingTaskSource,
console: MutNullableHeap<JS<Console>>,
crypto: MutNullableHeap<JS<Crypto>>,
navigator: MutNullableHeap<JS<Navigator>>,
#[ignore_heap_size_of = "channels are hard"]
@ -276,7 +275,10 @@ pub struct Window {
scroll_offsets: DOMRefCell<HashMap<UntrustedNodeAddress, Point2D<f32>>>,
/// https://html.spec.whatwg.org/multipage/#in-error-reporting-mode
in_error_reporting_mode: Cell<bool>
in_error_reporting_mode: Cell<bool>,
/// Timers used by the Console API.
console_timers: TimerSet,
}
impl Window {
@ -508,11 +510,6 @@ impl WindowMethods for Window {
self.local_storage.or_init(|| Storage::new(&GlobalRef::Window(self), StorageType::Local))
}
// https://developer.mozilla.org/en-US/docs/Web/API/Console
fn Console(&self) -> Root<Console> {
self.console.or_init(|| Console::new(GlobalRef::Window(self)))
}
// https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#dfn-GlobalCrypto
fn Crypto(&self) -> Root<Crypto> {
self.crypto.or_init(|| Crypto::new(GlobalRef::Window(self)))
@ -1701,7 +1698,6 @@ impl Window {
history_traversal_task_source: history_task_source,
file_reading_task_source: file_task_source,
image_cache_chan: image_cache_chan,
console: Default::default(),
crypto: Default::default(),
navigator: Default::default(),
image_cache_thread: image_cache_thread,
@ -1747,10 +1743,16 @@ impl Window {
error_reporter: error_reporter,
scroll_offsets: DOMRefCell::new(HashMap::new()),
in_error_reporting_mode: Cell::new(false),
console_timers: TimerSet::new(),
};
WindowBinding::Wrap(runtime.cx(), win)
}
pub fn console_timers(&self) -> &TimerSet {
&self.console_timers
}
pub fn live_devtools_updates(&self) -> bool {
return self.devtools_wants_updates.get();
}

View file

@ -12,7 +12,7 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::reflector::Reflectable;
use dom::bindings::str::DOMString;
use dom::console::Console;
use dom::console::TimerSet;
use dom::crypto::Crypto;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::eventtarget::EventTarget;
@ -80,7 +80,6 @@ pub struct WorkerGlobalScope {
resource_threads: ResourceThreads,
location: MutNullableHeap<JS<WorkerLocation>>,
navigator: MutNullableHeap<JS<WorkerNavigator>>,
console: MutNullableHeap<JS<Console>>,
crypto: MutNullableHeap<JS<Crypto>>,
timers: OneshotTimers,
@ -110,6 +109,9 @@ pub struct WorkerGlobalScope {
#[ignore_heap_size_of = "Defined in std"]
scheduler_chan: IpcSender<TimerEventRequest>,
/// Timers used by the Console API.
console_timers: TimerSet,
}
impl WorkerGlobalScope {
@ -130,7 +132,6 @@ impl WorkerGlobalScope {
resource_threads: init.resource_threads,
location: Default::default(),
navigator: Default::default(),
console: Default::default(),
crypto: Default::default(),
timers: OneshotTimers::new(timer_event_chan, init.scheduler_chan.clone()),
mem_profiler_chan: init.mem_profiler_chan,
@ -141,9 +142,14 @@ impl WorkerGlobalScope {
devtools_wants_updates: Cell::new(false),
constellation_chan: init.constellation_chan,
scheduler_chan: init.scheduler_chan,
console_timers: TimerSet::new(),
}
}
pub fn console_timers(&self) -> &TimerSet {
&self.console_timers
}
pub fn mem_profiler_chan(&self) -> &mem::ProfilerChan {
&self.mem_profiler_chan
}
@ -299,11 +305,6 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
self.navigator.or_init(|| WorkerNavigator::new(self))
}
// https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/console
fn Console(&self) -> Root<Console> {
self.console.or_init(|| Console::new(GlobalRef::Worker(self)))
}
// https://html.spec.whatwg.org/multipage/#dfn-Crypto
fn Crypto(&self) -> Root<Crypto> {
self.crypto.or_init(|| Crypto::new(GlobalRef::Worker(self)))

View file

@ -27,7 +27,6 @@ test_interfaces([
"DOMRect",
"DOMRectReadOnly",
"Comment",
"Console",
"CustomEvent",
"Document",
"DocumentFragment",
@ -184,5 +183,6 @@ test_interfaces([
"XMLHttpRequest",
"XMLHttpRequestEventTarget",
"XMLHttpRequestUpload",
"console",
]);
</script>

View file

@ -65,7 +65,7 @@ function test_interfaces(interfaceNamesInGlobalScope) {
}
for (var name of Object.getOwnPropertyNames(self)) {
if (!/^[A-Z]/.test(name)) {
if (!/^[A-Z]/.test(name) && name != 'console') {
continue;
}
assert_true(name in interfaceMap,

View file

@ -23,7 +23,6 @@ test_interfaces([
"DOMRect",
"DOMRectReadOnly",
"Comment",
"Console",
"CustomEvent",
"DedicatedWorkerGlobalScope",
"Document",
@ -129,6 +128,7 @@ test_interfaces([
"XMLHttpRequest",
"XMLHttpRequestEventTarget",
"XMLHttpRequestUpload",
"console",
]);
done();