mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Auto merge of #13596 - nox:inline, r=Ms2ger
Get rid of dom::bindings::global Globals in that PR are now represented by the fake IDL interface `GlobalScope`. <!-- 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/13596) <!-- Reviewable:end -->
This commit is contained in:
commit
a6e4b5bb86
170 changed files with 1595 additions and 1742 deletions
|
@ -5,8 +5,8 @@
|
|||
//! Base classes to work with IDL callbacks.
|
||||
|
||||
use dom::bindings::error::{Error, Fallible, report_pending_exception};
|
||||
use dom::bindings::global::global_root_from_object;
|
||||
use dom::bindings::reflector::Reflectable;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use js::jsapi::{Heap, MutableHandleObject, RootedObject};
|
||||
use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject};
|
||||
use js::jsapi::{JSCompartment, JS_EnterCompartment, JS_LeaveCompartment};
|
||||
|
@ -165,8 +165,8 @@ impl<'a> CallSetup<'a> {
|
|||
callback: &T,
|
||||
handling: ExceptionHandling)
|
||||
-> CallSetup<'a> {
|
||||
let global = unsafe { global_root_from_object(callback.callback()) };
|
||||
let cx = global.r().get_cx();
|
||||
let global = unsafe { GlobalScope::from_object(callback.callback()) };
|
||||
let cx = global.get_cx();
|
||||
|
||||
exception_compartment.ptr = unsafe {
|
||||
GetGlobalForObjectCrossCompartment(callback.callback())
|
||||
|
|
|
@ -817,16 +817,16 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
{ // Scope for our JSAutoCompartment.
|
||||
|
||||
rooted!(in(cx) let globalObj = CurrentGlobalOrNull(cx));
|
||||
let promiseGlobal = global_root_from_object_maybe_wrapped(globalObj.handle().get());
|
||||
let promiseGlobal = GlobalScope::from_object_maybe_wrapped(globalObj.handle().get());
|
||||
|
||||
rooted!(in(cx) let mut valueToResolve = $${val}.get());
|
||||
if !JS_WrapValue(cx, valueToResolve.handle_mut()) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
match Promise::Resolve(promiseGlobal.r(), cx, valueToResolve.handle()) {
|
||||
match Promise::Resolve(&promiseGlobal, cx, valueToResolve.handle()) {
|
||||
Ok(value) => value,
|
||||
Err(error) => {
|
||||
throw_dom_exception(cx, promiseGlobal.r(), error);
|
||||
throw_dom_exception(cx, &promiseGlobal, error);
|
||||
$*{exceptionCode}
|
||||
}
|
||||
}
|
||||
|
@ -1927,10 +1927,12 @@ class CGImports(CGWrapper):
|
|||
if t in dictionaries or t in enums:
|
||||
continue
|
||||
if t.isInterface() or t.isNamespace():
|
||||
descriptor = descriptorProvider.getDescriptor(getIdentifier(t).name)
|
||||
extras += [descriptor.path]
|
||||
if descriptor.interface.parent:
|
||||
parentName = getIdentifier(descriptor.interface.parent).name
|
||||
name = getIdentifier(t).name
|
||||
descriptor = descriptorProvider.getDescriptor(name)
|
||||
if name != 'GlobalScope':
|
||||
extras += [descriptor.path]
|
||||
parentName = descriptor.getParentName()
|
||||
if parentName:
|
||||
descriptor = descriptorProvider.getDescriptor(parentName)
|
||||
extras += [descriptor.path, descriptor.bindingPath]
|
||||
elif t.isType() and t.isMozMap():
|
||||
|
@ -2523,7 +2525,8 @@ class CGWrapMethod(CGAbstractMethod):
|
|||
def __init__(self, descriptor):
|
||||
assert not descriptor.interface.isCallback()
|
||||
assert not descriptor.isGlobal()
|
||||
args = [Argument('*mut JSContext', 'cx'), Argument('GlobalRef', 'scope'),
|
||||
args = [Argument('*mut JSContext', 'cx'),
|
||||
Argument('&GlobalScope', 'scope'),
|
||||
Argument("Box<%s>" % descriptor.concreteType, 'object')]
|
||||
retval = 'Root<%s>' % descriptor.concreteType
|
||||
CGAbstractMethod.__init__(self, descriptor, 'Wrap', retval, args,
|
||||
|
@ -2754,7 +2757,7 @@ assert!((*cache)[PrototypeList::Constructor::%(id)s as usize].is_null());
|
|||
getPrototypeProto = "prototype_proto.set(JS_GetObjectPrototype(cx, global))"
|
||||
else:
|
||||
getPrototypeProto = ("%s::GetProtoObject(cx, global, prototype_proto.handle_mut())" %
|
||||
toBindingNamespace(self.descriptor.prototypeChain[-2]))
|
||||
toBindingNamespace(self.descriptor.getParentName()))
|
||||
|
||||
code = [CGGeneric("""\
|
||||
rooted!(in(cx) let mut prototype_proto = ptr::null_mut());
|
||||
|
@ -2808,8 +2811,9 @@ assert!((*cache)[PrototypeList::ID::%(id)s as usize].is_null());
|
|||
properties["length"] = methodLength(self.descriptor.interface.ctor())
|
||||
else:
|
||||
properties["length"] = 0
|
||||
if self.descriptor.interface.parent:
|
||||
parentName = toBindingNamespace(self.descriptor.getParentName())
|
||||
parentName = self.descriptor.getParentName()
|
||||
if parentName:
|
||||
parentName = toBindingNamespace(parentName)
|
||||
code.append(CGGeneric("""
|
||||
rooted!(in(cx) let mut interface_proto = ptr::null_mut());
|
||||
%s::GetConstructorObject(cx, global, interface_proto.handle_mut());""" % parentName))
|
||||
|
@ -3164,16 +3168,15 @@ class CGCallGenerator(CGThing):
|
|||
|
||||
if isFallible:
|
||||
if static:
|
||||
glob = ""
|
||||
glob = "&global"
|
||||
else:
|
||||
glob = " let global = global_root_from_reflector(this);\n"
|
||||
glob = "&this.global()"
|
||||
|
||||
self.cgRoot.append(CGGeneric(
|
||||
"let result = match result {\n"
|
||||
" Ok(result) => result,\n"
|
||||
" Err(e) => {\n"
|
||||
"%s"
|
||||
" throw_dom_exception(cx, global.r(), e);\n"
|
||||
" throw_dom_exception(cx, %s, e);\n"
|
||||
" return%s;\n"
|
||||
" },\n"
|
||||
"};" % (glob, errorResult)))
|
||||
|
@ -3383,7 +3386,7 @@ class CGAbstractStaticBindingMethod(CGAbstractMethod):
|
|||
|
||||
def definition_body(self):
|
||||
preamble = CGGeneric("""\
|
||||
let global = global_root_from_object(JS_CALLEE(cx, vp).to_object());
|
||||
let global = GlobalScope::from_object(JS_CALLEE(cx, vp).to_object());
|
||||
""")
|
||||
return CGList([preamble, self.generate_code()])
|
||||
|
||||
|
@ -3435,7 +3438,7 @@ class CGStaticMethod(CGAbstractStaticBindingMethod):
|
|||
nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
|
||||
self.method)
|
||||
setupArgs = CGGeneric("let args = CallArgs::from_vp(vp, argc);\n")
|
||||
call = CGMethodCall(["global.r()"], nativeName, True, self.descriptor, self.method)
|
||||
call = CGMethodCall(["&global"], nativeName, True, self.descriptor, self.method)
|
||||
return CGList([setupArgs, call])
|
||||
|
||||
|
||||
|
@ -3489,7 +3492,7 @@ class CGStaticGetter(CGAbstractStaticBindingMethod):
|
|||
nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
|
||||
self.attr)
|
||||
setupArgs = CGGeneric("let args = CallArgs::from_vp(vp, argc);\n")
|
||||
call = CGGetterCall(["global.r()"], self.attr.type, nativeName, self.descriptor,
|
||||
call = CGGetterCall(["&global"], self.attr.type, nativeName, self.descriptor,
|
||||
self.attr)
|
||||
return CGList([setupArgs, call])
|
||||
|
||||
|
@ -3542,7 +3545,7 @@ class CGStaticSetter(CGAbstractStaticBindingMethod):
|
|||
" throw_type_error(cx, \"Not enough arguments to %s setter.\");\n"
|
||||
" return false;\n"
|
||||
"}" % self.attr.identifier.name)
|
||||
call = CGSetterCall(["global.r()"], self.attr.type, nativeName, self.descriptor,
|
||||
call = CGSetterCall(["&global"], self.attr.type, nativeName, self.descriptor,
|
||||
self.attr)
|
||||
return CGList([checkForArg, call])
|
||||
|
||||
|
@ -5249,12 +5252,12 @@ class CGClassConstructHook(CGAbstractExternMethod):
|
|||
|
||||
def definition_body(self):
|
||||
preamble = CGGeneric("""\
|
||||
let global = global_root_from_object(JS_CALLEE(cx, vp).to_object());
|
||||
let global = GlobalScope::from_object(JS_CALLEE(cx, vp).to_object());
|
||||
let args = CallArgs::from_vp(vp, argc);
|
||||
""")
|
||||
name = self.constructor.identifier.name
|
||||
nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
|
||||
callGenerator = CGMethodCall(["global.r()"], nativeName, True,
|
||||
callGenerator = CGMethodCall(["&global"], nativeName, True,
|
||||
self.descriptor, self.constructor)
|
||||
return CGList([preamble, callGenerator])
|
||||
|
||||
|
@ -5496,10 +5499,6 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
|||
'dom::bindings::codegen::InterfaceObjectMap',
|
||||
'dom::bindings::constant::ConstantSpec',
|
||||
'dom::bindings::constant::ConstantVal',
|
||||
'dom::bindings::global::GlobalRef',
|
||||
'dom::bindings::global::global_root_from_object',
|
||||
'dom::bindings::global::global_root_from_object_maybe_wrapped',
|
||||
'dom::bindings::global::global_root_from_reflector',
|
||||
'dom::bindings::interface::ConstructorClassHook',
|
||||
'dom::bindings::interface::InterfaceConstructorBehavior',
|
||||
'dom::bindings::interface::NonCallbackInterfaceObjectClass',
|
||||
|
@ -5593,6 +5592,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
|
|||
'dom::bindings::weakref::WeakBox',
|
||||
'dom::bindings::weakref::WeakReferenceable',
|
||||
'dom::browsingcontext::BrowsingContext',
|
||||
'dom::globalscope::GlobalScope',
|
||||
'mem::heap_size_of_raw_self_and_children',
|
||||
'libc',
|
||||
'util::prefs::PREFS',
|
||||
|
@ -5744,33 +5744,38 @@ class CGDescriptor(CGThing):
|
|||
|
||||
cgThings.append(CGGeneric(str(properties)))
|
||||
|
||||
if not descriptor.interface.isCallback() and not descriptor.interface.isNamespace():
|
||||
cgThings.append(CGGetProtoObjectMethod(descriptor))
|
||||
reexports.append('GetProtoObject')
|
||||
cgThings.append(CGPrototypeJSClass(descriptor))
|
||||
if descriptor.interface.hasInterfaceObject():
|
||||
if descriptor.interface.ctor():
|
||||
cgThings.append(CGClassConstructHook(descriptor))
|
||||
for ctor in descriptor.interface.namedConstructors:
|
||||
cgThings.append(CGClassConstructHook(descriptor, ctor))
|
||||
if not descriptor.interface.isCallback():
|
||||
cgThings.append(CGInterfaceObjectJSClass(descriptor))
|
||||
if descriptor.shouldHaveGetConstructorObjectMethod():
|
||||
cgThings.append(CGGetConstructorObjectMethod(descriptor))
|
||||
reexports.append('GetConstructorObject')
|
||||
if descriptor.register:
|
||||
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
|
||||
reexports.append('DefineDOMInterface')
|
||||
cgThings.append(CGConstructorEnabled(descriptor))
|
||||
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties, haveUnscopables))
|
||||
if not descriptor.interface.getExtendedAttribute("Inline"):
|
||||
if not descriptor.interface.isCallback() and not descriptor.interface.isNamespace():
|
||||
cgThings.append(CGGetProtoObjectMethod(descriptor))
|
||||
reexports.append('GetProtoObject')
|
||||
cgThings.append(CGPrototypeJSClass(descriptor))
|
||||
if descriptor.interface.hasInterfaceObject():
|
||||
if descriptor.interface.ctor():
|
||||
cgThings.append(CGClassConstructHook(descriptor))
|
||||
for ctor in descriptor.interface.namedConstructors:
|
||||
cgThings.append(CGClassConstructHook(descriptor, ctor))
|
||||
if not descriptor.interface.isCallback():
|
||||
cgThings.append(CGInterfaceObjectJSClass(descriptor))
|
||||
if descriptor.shouldHaveGetConstructorObjectMethod():
|
||||
cgThings.append(CGGetConstructorObjectMethod(descriptor))
|
||||
reexports.append('GetConstructorObject')
|
||||
if descriptor.register:
|
||||
cgThings.append(CGDefineDOMInterfaceMethod(descriptor))
|
||||
reexports.append('DefineDOMInterface')
|
||||
cgThings.append(CGConstructorEnabled(descriptor))
|
||||
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties, haveUnscopables))
|
||||
|
||||
cgThings = generate_imports(config, CGList(cgThings, '\n'), [descriptor])
|
||||
cgThings = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
|
||||
cgThings, public=True),
|
||||
post='\n')
|
||||
reexports = ', '.join(map(lambda name: reexportedName(name), reexports))
|
||||
self.cgRoot = CGList([CGGeneric('pub use self::%s::{%s};' % (toBindingNamespace(descriptor.name), reexports)),
|
||||
cgThings], '\n')
|
||||
|
||||
if reexports:
|
||||
reexports = ', '.join(map(lambda name: reexportedName(name), reexports))
|
||||
cgThings = CGList([CGGeneric('pub use self::%s::{%s};' % (toBindingNamespace(descriptor.name), reexports)),
|
||||
cgThings], '\n')
|
||||
|
||||
self.cgRoot = cgThings
|
||||
|
||||
def define(self):
|
||||
return self.cgRoot.define()
|
||||
|
@ -6799,7 +6804,7 @@ class GlobalGenRoots():
|
|||
globals_ = CGWrapper(CGIndenter(global_flags), pre="bitflags! {\n", post="\n}")
|
||||
|
||||
pairs = []
|
||||
for d in config.getDescriptors(hasInterfaceObject=True):
|
||||
for d in config.getDescriptors(hasInterfaceObject=True, isInline=False):
|
||||
binding = toBindingNamespace(d.name)
|
||||
pairs.append((d.name, binding, binding))
|
||||
for ctor in d.interface.namedConstructors:
|
||||
|
@ -6927,7 +6932,7 @@ class GlobalGenRoots():
|
|||
allprotos.append(CGGeneric("\n"))
|
||||
|
||||
if downcast:
|
||||
hierarchy[descriptor.getParentName()].append(name)
|
||||
hierarchy[descriptor.interface.parent.identifier.name].append(name)
|
||||
|
||||
typeIdCode = []
|
||||
topTypeVariants = [
|
||||
|
@ -6959,7 +6964,7 @@ impl Clone for TopTypeId {
|
|||
|
||||
for base, derived in hierarchy.iteritems():
|
||||
variants = []
|
||||
if not config.getInterface(base).getExtendedAttribute("Abstract"):
|
||||
if config.getDescriptor(base).concrete:
|
||||
variants.append(CGGeneric(base))
|
||||
variants += [CGGeneric(type_id_variant(derivedName)) for derivedName in derived]
|
||||
derives = "Clone, Copy, Debug, PartialEq"
|
||||
|
|
|
@ -88,6 +88,8 @@ class Configuration:
|
|||
getter = lambda x: x.interface.isJSImplemented()
|
||||
elif key == 'isGlobal':
|
||||
getter = lambda x: x.isGlobal()
|
||||
elif key == 'isInline':
|
||||
getter = lambda x: x.interface.getExtendedAttribute('Inline') is not None
|
||||
elif key == 'isExposedConditionally':
|
||||
getter = lambda x: x.interface.isExposedConditionally()
|
||||
elif key == 'isIteratorInterface':
|
||||
|
@ -234,6 +236,7 @@ class Descriptor(DescriptorProvider):
|
|||
self.concrete = (not self.interface.isCallback() and
|
||||
not self.interface.isNamespace() and
|
||||
not self.interface.getExtendedAttribute("Abstract") and
|
||||
not self.interface.getExtendedAttribute("Inline") and
|
||||
not spiderMonkeyInterface)
|
||||
self.hasUnforgeableMembers = (self.concrete and
|
||||
any(MemberIsUnforgeable(m, self) for m in
|
||||
|
@ -383,8 +386,12 @@ class Descriptor(DescriptorProvider):
|
|||
return attrs
|
||||
|
||||
def getParentName(self):
|
||||
assert self.interface.parent is not None
|
||||
return self.interface.parent.identifier.name
|
||||
parent = self.interface.parent
|
||||
while parent:
|
||||
if not parent.getExtendedAttribute("Inline"):
|
||||
return parent.identifier.name
|
||||
parent = parent.parent
|
||||
return None
|
||||
|
||||
def hasDescendants(self):
|
||||
return (self.interface.getUserData("hasConcreteDescendant", False) or
|
||||
|
|
|
@ -1695,7 +1695,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
|||
identifier == "ProbablyShortLivingObject" or
|
||||
identifier == "LegacyUnenumerableNamedProperties" or
|
||||
identifier == "NonOrdinaryGetPrototypeOf" or
|
||||
identifier == "Abstract"):
|
||||
identifier == "Abstract" or
|
||||
identifier == "Inline"):
|
||||
# Known extended attributes that do not take values
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[%s] must take no arguments" % identifier,
|
||||
|
|
12
components/script/dom/bindings/codegen/parser/inline.patch
Normal file
12
components/script/dom/bindings/codegen/parser/inline.patch
Normal file
|
@ -0,0 +1,12 @@
|
|||
--- WebIDL.py
|
||||
+++ WebIDL.py
|
||||
@@ -1695,7 +1695,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||
identifier == "ProbablyShortLivingObject" or
|
||||
identifier == "LegacyUnenumerableNamedProperties" or
|
||||
identifier == "NonOrdinaryGetPrototypeOf" or
|
||||
- identifier == "Abstract"):
|
||||
+ identifier == "Abstract" or
|
||||
+ identifier == "Inline"):
|
||||
# Known extended attributes that do not take values
|
||||
if not attr.noArguments():
|
||||
raise WebIDLError("[%s] must take no arguments" % identifier,
|
|
@ -4,6 +4,7 @@ patch < debug.patch
|
|||
patch < pref-main-thread.patch
|
||||
patch < callback-location.patch
|
||||
patch < union-typedef.patch
|
||||
patch < inline.patch
|
||||
|
||||
wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz
|
||||
rm -r tests
|
||||
|
|
|
@ -8,9 +8,9 @@ use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
|
|||
use dom::bindings::codegen::PrototypeList::proto_id_to_name;
|
||||
use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, ToJSValConvertible};
|
||||
use dom::bindings::conversions::root_from_object;
|
||||
use dom::bindings::global::{GlobalRef, global_root_from_context};
|
||||
use dom::bindings::str::USVString;
|
||||
use dom::domexception::{DOMErrorName, DOMException};
|
||||
use dom::globalscope::GlobalScope;
|
||||
use js::error::{throw_range_error, throw_type_error};
|
||||
use js::jsapi::HandleObject;
|
||||
use js::jsapi::JSContext;
|
||||
|
@ -87,7 +87,7 @@ pub type Fallible<T> = Result<T, Error>;
|
|||
pub type ErrorResult = Fallible<()>;
|
||||
|
||||
/// Set a pending exception for the given `result` on `cx`.
|
||||
pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: GlobalRef, result: Error) {
|
||||
pub unsafe fn throw_dom_exception(cx: *mut JSContext, global: &GlobalScope, result: Error) {
|
||||
let code = match result {
|
||||
Error::IndexSize => DOMErrorName::IndexSizeError,
|
||||
Error::NotFound => DOMErrorName::NotFoundError,
|
||||
|
@ -245,8 +245,8 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
|
|||
error_info.message);
|
||||
|
||||
if dispatch_event {
|
||||
let global = global_root_from_context(cx);
|
||||
global.r().report_an_error(error_info, value.handle());
|
||||
GlobalScope::from_context(cx)
|
||||
.report_an_error(error_info, value.handle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ pub unsafe fn throw_invalid_this(cx: *mut JSContext, proto_id: u16) {
|
|||
|
||||
impl Error {
|
||||
/// Convert this error value to a JS value, consuming it in the process.
|
||||
pub unsafe fn to_jsval(self, cx: *mut JSContext, global: GlobalRef, rval: MutableHandleValue) {
|
||||
pub unsafe fn to_jsval(self, cx: *mut JSContext, global: &GlobalScope, rval: MutableHandleValue) {
|
||||
assert!(!JS_IsExceptionPending(cx));
|
||||
throw_dom_exception(cx, global, self);
|
||||
assert!(JS_IsExceptionPending(cx));
|
||||
|
|
|
@ -1,398 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
//! Abstractions for global scopes.
|
||||
//!
|
||||
//! This module contains smart pointers to global scopes, to simplify writing
|
||||
//! code that works in workers as well as window scopes.
|
||||
|
||||
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||
use dom::bindings::conversions::root_from_object;
|
||||
use dom::bindings::error::{ErrorInfo, report_pending_exception};
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{Reflectable, Reflector};
|
||||
use dom::console::TimerSet;
|
||||
use dom::window;
|
||||
use dom::workerglobalscope::WorkerGlobalScope;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
|
||||
use js::glue::{IsWrapper, UnwrapObject};
|
||||
use js::jsapi::{CurrentGlobalOrNull, Evaluate2, GetGlobalForObjectCrossCompartment};
|
||||
use js::jsapi::{HandleValue, JS_GetClass, JSAutoCompartment, JSContext};
|
||||
use js::jsapi::{JSObject, MutableHandleValue};
|
||||
use js::rust::CompileOptionsWrapper;
|
||||
use libc;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::{CoreResourceThread, IpcSend, ResourceThreads};
|
||||
use profile_traits::{mem, time};
|
||||
use script_runtime::{CommonScriptMsg, EnqueuedPromiseCallback, ScriptChan};
|
||||
use script_runtime::{ScriptPort, maybe_take_panic_result};
|
||||
use script_thread::{MainThreadScriptChan, RunnableWrapper, ScriptThread};
|
||||
use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEventRequest};
|
||||
use std::ffi::CString;
|
||||
use std::panic;
|
||||
use task_source::file_reading::FileReadingTaskSource;
|
||||
use timers::{OneshotTimerCallback, OneshotTimerHandle};
|
||||
use url::Url;
|
||||
|
||||
/// A freely-copyable reference to a rooted global object.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum GlobalRef<'a> {
|
||||
/// A reference to a `Window` object.
|
||||
Window(&'a window::Window),
|
||||
/// A reference to a `WorkerGlobalScope` object.
|
||||
Worker(&'a WorkerGlobalScope),
|
||||
}
|
||||
|
||||
/// A stack-based rooted reference to a global object.
|
||||
pub enum GlobalRoot {
|
||||
/// A root for a `Window` object.
|
||||
Window(Root<window::Window>),
|
||||
/// A root for a `WorkerGlobalScope` object.
|
||||
Worker(Root<WorkerGlobalScope>),
|
||||
}
|
||||
|
||||
impl<'a> GlobalRef<'a> {
|
||||
/// Get the `JSContext` for the `JSRuntime` associated with the thread
|
||||
/// this global object is on.
|
||||
pub fn get_cx(&self) -> *mut JSContext {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.get_cx(),
|
||||
GlobalRef::Worker(ref worker) => worker.get_cx(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract a `Window`, causing thread failure if the global object is not
|
||||
/// a `Window`.
|
||||
pub fn as_window(&self) -> &window::Window {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window,
|
||||
GlobalRef::Worker(_) => panic!("expected a Window scope"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the `PipelineId` for this global scope.
|
||||
pub fn pipeline_id(&self) -> PipelineId {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.pipeline_id(),
|
||||
GlobalRef::Worker(worker) => worker.pipeline_id(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a `mem::ProfilerChan` to send messages to the memory profiler thread.
|
||||
pub fn mem_profiler_chan(&self) -> &mem::ProfilerChan {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.mem_profiler_chan(),
|
||||
GlobalRef::Worker(worker) => worker.mem_profiler_chan(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a `time::ProfilerChan` to send messages to the time profiler thread.
|
||||
pub fn time_profiler_chan(&self) -> &time::ProfilerChan {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.time_profiler_chan(),
|
||||
GlobalRef::Worker(worker) => worker.time_profiler_chan(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a `IpcSender` to send messages to the constellation when available.
|
||||
pub fn constellation_chan(&self) -> &IpcSender<ConstellationMsg> {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.constellation_chan(),
|
||||
GlobalRef::Worker(worker) => worker.constellation_chan(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the scheduler channel to request timer events.
|
||||
pub fn scheduler_chan(&self) -> &IpcSender<TimerEventRequest> {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.scheduler_chan(),
|
||||
GlobalRef::Worker(worker) => worker.scheduler_chan(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an `IpcSender<ScriptToDevtoolsControlMsg>` to send messages to Devtools
|
||||
/// thread when available.
|
||||
pub fn devtools_chan(&self) -> Option<IpcSender<ScriptToDevtoolsControlMsg>> {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.devtools_chan(),
|
||||
GlobalRef::Worker(worker) => worker.devtools_chan(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the `ResourceThreads` for this global scope.
|
||||
pub fn resource_threads(&self) -> ResourceThreads {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.resource_threads().clone(),
|
||||
GlobalRef::Worker(ref worker) => worker.resource_threads().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the `CoreResourceThread` for this global scope
|
||||
pub fn core_resource_thread(&self) -> CoreResourceThread {
|
||||
self.resource_threads().sender()
|
||||
}
|
||||
|
||||
/// Get next worker id.
|
||||
pub fn get_next_worker_id(&self) -> WorkerId {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.get_next_worker_id(),
|
||||
GlobalRef::Worker(ref worker) => worker.get_next_worker_id(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the URL for this global scope.
|
||||
pub fn get_url(&self) -> Url {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.get_url(),
|
||||
GlobalRef::Worker(ref worker) => worker.get_url().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the [base url](https://html.spec.whatwg.org/multipage/#api-base-url)
|
||||
/// for this global scope.
|
||||
pub fn api_base_url(&self) -> Url {
|
||||
match *self {
|
||||
// https://html.spec.whatwg.org/multipage/#script-settings-for-browsing-contexts:api-base-url
|
||||
GlobalRef::Window(ref window) => window.Document().base_url(),
|
||||
// https://html.spec.whatwg.org/multipage/#script-settings-for-workers:api-base-url
|
||||
GlobalRef::Worker(ref worker) => worker.get_url().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// `ScriptChan` used to send messages to the event loop of this global's
|
||||
/// thread.
|
||||
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) =>
|
||||
MainThreadScriptChan(window.main_thread_script_chan().clone()).clone(),
|
||||
GlobalRef::Worker(ref worker) => worker.script_chan(),
|
||||
}
|
||||
}
|
||||
|
||||
/// `ScriptChan` used to send messages to the event loop of this global's
|
||||
/// thread.
|
||||
pub fn networking_task_source(&self) -> Box<ScriptChan + Send> {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.networking_task_source(),
|
||||
GlobalRef::Worker(ref worker) => worker.script_chan(),
|
||||
}
|
||||
}
|
||||
|
||||
/// `ScriptChan` used to send messages to the event loop of this global's
|
||||
/// thread.
|
||||
pub fn file_reading_task_source(&self) -> FileReadingTaskSource {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.file_reading_task_source(),
|
||||
GlobalRef::Worker(ref worker) => worker.file_reading_task_source(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new sender/receiver pair that can be used to implement an on-demand
|
||||
/// event loop. Used for implementing web APIs that require blocking semantics
|
||||
/// without resorting to nested event loops.
|
||||
pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.new_script_pair(),
|
||||
GlobalRef::Worker(ref worker) => worker.new_script_pair(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Process a single event as if it were the next event in the thread queue for
|
||||
/// this global.
|
||||
pub fn process_event(&self, msg: CommonScriptMsg) {
|
||||
match *self {
|
||||
GlobalRef::Window(_) => ScriptThread::process_event(msg),
|
||||
GlobalRef::Worker(ref worker) => worker.process_event(msg),
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate JS code on this global.
|
||||
pub fn evaluate_js_on_global_with_result(
|
||||
&self, code: &str, rval: MutableHandleValue) {
|
||||
self.evaluate_script_on_global_with_result(code, "", rval)
|
||||
}
|
||||
|
||||
/// Evaluate a JS script on this global.
|
||||
#[allow(unsafe_code)]
|
||||
pub fn evaluate_script_on_global_with_result(
|
||||
&self, code: &str, filename: &str, rval: MutableHandleValue) {
|
||||
let metadata = time::TimerMetadata {
|
||||
url: if filename.is_empty() {
|
||||
self.get_url().as_str().into()
|
||||
} else {
|
||||
filename.into()
|
||||
},
|
||||
iframe: time::TimerMetadataFrameType::RootWindow,
|
||||
incremental: time::TimerMetadataReflowType::FirstReflow,
|
||||
};
|
||||
time::profile(
|
||||
time::ProfilerCategory::ScriptEvaluate,
|
||||
Some(metadata),
|
||||
self.time_profiler_chan().clone(),
|
||||
|| {
|
||||
let cx = self.get_cx();
|
||||
let globalhandle = self.reflector().get_jsobject();
|
||||
let code: Vec<u16> = code.encode_utf16().collect();
|
||||
let filename = CString::new(filename).unwrap();
|
||||
|
||||
let _ac = JSAutoCompartment::new(cx, globalhandle.get());
|
||||
let options = CompileOptionsWrapper::new(cx, filename.as_ptr(), 1);
|
||||
unsafe {
|
||||
if !Evaluate2(cx, options.ptr, code.as_ptr(),
|
||||
code.len() as libc::size_t,
|
||||
rval) {
|
||||
debug!("error evaluating JS string");
|
||||
report_pending_exception(cx, true);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(error) = maybe_take_panic_result() {
|
||||
panic::resume_unwind(error);
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// Set the `bool` value to indicate whether developer tools has requested
|
||||
/// updates from the global
|
||||
pub fn set_devtools_wants_updates(&self, send_updates: bool) {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.set_devtools_wants_updates(send_updates),
|
||||
GlobalRef::Worker(worker) => worker.set_devtools_wants_updates(send_updates),
|
||||
}
|
||||
}
|
||||
|
||||
/// Schedule the given `callback` to be invoked after at least `duration` milliseconds have
|
||||
/// passed.
|
||||
pub fn schedule_callback(&self,
|
||||
callback: OneshotTimerCallback,
|
||||
duration: MsDuration)
|
||||
-> OneshotTimerHandle {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.schedule_callback(callback, duration),
|
||||
GlobalRef::Worker(worker) => worker.schedule_callback(callback, duration),
|
||||
}
|
||||
}
|
||||
|
||||
/// Unschedule a previously-scheduled callback.
|
||||
pub fn unschedule_callback(&self, handle: OneshotTimerHandle) {
|
||||
match *self {
|
||||
GlobalRef::Window(window) => window.unschedule_callback(handle),
|
||||
GlobalRef::Worker(worker) => worker.unschedule_callback(handle),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.get_runnable_wrapper(),
|
||||
GlobalRef::Worker(ref worker) => worker.get_runnable_wrapper(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Enqueue a promise callback for subsequent execution.
|
||||
pub fn enqueue_promise_job(&self, job: EnqueuedPromiseCallback) {
|
||||
match *self {
|
||||
GlobalRef::Window(_) => ScriptThread::enqueue_promise_job(job, *self),
|
||||
GlobalRef::Worker(ref worker) => worker.enqueue_promise_job(job),
|
||||
}
|
||||
}
|
||||
|
||||
/// Start the process of executing the pending promise callbacks. They will be invoked
|
||||
/// in FIFO order, synchronously, at some point in the future.
|
||||
pub fn flush_promise_jobs(&self) {
|
||||
match *self {
|
||||
GlobalRef::Window(_) => ScriptThread::flush_promise_jobs(*self),
|
||||
GlobalRef::Worker(ref worker) => worker.flush_promise_jobs(),
|
||||
}
|
||||
}
|
||||
|
||||
/// https://html.spec.whatwg.org/multipage/#report-the-error
|
||||
pub fn report_an_error(&self, error_info: ErrorInfo, value: HandleValue) {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.report_an_error(error_info, value),
|
||||
GlobalRef::Worker(ref worker) => worker.report_an_error(error_info, value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Reflectable for GlobalRef<'a> {
|
||||
fn reflector(&self) -> &Reflector {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.reflector(),
|
||||
GlobalRef::Worker(ref worker) => worker.reflector(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GlobalRoot {
|
||||
/// Obtain a safe reference to the global object that cannot outlive the
|
||||
/// lifetime of this root.
|
||||
pub fn r(&self) -> GlobalRef {
|
||||
match *self {
|
||||
GlobalRoot::Window(ref window) => GlobalRef::Window(window.r()),
|
||||
GlobalRoot::Worker(ref worker) => GlobalRef::Worker(worker.r()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the global object of the realm that the given DOM object's reflector was created in.
|
||||
pub fn global_root_from_reflector<T: Reflectable>(reflector: &T) -> GlobalRoot {
|
||||
unsafe { global_root_from_object(*reflector.reflector().get_jsobject()) }
|
||||
}
|
||||
|
||||
/// Returns the Rust global object from a JS global object.
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn global_root_from_global(global: *mut JSObject) -> GlobalRoot {
|
||||
assert!(!global.is_null());
|
||||
let clasp = JS_GetClass(global);
|
||||
assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0);
|
||||
match root_from_object(global) {
|
||||
Ok(window) => return GlobalRoot::Window(window),
|
||||
Err(_) => (),
|
||||
}
|
||||
|
||||
match root_from_object(global) {
|
||||
Ok(worker) => return GlobalRoot::Worker(worker),
|
||||
Err(_) => (),
|
||||
}
|
||||
|
||||
panic!("found DOM global that doesn't unwrap to Window or WorkerGlobalScope")
|
||||
}
|
||||
|
||||
/// Returns the global object of the realm that the given JS object was created in.
|
||||
#[allow(unrooted_must_root)]
|
||||
pub unsafe fn global_root_from_object(obj: *mut JSObject) -> GlobalRoot {
|
||||
assert!(!obj.is_null());
|
||||
let global = GetGlobalForObjectCrossCompartment(obj);
|
||||
global_root_from_global(global)
|
||||
}
|
||||
|
||||
/// Returns the global object for the given JSContext
|
||||
#[allow(unrooted_must_root)]
|
||||
pub unsafe fn global_root_from_context(cx: *mut JSContext) -> GlobalRoot {
|
||||
let global = CurrentGlobalOrNull(cx);
|
||||
global_root_from_global(global)
|
||||
}
|
||||
|
||||
/// Returns the global object of the realm that the given JS object was created in,
|
||||
/// after unwrapping any wrappers.
|
||||
pub unsafe fn global_root_from_object_maybe_wrapped(mut obj: *mut JSObject) -> GlobalRoot {
|
||||
if IsWrapper(obj) {
|
||||
obj = UnwrapObject(obj, /* stopAtWindowProxy = */ 0);
|
||||
assert!(!obj.is_null());
|
||||
}
|
||||
global_root_from_object(obj)
|
||||
}
|
|
@ -10,10 +10,10 @@ use core::nonzero::NonZero;
|
|||
use dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyAndValueResult;
|
||||
use dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyOrValueResult;
|
||||
use dom::bindings::error::Fallible;
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JS, Root};
|
||||
use dom::bindings::reflector::{Reflector, Reflectable, MutReflectable, reflect_dom_object};
|
||||
use dom::bindings::trace::JSTraceable;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use js::conversions::ToJSValConvertible;
|
||||
use js::jsapi::{JSContext, JSObject, MutableHandleValue, MutableHandleObject, HandleValue};
|
||||
use js::jsval::UndefinedValue;
|
||||
|
@ -85,7 +85,7 @@ impl<T: Reflectable + JSTraceable + Iterable> IterableIterator<T> {
|
|||
/// Create a new iterator instance for the provided iterable DOM interface.
|
||||
pub fn new(iterable: &T,
|
||||
type_: IteratorType,
|
||||
wrap: fn(*mut JSContext, GlobalRef, Box<IterableIterator<T>>)
|
||||
wrap: fn(*mut JSContext, &GlobalScope, Box<IterableIterator<T>>)
|
||||
-> Root<Self>) -> Root<Self> {
|
||||
let iterator = box IterableIterator {
|
||||
reflector: Reflector::new(),
|
||||
|
@ -93,8 +93,7 @@ impl<T: Reflectable + JSTraceable + Iterable> IterableIterator<T> {
|
|||
iterable: JS::from_ref(iterable),
|
||||
index: Cell::new(0),
|
||||
};
|
||||
let global = iterable.global();
|
||||
reflect_dom_object(iterator, global.r(), wrap)
|
||||
reflect_dom_object(iterator, &*iterable.global(), wrap)
|
||||
}
|
||||
|
||||
/// Return the next value from the iterable object.
|
||||
|
|
|
@ -43,8 +43,9 @@
|
|||
//! [`Fallible<T>`](error/type.Fallible.html).
|
||||
//! Methods that use certain WebIDL types like `any` or `object` will get a
|
||||
//! `*mut JSContext` argument prepended to the argument list. Static methods
|
||||
//! will be passed a [`GlobalRef`](global/enum.GlobalRef.html) for the relevant
|
||||
//! global. This argument comes before the `*mut JSContext` argument, if any.
|
||||
//! will be passed a [`&GlobalScope`](../globalscope/struct.GlobalScope.html)
|
||||
//! for the relevant global. This argument comes before the `*mut JSContext`
|
||||
//! argument, if any.
|
||||
//!
|
||||
//! Rust reflections of WebIDL operations (methods)
|
||||
//! -----------------------------------------------
|
||||
|
@ -79,7 +80,7 @@
|
|||
//!
|
||||
//! A WebIDL constructor is turned into a static class method named
|
||||
//! `Constructor`. The arguments of this method will be the arguments of the
|
||||
//! WebIDL constructor, with a `GlobalRef` for the relevant global prepended.
|
||||
//! WebIDL constructor, with a `&GlobalScope` for the relevant global prepended.
|
||||
//! The return value of the constructor for MyInterface is exactly the same as
|
||||
//! that of a method returning an instance of MyInterface. Constructors are
|
||||
//! always [allowed to throw](#throwing-exceptions).
|
||||
|
@ -133,7 +134,6 @@ pub mod cell;
|
|||
pub mod constant;
|
||||
pub mod conversions;
|
||||
pub mod error;
|
||||
pub mod global;
|
||||
pub mod guard;
|
||||
pub mod inheritance;
|
||||
pub mod interface;
|
||||
|
|
|
@ -4,19 +4,24 @@
|
|||
|
||||
//! The `Reflector` struct.
|
||||
|
||||
use dom::bindings::global::{GlobalRef, GlobalRoot, global_root_from_reflector};
|
||||
use dom::bindings::conversions::DerivedFrom;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use js::jsapi::{HandleObject, JSContext, JSObject};
|
||||
use std::cell::UnsafeCell;
|
||||
use std::ptr;
|
||||
|
||||
/// Create the reflector for a new DOM object and yield ownership to the
|
||||
/// reflector.
|
||||
pub fn reflect_dom_object<T: Reflectable>(obj: Box<T>,
|
||||
global: GlobalRef,
|
||||
wrap_fn: fn(*mut JSContext, GlobalRef, Box<T>) -> Root<T>)
|
||||
-> Root<T> {
|
||||
wrap_fn(global.get_cx(), global, obj)
|
||||
pub fn reflect_dom_object<T, U>(
|
||||
obj: Box<T>,
|
||||
global: &U,
|
||||
wrap_fn: fn(*mut JSContext, &GlobalScope, Box<T>) -> Root<T>)
|
||||
-> Root<T>
|
||||
where T: Reflectable, U: DerivedFrom<GlobalScope>
|
||||
{
|
||||
let global_scope = global.upcast();
|
||||
wrap_fn(global_scope.get_cx(), global_scope, obj)
|
||||
}
|
||||
|
||||
/// A struct to store a reference to the reflector of a DOM object.
|
||||
|
@ -74,9 +79,9 @@ pub trait Reflectable {
|
|||
/// Returns the receiver's reflector.
|
||||
fn reflector(&self) -> &Reflector;
|
||||
|
||||
/// Returns the global object of the realm that the Reflectable was created in.
|
||||
fn global(&self) -> GlobalRoot where Self: Sized {
|
||||
global_root_from_reflector(self)
|
||||
/// Returns the global scope of the realm that the Reflectable was created in.
|
||||
fn global(&self) -> Root<GlobalScope> where Self: Sized {
|
||||
GlobalScope::from_reflector(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//! (https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data).
|
||||
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use js::jsapi::{HandleValue, MutableHandleValue};
|
||||
use js::jsapi::{JSContext, JS_ReadStructuredClone, JS_STRUCTURED_CLONE_VERSION};
|
||||
use js::jsapi::{JS_ClearPendingException, JS_WriteStructuredClone};
|
||||
|
@ -60,7 +60,7 @@ impl StructuredCloneData {
|
|||
/// Reads a structured clone.
|
||||
///
|
||||
/// Panics if `JS_ReadStructuredClone` fails.
|
||||
fn read_clone(global: GlobalRef, data: *mut u64, nbytes: size_t, rval: MutableHandleValue) {
|
||||
fn read_clone(global: &GlobalScope, data: *mut u64, nbytes: size_t, rval: MutableHandleValue) {
|
||||
unsafe {
|
||||
assert!(JS_ReadStructuredClone(global.get_cx(),
|
||||
data,
|
||||
|
@ -73,7 +73,7 @@ impl StructuredCloneData {
|
|||
}
|
||||
|
||||
/// Thunk for the actual `read_clone` method. Resolves proper variant for read_clone.
|
||||
pub fn read(self, global: GlobalRef, rval: MutableHandleValue) {
|
||||
pub fn read(self, global: &GlobalScope, rval: MutableHandleValue) {
|
||||
match self {
|
||||
StructuredCloneData::Vector(mut vec_msg) => {
|
||||
let nbytes = vec_msg.len();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue