mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Eagerly define interfaces on non-Window globals (#36604)
These changes make us match Gecko's setup for how Window and non-Window globals are initialized. Since Window globals are much more common than Worker globals, using lazy interface definitions can be a useful memory optimization at the expense of increased complexity for property lookups. Also adds the MayResolve hook for all globals, which is an optimization for the JIT to avoid calling resolve hooks unnecessarily. Testing: Existing test coverage on global interfaces should suffice. --------- Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
436dee8450
commit
76ee127af8
10 changed files with 138 additions and 35 deletions
|
@ -118,6 +118,19 @@ pub(crate) const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks {
|
||||||
instanceClassMatchesProto: Some(instance_class_has_proto_at_depth),
|
instanceClassMatchesProto: Some(instance_class_has_proto_at_depth),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Eagerly define all relevant WebIDL interface constructors on the
|
||||||
|
/// provided global object.
|
||||||
|
pub(crate) fn define_all_exposed_interfaces(
|
||||||
|
global: &GlobalScope,
|
||||||
|
_in_realm: InRealm,
|
||||||
|
_can_gc: CanGc,
|
||||||
|
) {
|
||||||
|
let cx = GlobalScope::get_cx();
|
||||||
|
for (_, interface) in &InterfaceObjectMap::MAP {
|
||||||
|
(interface.define)(cx, global.reflector().get_jsobject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DomHelpers<crate::DomTypeHolder> for crate::DomTypeHolder {
|
impl DomHelpers<crate::DomTypeHolder> for crate::DomTypeHolder {
|
||||||
fn throw_dom_exception(
|
fn throw_dom_exception(
|
||||||
cx: SafeJSContext,
|
cx: SafeJSContext,
|
||||||
|
|
|
@ -42,6 +42,7 @@ use crate::dom::bindings::root::{DomRoot, RootCollection, ThreadLocalStackRoots}
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::bindings::structuredclone;
|
use crate::dom::bindings::structuredclone;
|
||||||
use crate::dom::bindings::trace::{CustomTraceable, RootedTraceableBox};
|
use crate::dom::bindings::trace::{CustomTraceable, RootedTraceableBox};
|
||||||
|
use crate::dom::bindings::utils::define_all_exposed_interfaces;
|
||||||
use crate::dom::errorevent::ErrorEvent;
|
use crate::dom::errorevent::ErrorEvent;
|
||||||
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
use crate::dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
@ -493,7 +494,12 @@ impl DedicatedWorkerGlobalScope {
|
||||||
|
|
||||||
{
|
{
|
||||||
let _ar = AutoWorkerReset::new(&global, worker.clone());
|
let _ar = AutoWorkerReset::new(&global, worker.clone());
|
||||||
let _ac = enter_realm(scope);
|
let realm = enter_realm(scope);
|
||||||
|
define_all_exposed_interfaces(
|
||||||
|
global.upcast(),
|
||||||
|
InRealm::entered(&realm),
|
||||||
|
CanGc::note(),
|
||||||
|
);
|
||||||
scope.execute_script(DOMString::from(source), CanGc::note());
|
scope.execute_script(DOMString::from(source), CanGc::note());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ use crate::dom::bindings::root::{DomRoot, RootCollection, ThreadLocalStackRoots}
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::bindings::structuredclone;
|
use crate::dom::bindings::structuredclone;
|
||||||
use crate::dom::bindings::trace::CustomTraceable;
|
use crate::dom::bindings::trace::CustomTraceable;
|
||||||
|
use crate::dom::bindings::utils::define_all_exposed_interfaces;
|
||||||
use crate::dom::dedicatedworkerglobalscope::AutoWorkerReset;
|
use crate::dom::dedicatedworkerglobalscope::AutoWorkerReset;
|
||||||
use crate::dom::event::Event;
|
use crate::dom::event::Event;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
@ -379,6 +380,11 @@ impl ServiceWorkerGlobalScope {
|
||||||
{
|
{
|
||||||
// TODO: use AutoWorkerReset as in dedicated worker?
|
// TODO: use AutoWorkerReset as in dedicated worker?
|
||||||
let realm = enter_realm(scope);
|
let realm = enter_realm(scope);
|
||||||
|
define_all_exposed_interfaces(
|
||||||
|
scope.upcast(),
|
||||||
|
InRealm::entered(&realm),
|
||||||
|
CanGc::note(),
|
||||||
|
);
|
||||||
scope.execute_script(DOMString::from(source), CanGc::note());
|
scope.execute_script(DOMString::from(source), CanGc::note());
|
||||||
global.dispatch_activate(CanGc::note(), InRealm::entered(&realm));
|
global.dispatch_activate(CanGc::note(), InRealm::entered(&realm));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ use js::rust::Runtime;
|
||||||
use net_traits::ResourceThreads;
|
use net_traits::ResourceThreads;
|
||||||
use net_traits::image_cache::ImageCache;
|
use net_traits::image_cache::ImageCache;
|
||||||
use profile_traits::{mem, time};
|
use profile_traits::{mem, time};
|
||||||
|
use script_bindings::realms::InRealm;
|
||||||
use script_traits::Painter;
|
use script_traits::Painter;
|
||||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||||
use stylo_atoms::Atom;
|
use stylo_atoms::Atom;
|
||||||
|
@ -22,6 +23,7 @@ use stylo_atoms::Atom;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::trace::CustomTraceable;
|
use crate::dom::bindings::trace::CustomTraceable;
|
||||||
|
use crate::dom::bindings::utils::define_all_exposed_interfaces;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::paintworkletglobalscope::{PaintWorkletGlobalScope, PaintWorkletTask};
|
use crate::dom::paintworkletglobalscope::{PaintWorkletGlobalScope, PaintWorkletTask};
|
||||||
use crate::dom::testworkletglobalscope::{TestWorkletGlobalScope, TestWorkletTask};
|
use crate::dom::testworkletglobalscope::{TestWorkletGlobalScope, TestWorkletTask};
|
||||||
|
@ -29,6 +31,7 @@ use crate::dom::testworkletglobalscope::{TestWorkletGlobalScope, TestWorkletTask
|
||||||
use crate::dom::webgpu::identityhub::IdentityHub;
|
use crate::dom::webgpu::identityhub::IdentityHub;
|
||||||
use crate::dom::worklet::WorkletExecutor;
|
use crate::dom::worklet::WorkletExecutor;
|
||||||
use crate::messaging::MainThreadScriptMsg;
|
use crate::messaging::MainThreadScriptMsg;
|
||||||
|
use crate::realms::enter_realm;
|
||||||
use crate::script_module::ScriptFetchOptions;
|
use crate::script_module::ScriptFetchOptions;
|
||||||
use crate::script_runtime::{CanGc, JSContext};
|
use crate::script_runtime::{CanGc, JSContext};
|
||||||
|
|
||||||
|
@ -56,7 +59,7 @@ impl WorkletGlobalScope {
|
||||||
executor: WorkletExecutor,
|
executor: WorkletExecutor,
|
||||||
init: &WorkletGlobalScopeInit,
|
init: &WorkletGlobalScopeInit,
|
||||||
) -> DomRoot<WorkletGlobalScope> {
|
) -> DomRoot<WorkletGlobalScope> {
|
||||||
match scope_type {
|
let scope: DomRoot<WorkletGlobalScope> = match scope_type {
|
||||||
WorkletGlobalScopeType::Test => DomRoot::upcast(TestWorkletGlobalScope::new(
|
WorkletGlobalScopeType::Test => DomRoot::upcast(TestWorkletGlobalScope::new(
|
||||||
runtime,
|
runtime,
|
||||||
pipeline_id,
|
pipeline_id,
|
||||||
|
@ -71,7 +74,12 @@ impl WorkletGlobalScope {
|
||||||
executor,
|
executor,
|
||||||
init,
|
init,
|
||||||
)),
|
)),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let realm = enter_realm(&*scope);
|
||||||
|
define_all_exposed_interfaces(scope.upcast(), InRealm::entered(&realm), CanGc::note());
|
||||||
|
|
||||||
|
scope
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new stack-allocated `WorkletGlobalScope`.
|
/// Create a new stack-allocated `WorkletGlobalScope`.
|
||||||
|
|
|
@ -2405,15 +2405,22 @@ class CGDOMJSClass(CGThing):
|
||||||
"flags": "JSCLASS_FOREGROUND_FINALIZE",
|
"flags": "JSCLASS_FOREGROUND_FINALIZE",
|
||||||
"name": str_to_cstr_ptr(self.descriptor.interface.identifier.name),
|
"name": str_to_cstr_ptr(self.descriptor.interface.identifier.name),
|
||||||
"resolveHook": "None",
|
"resolveHook": "None",
|
||||||
|
"mayResolveHook": "None",
|
||||||
"slots": "1",
|
"slots": "1",
|
||||||
"traceHook": f"{TRACE_HOOK_NAME}::<D>",
|
"traceHook": f"{TRACE_HOOK_NAME}::<D>",
|
||||||
}
|
}
|
||||||
if self.descriptor.isGlobal():
|
if self.descriptor.isGlobal():
|
||||||
assert not self.descriptor.weakReferenceable
|
assert not self.descriptor.weakReferenceable
|
||||||
args["enumerateHook"] = "Some(enumerate_global::<D>)"
|
|
||||||
args["flags"] = "JSCLASS_IS_GLOBAL | JSCLASS_DOM_GLOBAL | JSCLASS_FOREGROUND_FINALIZE"
|
args["flags"] = "JSCLASS_IS_GLOBAL | JSCLASS_DOM_GLOBAL | JSCLASS_FOREGROUND_FINALIZE"
|
||||||
args["slots"] = "JSCLASS_GLOBAL_SLOT_COUNT + 1"
|
args["slots"] = "JSCLASS_GLOBAL_SLOT_COUNT + 1"
|
||||||
args["resolveHook"] = "Some(resolve_global::<D>)"
|
if self.descriptor.interface.getExtendedAttribute("NeedResolve"):
|
||||||
|
args["enumerateHook"] = "Some(enumerate_window::<D>)"
|
||||||
|
args["resolveHook"] = "Some(resolve_window::<D>)"
|
||||||
|
args["mayResolveHook"] = "Some(may_resolve_window::<D>)"
|
||||||
|
else:
|
||||||
|
args["enumerateHook"] = "Some(enumerate_global)"
|
||||||
|
args["resolveHook"] = "Some(resolve_global)"
|
||||||
|
args["mayResolveHook"] = "Some(may_resolve_global)"
|
||||||
args["traceHook"] = "js::jsapi::JS_GlobalObjectTraceHook"
|
args["traceHook"] = "js::jsapi::JS_GlobalObjectTraceHook"
|
||||||
elif self.descriptor.weakReferenceable:
|
elif self.descriptor.weakReferenceable:
|
||||||
args["slots"] = "2"
|
args["slots"] = "2"
|
||||||
|
@ -2427,7 +2434,7 @@ pub(crate) fn init_class_ops<D: DomTypes>() {{
|
||||||
enumerate: None,
|
enumerate: None,
|
||||||
newEnumerate: {args['enumerateHook']},
|
newEnumerate: {args['enumerateHook']},
|
||||||
resolve: {args['resolveHook']},
|
resolve: {args['resolveHook']},
|
||||||
mayResolve: None,
|
mayResolve: {args['mayResolveHook']},
|
||||||
finalize: Some({args['finalizeHook']}),
|
finalize: Some({args['finalizeHook']}),
|
||||||
call: None,
|
call: None,
|
||||||
construct: None,
|
construct: None,
|
||||||
|
|
|
@ -127,10 +127,11 @@ pub(crate) mod module {
|
||||||
pub(crate) use crate::script_runtime::CanGc;
|
pub(crate) use crate::script_runtime::CanGc;
|
||||||
pub(crate) use crate::utils::{
|
pub(crate) use crate::utils::{
|
||||||
AsVoidPtr, DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, DOMClass, DOMJSClass, JSCLASS_DOM_GLOBAL,
|
AsVoidPtr, DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, DOMClass, DOMJSClass, JSCLASS_DOM_GLOBAL,
|
||||||
ProtoOrIfaceArray, enumerate_global, exception_to_promise, generic_getter,
|
ProtoOrIfaceArray, enumerate_global, enumerate_window, exception_to_promise,
|
||||||
generic_lenient_getter, generic_lenient_setter, generic_method, generic_setter,
|
generic_getter, generic_lenient_getter, generic_lenient_setter, generic_method,
|
||||||
generic_static_promise_method, get_array_index_from_id, get_property_on_prototype,
|
generic_setter, generic_static_promise_method, get_array_index_from_id,
|
||||||
has_property_on_prototype, resolve_global, trace_global,
|
get_property_on_prototype, has_property_on_prototype, may_resolve_global,
|
||||||
|
may_resolve_window, resolve_global, resolve_window, trace_global,
|
||||||
};
|
};
|
||||||
pub(crate) use crate::weakref::DOM_WEAK_SLOT;
|
pub(crate) use crate::weakref::DOM_WEAK_SLOT;
|
||||||
pub(crate) use crate::{JSTraceable, proxyhandler};
|
pub(crate) use crate::{JSTraceable, proxyhandler};
|
||||||
|
|
|
@ -18,9 +18,10 @@ use js::jsapi::{
|
||||||
GetLinearStringLength, GetNonCCWObjectGlobal, HandleId as RawHandleId,
|
GetLinearStringLength, GetNonCCWObjectGlobal, HandleId as RawHandleId,
|
||||||
HandleObject as RawHandleObject, Heap, JS_AtomizeStringN, JS_ClearPendingException,
|
HandleObject as RawHandleObject, Heap, JS_AtomizeStringN, JS_ClearPendingException,
|
||||||
JS_DeprecatedStringHasLatin1Chars, JS_GetLatin1StringCharsAndLength, JS_IsExceptionPending,
|
JS_DeprecatedStringHasLatin1Chars, JS_GetLatin1StringCharsAndLength, JS_IsExceptionPending,
|
||||||
JS_IsGlobalObject, JS_NewEnumerateStandardClasses, JS_ResolveStandardClass, JSAtom, JSContext,
|
JS_IsGlobalObject, JS_MayResolveStandardClass, JS_NewEnumerateStandardClasses,
|
||||||
JSJitInfo, JSObject, JSTracer, MutableHandleIdVector as RawMutableHandleIdVector,
|
JS_ResolveStandardClass, JSAtom, JSAtomState, JSContext, JSJitInfo, JSObject, JSTracer,
|
||||||
MutableHandleValue as RawMutableHandleValue, ObjectOpResult, StringIsArrayIndex,
|
MutableHandleIdVector as RawMutableHandleIdVector, MutableHandleValue as RawMutableHandleValue,
|
||||||
|
ObjectOpResult, PropertyKey, StringIsArrayIndex, jsid,
|
||||||
};
|
};
|
||||||
use js::jsid::StringId;
|
use js::jsid::StringId;
|
||||||
use js::jsval::{JSVal, UndefinedValue};
|
use js::jsval::{JSVal, UndefinedValue};
|
||||||
|
@ -30,7 +31,7 @@ use js::rust::wrappers::{
|
||||||
JS_SetPendingException, JS_SetProperty,
|
JS_SetPendingException, JS_SetProperty,
|
||||||
};
|
};
|
||||||
use js::rust::{
|
use js::rust::{
|
||||||
HandleId, HandleObject, HandleValue, MutableHandleValue, ToString, get_object_class,
|
HandleId, HandleObject, HandleValue, MutableHandleValue, Runtime, ToString, get_object_class,
|
||||||
};
|
};
|
||||||
use js::{JS_CALLEE, rooted};
|
use js::{JS_CALLEE, rooted};
|
||||||
use malloc_size_of::MallocSizeOfOps;
|
use malloc_size_of::MallocSizeOfOps;
|
||||||
|
@ -577,15 +578,25 @@ impl AsCCharPtrPtr for [u8] {
|
||||||
|
|
||||||
/// Enumerate lazy properties of a global object.
|
/// Enumerate lazy properties of a global object.
|
||||||
/// Modeled after <https://github.com/mozilla/gecko-dev/blob/3fd619f47/dom/bindings/BindingUtils.cpp#L2814>
|
/// Modeled after <https://github.com/mozilla/gecko-dev/blob/3fd619f47/dom/bindings/BindingUtils.cpp#L2814>
|
||||||
/// and <https://github.com/mozilla/gecko-dev/blob/3fd619f47/dom/base/nsGlobalWindowInner.cpp#3297>
|
pub(crate) unsafe extern "C" fn enumerate_global(
|
||||||
pub(crate) unsafe extern "C" fn enumerate_global<D: DomTypes>(
|
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
obj: RawHandleObject,
|
obj: RawHandleObject,
|
||||||
props: RawMutableHandleIdVector,
|
props: RawMutableHandleIdVector,
|
||||||
enumerable_only: bool,
|
enumerable_only: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
assert!(JS_IsGlobalObject(obj.get()));
|
assert!(JS_IsGlobalObject(obj.get()));
|
||||||
if !JS_NewEnumerateStandardClasses(cx, obj, props, enumerable_only) {
|
JS_NewEnumerateStandardClasses(cx, obj, props, enumerable_only)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enumerate lazy properties of a global object that is a Window.
|
||||||
|
/// <https://github.com/mozilla/gecko-dev/blob/3fd619f47/dom/base/nsGlobalWindowInner.cpp#3297>
|
||||||
|
pub(crate) unsafe extern "C" fn enumerate_window<D: DomTypes>(
|
||||||
|
cx: *mut JSContext,
|
||||||
|
obj: RawHandleObject,
|
||||||
|
props: RawMutableHandleIdVector,
|
||||||
|
enumerable_only: bool,
|
||||||
|
) -> bool {
|
||||||
|
if !enumerate_global(cx, obj, props, enumerable_only) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,34 +621,68 @@ pub(crate) unsafe extern "C" fn enumerate_global<D: DomTypes>(
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the resolve hook for this global may resolve the provided id.
|
||||||
|
/// <https://searchfox.org/mozilla-central/rev/f3c8c63a097b61bb1f01e13629b9514e09395947/dom/bindings/BindingUtils.cpp#2809>
|
||||||
|
/// <https://searchfox.org/mozilla-central/rev/f3c8c63a097b61bb1f01e13629b9514e09395947/js/public/Class.h#283-291>
|
||||||
|
pub(crate) unsafe extern "C" fn may_resolve_global(
|
||||||
|
names: *const JSAtomState,
|
||||||
|
id: PropertyKey,
|
||||||
|
maybe_obj: *mut JSObject,
|
||||||
|
) -> bool {
|
||||||
|
JS_MayResolveStandardClass(names, id, maybe_obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the resolve hook for this window may resolve the provided id.
|
||||||
|
/// <https://searchfox.org/mozilla-central/rev/f3c8c63a097b61bb1f01e13629b9514e09395947/dom/base/nsGlobalWindowInner.cpp#3275>
|
||||||
|
/// <https://searchfox.org/mozilla-central/rev/f3c8c63a097b61bb1f01e13629b9514e09395947/js/public/Class.h#283-291>
|
||||||
|
pub(crate) unsafe extern "C" fn may_resolve_window<D: DomTypes>(
|
||||||
|
names: *const JSAtomState,
|
||||||
|
id: PropertyKey,
|
||||||
|
maybe_obj: *mut JSObject,
|
||||||
|
) -> bool {
|
||||||
|
if may_resolve_global(names, id, maybe_obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cx = Runtime::get()
|
||||||
|
.expect("There must be a JSContext active")
|
||||||
|
.as_ptr();
|
||||||
|
let Ok(bytes) = latin1_bytes_from_id(cx, id) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
<D as DomHelpers<D>>::interface_map().contains_key(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolve a lazy global property, for interface objects and named constructors.
|
/// Resolve a lazy global property, for interface objects and named constructors.
|
||||||
pub(crate) unsafe extern "C" fn resolve_global<D: DomTypes>(
|
pub(crate) unsafe extern "C" fn resolve_global(
|
||||||
cx: *mut JSContext,
|
cx: *mut JSContext,
|
||||||
obj: RawHandleObject,
|
obj: RawHandleObject,
|
||||||
id: RawHandleId,
|
id: RawHandleId,
|
||||||
rval: *mut bool,
|
rval: *mut bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
assert!(JS_IsGlobalObject(obj.get()));
|
assert!(JS_IsGlobalObject(obj.get()));
|
||||||
if !JS_ResolveStandardClass(cx, obj, id, rval) {
|
JS_ResolveStandardClass(cx, obj, id, rval)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve a lazy global property for a Window global.
|
||||||
|
pub(crate) unsafe extern "C" fn resolve_window<D: DomTypes>(
|
||||||
|
cx: *mut JSContext,
|
||||||
|
obj: RawHandleObject,
|
||||||
|
id: RawHandleId,
|
||||||
|
rval: *mut bool,
|
||||||
|
) -> bool {
|
||||||
|
if !resolve_global(cx, obj, id, rval) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if *rval {
|
if *rval {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if !id.is_string() {
|
let Ok(bytes) = latin1_bytes_from_id(cx, *id) else {
|
||||||
*rval = false;
|
*rval = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
};
|
||||||
|
|
||||||
let string = id.to_string();
|
|
||||||
if !JS_DeprecatedStringHasLatin1Chars(string) {
|
|
||||||
*rval = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let mut length = 0;
|
|
||||||
let ptr = JS_GetLatin1StringCharsAndLength(cx, ptr::null(), string, &mut length);
|
|
||||||
assert!(!ptr.is_null());
|
|
||||||
let bytes = slice::from_raw_parts(ptr, length);
|
|
||||||
|
|
||||||
if let Some(interface) = <D as DomHelpers<D>>::interface_map().get(bytes) {
|
if let Some(interface) = <D as DomHelpers<D>>::interface_map().get(bytes) {
|
||||||
(interface.define)(SafeJSContext::from_ptr(cx), Handle::from_raw(obj));
|
(interface.define)(SafeJSContext::from_ptr(cx), Handle::from_raw(obj));
|
||||||
|
@ -647,3 +692,22 @@ pub(crate) unsafe extern "C" fn resolve_global<D: DomTypes>(
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a slice of bytes corresponding to the bytes in the provided string id.
|
||||||
|
/// Returns an error if the id is not a string, or the string contains non-latin1 characters.
|
||||||
|
/// # Safety
|
||||||
|
/// The slice is only valid as long as the original id is not garbage collected.
|
||||||
|
unsafe fn latin1_bytes_from_id(cx: *mut JSContext, id: jsid) -> Result<&'static [u8], ()> {
|
||||||
|
if !id.is_string() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let string = id.to_string();
|
||||||
|
if !JS_DeprecatedStringHasLatin1Chars(string) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let mut length = 0;
|
||||||
|
let ptr = JS_GetLatin1StringCharsAndLength(cx, ptr::null(), string, &mut length);
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
Ok(slice::from_raw_parts(ptr, length))
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#window
|
// https://html.spec.whatwg.org/multipage/#window
|
||||||
[Global=Window, Exposed=Window /*, LegacyUnenumerableNamedProperties */]
|
[Global=Window, Exposed=Window, LegacyUnenumerableNamedProperties, NeedResolve]
|
||||||
/*sealed*/ interface Window : GlobalScope {
|
/*sealed*/ interface Window : GlobalScope {
|
||||||
// the current browsing context
|
// the current browsing context
|
||||||
[LegacyUnforgeable, CrossOriginReadable] readonly attribute WindowProxy window;
|
[LegacyUnforgeable, CrossOriginReadable] readonly attribute WindowProxy window;
|
||||||
|
|
2
tests/wpt/mozilla/meta/MANIFEST.json
vendored
2
tests/wpt/mozilla/meta/MANIFEST.json
vendored
|
@ -13531,7 +13531,7 @@
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"interfaces.worker.js": [
|
"interfaces.worker.js": [
|
||||||
"8af942c0f99218fb39770cdcf299eaa230339010",
|
"8d109502622fac7266a4564de09684a3ab94118c",
|
||||||
[
|
[
|
||||||
"mozilla/interfaces.worker.html",
|
"mozilla/interfaces.worker.html",
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -107,7 +107,6 @@ test_interfaces([
|
||||||
"Response",
|
"Response",
|
||||||
"SecurityPolicyViolationEvent",
|
"SecurityPolicyViolationEvent",
|
||||||
"ServiceWorkerContainer",
|
"ServiceWorkerContainer",
|
||||||
"SVGRect",
|
|
||||||
"TextDecoder",
|
"TextDecoder",
|
||||||
"TextEncoder",
|
"TextEncoder",
|
||||||
"TrustedHTML",
|
"TrustedHTML",
|
||||||
|
@ -129,7 +128,6 @@ test_interfaces([
|
||||||
"WebGLShaderPrecisionFormat",
|
"WebGLShaderPrecisionFormat",
|
||||||
"WebGLTexture",
|
"WebGLTexture",
|
||||||
"WebGLUniformLocation",
|
"WebGLUniformLocation",
|
||||||
"WebKitCSSMatrix",
|
|
||||||
"WebSocket",
|
"WebSocket",
|
||||||
"WeakRef",
|
"WeakRef",
|
||||||
"Worker",
|
"Worker",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue