mirror of
https://github.com/servo/servo.git
synced 2025-08-01 03:30:33 +01:00
bindings: Fix support for interface members in setlike/maplike. (#35651)
#30151 added support for setlike and maplike declarations in WebIDL, but the tests only validated if generator code worked with 'DOMString' as the key type. The support for interface type as members was broken as `DomRoot<T>` didn't satify the bounds `Eq` and `Hash` needed by the `Key` and `Value` types in `Setlike` and `Maplike` traits respectively. In addition, the splitting of bindings into a separate 'script_bindings' crate had also broken support for this in CodegenRust.py, as the types used within the definition of `DomTraits` were not referenced using `Self::`. This patch fixes the WebIDL code generator by doing a simple string replacement on the return value of `getRetvalDeclarationForType` so that the proper `Self::` is used. I'm not not sure if there is a better approach to this as it seems most logic in CodegenRust.py uses the `D::` prefix that is expected to be available only when compiling `script` crate and not `script_bindings`. This patch also adds the missing trait implementations for `DomRoot` and ensures that the generated code works for both members of primitive and interface types by splitting the existing `TestBinding{Map,Set}Like` interfaces into `TestBinding{Map,Set}LikeWith{Primitive,Interface}` tests. Fixes #35542. Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
parent
1d62776102
commit
3cf4ef61ef
15 changed files with 570 additions and 266 deletions
|
@ -544,10 +544,12 @@ pub(crate) mod svggraphicselement;
|
||||||
pub(crate) mod svgsvgelement;
|
pub(crate) mod svgsvgelement;
|
||||||
pub(crate) mod testbinding;
|
pub(crate) mod testbinding;
|
||||||
pub(crate) mod testbindingiterable;
|
pub(crate) mod testbindingiterable;
|
||||||
pub(crate) mod testbindingmaplike;
|
pub(crate) mod testbindingmaplikewithinterface;
|
||||||
|
pub(crate) mod testbindingmaplikewithprimitive;
|
||||||
pub(crate) mod testbindingpairiterable;
|
pub(crate) mod testbindingpairiterable;
|
||||||
pub(crate) mod testbindingproxy;
|
pub(crate) mod testbindingproxy;
|
||||||
pub(crate) mod testbindingsetlike;
|
pub(crate) mod testbindingsetlikewithinterface;
|
||||||
|
pub(crate) mod testbindingsetlikewithprimitive;
|
||||||
pub(crate) mod testns;
|
pub(crate) mod testns;
|
||||||
pub(crate) mod testworklet;
|
pub(crate) mod testworklet;
|
||||||
pub(crate) mod testworkletglobalscope;
|
pub(crate) mod testworkletglobalscope;
|
||||||
|
|
100
components/script/dom/testbindingmaplikewithinterface.rs
Normal file
100
components/script/dom/testbindingmaplikewithinterface.rs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// check-tidy: no specs after this line
|
||||||
|
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
use js::rust::HandleObject;
|
||||||
|
|
||||||
|
use super::bindings::error::Error;
|
||||||
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::TestBindingMaplikeWithInterfaceBinding::TestBindingMaplikeWithInterfaceMethods;
|
||||||
|
use crate::dom::bindings::error::Fallible;
|
||||||
|
use crate::dom::bindings::like::Maplike;
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector};
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::testbinding::TestBinding;
|
||||||
|
use crate::maplike;
|
||||||
|
use crate::script_runtime::CanGc;
|
||||||
|
|
||||||
|
/// maplike<DOMString, TestBinding>
|
||||||
|
#[dom_struct]
|
||||||
|
pub(crate) struct TestBindingMaplikeWithInterface {
|
||||||
|
reflector: Reflector,
|
||||||
|
#[custom_trace]
|
||||||
|
internal: DomRefCell<IndexMap<DOMString, DomRoot<TestBinding>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestBindingMaplikeWithInterface {
|
||||||
|
fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
proto: Option<HandleObject>,
|
||||||
|
can_gc: CanGc,
|
||||||
|
) -> DomRoot<TestBindingMaplikeWithInterface> {
|
||||||
|
reflect_dom_object_with_proto(
|
||||||
|
Box::new(TestBindingMaplikeWithInterface {
|
||||||
|
reflector: Reflector::new(),
|
||||||
|
internal: DomRefCell::new(IndexMap::new()),
|
||||||
|
}),
|
||||||
|
global,
|
||||||
|
proto,
|
||||||
|
can_gc,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestBindingMaplikeWithInterfaceMethods<crate::DomTypeHolder>
|
||||||
|
for TestBindingMaplikeWithInterface
|
||||||
|
{
|
||||||
|
fn Constructor(
|
||||||
|
global: &GlobalScope,
|
||||||
|
proto: Option<HandleObject>,
|
||||||
|
can_gc: CanGc,
|
||||||
|
) -> Fallible<DomRoot<TestBindingMaplikeWithInterface>> {
|
||||||
|
Ok(TestBindingMaplikeWithInterface::new(global, proto, can_gc))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SetInternal(&self, key: DOMString, value: &TestBinding) {
|
||||||
|
let value = DomRoot::from_ref(value);
|
||||||
|
self.internal.set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ClearInternal(&self) {
|
||||||
|
self.internal.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn DeleteInternal(&self, key: DOMString) -> bool {
|
||||||
|
self.internal.delete(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn HasInternal(&self, key: DOMString) -> bool {
|
||||||
|
self.internal.has(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn GetInternal(&self, key: DOMString) -> Fallible<DomRoot<TestBinding>> {
|
||||||
|
// TODO: error type?
|
||||||
|
self.internal
|
||||||
|
.borrow()
|
||||||
|
.get(&key)
|
||||||
|
.ok_or_else(|| Error::Type(format!("No entry for key {key}")))
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Size(&self) -> u32 {
|
||||||
|
self.internal.size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this error is wrong because if we inline Self::Key and Self::Value all errors are gone
|
||||||
|
// TODO: FIX THIS
|
||||||
|
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||||
|
impl Maplike for TestBindingMaplikeWithInterface {
|
||||||
|
type Key = DOMString;
|
||||||
|
type Value = DomRoot<TestBinding>;
|
||||||
|
|
||||||
|
maplike!(self, internal);
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ use js::rust::HandleObject;
|
||||||
|
|
||||||
use super::bindings::error::Error;
|
use super::bindings::error::Error;
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
use crate::dom::bindings::codegen::Bindings::TestBindingMaplikeBinding::TestBindingMaplikeMethods;
|
use crate::dom::bindings::codegen::Bindings::TestBindingMaplikeWithPrimitiveBinding::TestBindingMaplikeWithPrimitiveMethods;
|
||||||
use crate::dom::bindings::error::Fallible;
|
use crate::dom::bindings::error::Fallible;
|
||||||
use crate::dom::bindings::like::Maplike;
|
use crate::dom::bindings::like::Maplike;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector};
|
||||||
|
@ -22,20 +22,20 @@ use crate::script_runtime::CanGc;
|
||||||
|
|
||||||
/// maplike<DOMString, long>
|
/// maplike<DOMString, long>
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub(crate) struct TestBindingMaplike {
|
pub(crate) struct TestBindingMaplikeWithPrimitive {
|
||||||
reflector: Reflector,
|
reflector: Reflector,
|
||||||
#[custom_trace]
|
#[custom_trace]
|
||||||
internal: DomRefCell<IndexMap<DOMString, i32>>,
|
internal: DomRefCell<IndexMap<DOMString, i32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestBindingMaplike {
|
impl TestBindingMaplikeWithPrimitive {
|
||||||
fn new(
|
fn new(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
proto: Option<HandleObject>,
|
proto: Option<HandleObject>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<TestBindingMaplike> {
|
) -> DomRoot<TestBindingMaplikeWithPrimitive> {
|
||||||
reflect_dom_object_with_proto(
|
reflect_dom_object_with_proto(
|
||||||
Box::new(TestBindingMaplike {
|
Box::new(TestBindingMaplikeWithPrimitive {
|
||||||
reflector: Reflector::new(),
|
reflector: Reflector::new(),
|
||||||
internal: DomRefCell::new(IndexMap::new()),
|
internal: DomRefCell::new(IndexMap::new()),
|
||||||
}),
|
}),
|
||||||
|
@ -46,13 +46,15 @@ impl TestBindingMaplike {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestBindingMaplikeMethods<crate::DomTypeHolder> for TestBindingMaplike {
|
impl TestBindingMaplikeWithPrimitiveMethods<crate::DomTypeHolder>
|
||||||
|
for TestBindingMaplikeWithPrimitive
|
||||||
|
{
|
||||||
fn Constructor(
|
fn Constructor(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
proto: Option<HandleObject>,
|
proto: Option<HandleObject>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Fallible<DomRoot<TestBindingMaplike>> {
|
) -> Fallible<DomRoot<TestBindingMaplikeWithPrimitive>> {
|
||||||
Ok(TestBindingMaplike::new(global, proto, can_gc))
|
Ok(TestBindingMaplikeWithPrimitive::new(global, proto, can_gc))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetInternal(&self, key: DOMString, value: i32) {
|
fn SetInternal(&self, key: DOMString, value: i32) {
|
||||||
|
@ -88,7 +90,7 @@ impl TestBindingMaplikeMethods<crate::DomTypeHolder> for TestBindingMaplike {
|
||||||
// this error is wrong because if we inline Self::Key and Self::Value all errors are gone
|
// this error is wrong because if we inline Self::Key and Self::Value all errors are gone
|
||||||
// TODO: FIX THIS
|
// TODO: FIX THIS
|
||||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||||
impl Maplike for TestBindingMaplike {
|
impl Maplike for TestBindingMaplikeWithPrimitive {
|
||||||
type Key = DOMString;
|
type Key = DOMString;
|
||||||
type Value = i32;
|
type Value = i32;
|
||||||
|
|
71
components/script/dom/testbindingsetlikewithinterface.rs
Normal file
71
components/script/dom/testbindingsetlikewithinterface.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// check-tidy: no specs after this line
|
||||||
|
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use indexmap::IndexSet;
|
||||||
|
use js::rust::HandleObject;
|
||||||
|
|
||||||
|
use super::bindings::like::Setlike;
|
||||||
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::TestBindingSetlikeWithInterfaceBinding::TestBindingSetlikeWithInterfaceMethods;
|
||||||
|
use crate::dom::bindings::error::Fallible;
|
||||||
|
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector};
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::testbinding::TestBinding;
|
||||||
|
use crate::script_runtime::CanGc;
|
||||||
|
use crate::setlike;
|
||||||
|
|
||||||
|
// setlike<TestBinding>
|
||||||
|
#[dom_struct]
|
||||||
|
pub(crate) struct TestBindingSetlikeWithInterface {
|
||||||
|
reflector: Reflector,
|
||||||
|
#[custom_trace]
|
||||||
|
internal: DomRefCell<IndexSet<DomRoot<TestBinding>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestBindingSetlikeWithInterface {
|
||||||
|
fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
proto: Option<HandleObject>,
|
||||||
|
can_gc: CanGc,
|
||||||
|
) -> DomRoot<TestBindingSetlikeWithInterface> {
|
||||||
|
reflect_dom_object_with_proto(
|
||||||
|
Box::new(TestBindingSetlikeWithInterface {
|
||||||
|
reflector: Reflector::new(),
|
||||||
|
internal: DomRefCell::new(IndexSet::new()),
|
||||||
|
}),
|
||||||
|
global,
|
||||||
|
proto,
|
||||||
|
can_gc,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestBindingSetlikeWithInterfaceMethods<crate::DomTypeHolder>
|
||||||
|
for TestBindingSetlikeWithInterface
|
||||||
|
{
|
||||||
|
fn Constructor(
|
||||||
|
global: &GlobalScope,
|
||||||
|
proto: Option<HandleObject>,
|
||||||
|
can_gc: CanGc,
|
||||||
|
) -> Fallible<DomRoot<TestBindingSetlikeWithInterface>> {
|
||||||
|
Ok(TestBindingSetlikeWithInterface::new(global, proto, can_gc))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Size(&self) -> u32 {
|
||||||
|
self.internal.size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this error is wrong because if we inline Self::Key and Self::Value all errors are gone
|
||||||
|
// TODO: FIX THIS
|
||||||
|
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||||
|
impl Setlike for TestBindingSetlikeWithInterface {
|
||||||
|
type Key = DomRoot<TestBinding>;
|
||||||
|
|
||||||
|
setlike!(self, internal);
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ use js::rust::HandleObject;
|
||||||
|
|
||||||
use super::bindings::like::Setlike;
|
use super::bindings::like::Setlike;
|
||||||
use crate::dom::bindings::cell::DomRefCell;
|
use crate::dom::bindings::cell::DomRefCell;
|
||||||
use crate::dom::bindings::codegen::Bindings::TestBindingSetlikeBinding::TestBindingSetlikeMethods;
|
use crate::dom::bindings::codegen::Bindings::TestBindingSetlikeWithPrimitiveBinding::TestBindingSetlikeWithPrimitiveMethods;
|
||||||
use crate::dom::bindings::error::Fallible;
|
use crate::dom::bindings::error::Fallible;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, Reflector};
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
@ -21,20 +21,20 @@ use crate::setlike;
|
||||||
|
|
||||||
// setlike<DOMString>
|
// setlike<DOMString>
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub(crate) struct TestBindingSetlike {
|
pub(crate) struct TestBindingSetlikeWithPrimitive {
|
||||||
reflector: Reflector,
|
reflector: Reflector,
|
||||||
#[custom_trace]
|
#[custom_trace]
|
||||||
internal: DomRefCell<IndexSet<DOMString>>,
|
internal: DomRefCell<IndexSet<DOMString>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestBindingSetlike {
|
impl TestBindingSetlikeWithPrimitive {
|
||||||
fn new(
|
fn new(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
proto: Option<HandleObject>,
|
proto: Option<HandleObject>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> DomRoot<TestBindingSetlike> {
|
) -> DomRoot<TestBindingSetlikeWithPrimitive> {
|
||||||
reflect_dom_object_with_proto(
|
reflect_dom_object_with_proto(
|
||||||
Box::new(TestBindingSetlike {
|
Box::new(TestBindingSetlikeWithPrimitive {
|
||||||
reflector: Reflector::new(),
|
reflector: Reflector::new(),
|
||||||
internal: DomRefCell::new(IndexSet::new()),
|
internal: DomRefCell::new(IndexSet::new()),
|
||||||
}),
|
}),
|
||||||
|
@ -45,13 +45,15 @@ impl TestBindingSetlike {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestBindingSetlikeMethods<crate::DomTypeHolder> for TestBindingSetlike {
|
impl TestBindingSetlikeWithPrimitiveMethods<crate::DomTypeHolder>
|
||||||
|
for TestBindingSetlikeWithPrimitive
|
||||||
|
{
|
||||||
fn Constructor(
|
fn Constructor(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
proto: Option<HandleObject>,
|
proto: Option<HandleObject>,
|
||||||
can_gc: CanGc,
|
can_gc: CanGc,
|
||||||
) -> Fallible<DomRoot<TestBindingSetlike>> {
|
) -> Fallible<DomRoot<TestBindingSetlikeWithPrimitive>> {
|
||||||
Ok(TestBindingSetlike::new(global, proto, can_gc))
|
Ok(TestBindingSetlikeWithPrimitive::new(global, proto, can_gc))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Size(&self) -> u32 {
|
fn Size(&self) -> u32 {
|
||||||
|
@ -62,7 +64,7 @@ impl TestBindingSetlikeMethods<crate::DomTypeHolder> for TestBindingSetlike {
|
||||||
// this error is wrong because if we inline Self::Key and Self::Value all errors are gone
|
// this error is wrong because if we inline Self::Key and Self::Value all errors are gone
|
||||||
// TODO: FIX THIS
|
// TODO: FIX THIS
|
||||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||||
impl Setlike for TestBindingSetlike {
|
impl Setlike for TestBindingSetlikeWithPrimitive {
|
||||||
type Key = DOMString;
|
type Key = DOMString;
|
||||||
|
|
||||||
setlike!(self, internal);
|
setlike!(self, internal);
|
|
@ -2688,6 +2688,10 @@ def DomTypes(descriptors, descriptorProvider, dictionaries, callbacks, typedefs,
|
||||||
]
|
]
|
||||||
joinedTraits = ' + '.join(traits)
|
joinedTraits = ' + '.join(traits)
|
||||||
elements = [CGGeneric(f"pub(crate) trait DomTypes: {joinedTraits} where Self: 'static {{\n")]
|
elements = [CGGeneric(f"pub(crate) trait DomTypes: {joinedTraits} where Self: 'static {{\n")]
|
||||||
|
|
||||||
|
def fixupInterfaceTypeReferences(typename):
|
||||||
|
return typename.replace("D::", "Self::")
|
||||||
|
|
||||||
for descriptor in descriptors:
|
for descriptor in descriptors:
|
||||||
iface_name = descriptor.interface.identifier.name
|
iface_name = descriptor.interface.identifier.name
|
||||||
traits = []
|
traits = []
|
||||||
|
@ -2711,11 +2715,17 @@ def DomTypes(descriptors, descriptorProvider, dictionaries, callbacks, typedefs,
|
||||||
iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
|
iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
|
||||||
if iterableDecl:
|
if iterableDecl:
|
||||||
if iterableDecl.isMaplike():
|
if iterableDecl.isMaplike():
|
||||||
keytype = getRetvalDeclarationForType(iterableDecl.keyType, None).define()
|
keytype = fixupInterfaceTypeReferences(
|
||||||
valuetype = getRetvalDeclarationForType(iterableDecl.valueType, None).define()
|
getRetvalDeclarationForType(iterableDecl.keyType, descriptor).define()
|
||||||
|
)
|
||||||
|
valuetype = fixupInterfaceTypeReferences(
|
||||||
|
getRetvalDeclarationForType(iterableDecl.valueType, descriptor).define()
|
||||||
|
)
|
||||||
traits += [f"crate::dom::bindings::like::Maplike<Key={keytype}, Value={valuetype}>"]
|
traits += [f"crate::dom::bindings::like::Maplike<Key={keytype}, Value={valuetype}>"]
|
||||||
if iterableDecl.isSetlike():
|
if iterableDecl.isSetlike():
|
||||||
keytype = getRetvalDeclarationForType(iterableDecl.keyType, None).define()
|
keytype = fixupInterfaceTypeReferences(
|
||||||
|
getRetvalDeclarationForType(iterableDecl.keyType, descriptor).define()
|
||||||
|
)
|
||||||
traits += [f"crate::dom::bindings::like::Setlike<Key={keytype}>"]
|
traits += [f"crate::dom::bindings::like::Setlike<Key={keytype}>"]
|
||||||
if iterableDecl.hasKeyType():
|
if iterableDecl.hasKeyType():
|
||||||
traits += [
|
traits += [
|
||||||
|
@ -2769,7 +2779,11 @@ def DomTypes(descriptors, descriptorProvider, dictionaries, callbacks, typedefs,
|
||||||
CGGeneric(f" type {firstCap(iface_name)}: {' + '.join(traits)};\n")
|
CGGeneric(f" type {firstCap(iface_name)}: {' + '.join(traits)};\n")
|
||||||
]
|
]
|
||||||
elements += [CGGeneric("}\n")]
|
elements += [CGGeneric("}\n")]
|
||||||
return CGList([CGGeneric("use crate::dom::bindings::str::DOMString;\n")] + elements)
|
imports = [
|
||||||
|
CGGeneric("use crate::dom::bindings::root::DomRoot;\n"),
|
||||||
|
CGGeneric("use crate::dom::bindings::str::DOMString;\n"),
|
||||||
|
]
|
||||||
|
return CGList(imports + elements)
|
||||||
|
|
||||||
|
|
||||||
def DomTypeHolder(descriptors, descriptorProvider, dictionaries, callbacks, typedefs, config):
|
def DomTypeHolder(descriptors, descriptorProvider, dictionaries, callbacks, typedefs, config):
|
||||||
|
|
|
@ -351,6 +351,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: DomObject> Eq for DomRoot<T> {}
|
||||||
|
|
||||||
|
impl<T: DomObject> Hash for DomRoot<T> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.value.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Clone for DomRoot<T>
|
impl<T> Clone for DomRoot<T>
|
||||||
where
|
where
|
||||||
T: DomObject,
|
T: DomObject,
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// This interface is entirely internal to Servo, and should not be accessible to
|
||||||
|
// web pages.
|
||||||
|
|
||||||
|
[Pref="dom_testbinding_enabled", Exposed=(Window,Worker)]
|
||||||
|
interface TestBindingMaplikeWithInterface {
|
||||||
|
[Throws]
|
||||||
|
constructor();
|
||||||
|
|
||||||
|
maplike<DOMString, TestBinding>;
|
||||||
|
undefined setInternal(DOMString aKey, TestBinding aValue);
|
||||||
|
undefined clearInternal();
|
||||||
|
boolean deleteInternal(DOMString aKey);
|
||||||
|
boolean hasInternal(DOMString aKey);
|
||||||
|
[Throws]
|
||||||
|
TestBinding getInternal(DOMString aKey);
|
||||||
|
};
|
|
@ -6,7 +6,7 @@
|
||||||
// web pages.
|
// web pages.
|
||||||
|
|
||||||
[Pref="dom_testbinding_enabled", Exposed=(Window,Worker)]
|
[Pref="dom_testbinding_enabled", Exposed=(Window,Worker)]
|
||||||
interface TestBindingMaplike {
|
interface TestBindingMaplikeWithPrimitive {
|
||||||
[Throws]
|
[Throws]
|
||||||
constructor();
|
constructor();
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// This interface is entirely internal to Servo, and should not be accessible to
|
||||||
|
// web pages.
|
||||||
|
|
||||||
|
[Pref="dom_testbinding_enabled", Exposed=(Window,Worker)]
|
||||||
|
interface TestBindingSetlikeWithInterface {
|
||||||
|
[Throws]
|
||||||
|
constructor();
|
||||||
|
|
||||||
|
setlike<TestBinding>;
|
||||||
|
};
|
|
@ -6,7 +6,7 @@
|
||||||
// web pages.
|
// web pages.
|
||||||
|
|
||||||
[Pref="dom_testbinding_enabled", Exposed=(Window,Worker)]
|
[Pref="dom_testbinding_enabled", Exposed=(Window,Worker)]
|
||||||
interface TestBindingSetlike {
|
interface TestBindingSetlikeWithPrimitive {
|
||||||
[Throws]
|
[Throws]
|
||||||
constructor();
|
constructor();
|
||||||
|
|
|
@ -1,23 +1,29 @@
|
||||||
[like.any.html]
|
[like.any.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
prefs: [dom_testbinding_enabled:true]
|
prefs: [dom_testbinding_enabled:true]
|
||||||
[Test defaulting arguments on setlike to undefined]
|
[setlike<DOMString> - Default arguments for r/w methods is undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Simple map creation and functionality test]
|
[maplike<string, number> - 'get' with a bogus key should return undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Test defaulting arguments on maplike to undefined]
|
[maplike<string, TestBinding> - 'get' with a bogus key should return undefined]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[maplike<DOMString, number> - Default arguments for r/w methods is undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[like.any.worker.html]
|
[like.any.worker.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
prefs: [dom_testbinding_enabled:true]
|
prefs: [dom_testbinding_enabled:true]
|
||||||
[Test defaulting arguments on setlike to undefined]
|
[setlike<DOMString> - Default arguments for r/w methods is undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Simple map creation and functionality test]
|
[maplike<string, number> - 'get' with a bogus key should return undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Test defaulting arguments on maplike to undefined]
|
[maplike<string, TestBinding> - 'get' with a bogus key should return undefined]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[maplike<DOMString, number> - Default arguments for r/w methods is undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
2
tests/wpt/mozilla/meta/MANIFEST.json
vendored
2
tests/wpt/mozilla/meta/MANIFEST.json
vendored
|
@ -13538,7 +13538,7 @@
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"like.any.js": [
|
"like.any.js": [
|
||||||
"11e4d86325ce6216754a0e0b760c59beb812db85",
|
"30d8007fb5cbef2847e36fe9b4cb9e6535aaf1e0",
|
||||||
[
|
[
|
||||||
"mozilla/like.any.html",
|
"mozilla/like.any.html",
|
||||||
{
|
{
|
||||||
|
|
19
tests/wpt/mozilla/meta/mozilla/like.any.js.ini
vendored
19
tests/wpt/mozilla/meta/mozilla/like.any.js.ini
vendored
|
@ -1,23 +1,30 @@
|
||||||
[like.any.html]
|
[like.any.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
prefs: [dom_testbinding_enabled:true]
|
prefs: [dom_testbinding_enabled:true]
|
||||||
[Test defaulting arguments on setlike to undefined]
|
[setlike<DOMString> - Default arguments for r/w methods is undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Simple map creation and functionality test]
|
[maplike<string, number> - 'get' with a bogus key should return undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Test defaulting arguments on maplike to undefined]
|
[maplike<string, TestBinding> - 'get' with a bogus key should return undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[maplike<DOMString, number> - Default arguments for r/w methods is undefined]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
[like.any.worker.html]
|
[like.any.worker.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
prefs: [dom_testbinding_enabled:true]
|
prefs: [dom_testbinding_enabled:true]
|
||||||
[Test defaulting arguments on setlike to undefined]
|
[setlike<DOMString> - Default arguments for r/w methods is undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Simple map creation and functionality test]
|
[maplike<string, number> - 'get' with a bogus key should return undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Test defaulting arguments on maplike to undefined]
|
[maplike<string, TestBinding> - 'get' with a bogus key should return undefined]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[maplike<DOMString, number> - Default arguments for r/w methods is undefined]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
512
tests/wpt/mozilla/tests/mozilla/like.any.js
vendored
512
tests/wpt/mozilla/tests/mozilla/like.any.js
vendored
|
@ -59,250 +59,308 @@ var testExistence = function testExistence(prefix, obj, properties) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
test(function () {
|
let setLikeTests = [
|
||||||
var m = new TestBindingSetlike();
|
{
|
||||||
assert_true(ok(m), "SimpleSet: got a TestBindingSetlike object");
|
setConstructor: TestBindingSetlikeWithPrimitive,
|
||||||
testExistence("SimpleSet: ", m, setlike_rw_properties);
|
testValues: ["first", "second", "third", "fourth"],
|
||||||
assert_equals(m.size, 0, "SimpleSet: size should be zero");
|
memberType: "string"
|
||||||
assert_true(!m.has("test"), "SimpleSet: maplike has should return false");
|
},
|
||||||
m1 = m.add("test");
|
{
|
||||||
assert_equals(m, m1, "SimpleSet: return from set should be map object");
|
setConstructor: TestBindingSetlikeWithInterface,
|
||||||
assert_equals(m.size, 1, "SimpleSet: size should be 1");
|
testValues: [new TestBinding(), new TestBinding(), new TestBinding(), new TestBinding()],
|
||||||
assert_true(m.has("test"), "SimpleSet: maplike has should return true");
|
memberType: "TestBinding"
|
||||||
m.add("test2");
|
},
|
||||||
assert_equals(m.size, 2, "SimpleSet: size should be 2");
|
];
|
||||||
testSet = ["test", "test2"];
|
|
||||||
testIndex = 0;
|
for (const { setConstructor, testValues, memberType } of setLikeTests) {
|
||||||
m.forEach(function (v, k, o) {
|
test(function () {
|
||||||
"use strict";
|
var s = new setConstructor();
|
||||||
assert_equals(o, m, "SimpleSet: foreach obj is correct");
|
assert_true(ok(s), `got a ${setConstructor.name} object`);
|
||||||
assert_equals(k, testSet[testIndex], "SimpleSet: foreach set key: " + k + " = " + testSet[testIndex]);
|
testExistence(setConstructor.name, s, setlike_rw_properties);
|
||||||
testIndex += 1;
|
assert_equals(s.size, 0, "size of new set should be zero");
|
||||||
});
|
const testValue1 = testValues[0];
|
||||||
assert_equals(testIndex, 2, "SimpleSet: foreach ran correct number of times");
|
assert_true(!s.has(testValue1), "has() should return false for bogus value");
|
||||||
assert_true(m.has("test2"), "SimpleSet: maplike has should return true");
|
s1 = s.add(testValue1);
|
||||||
assert_equals(m.delete("test2"), true, "SimpleSet: maplike deletion should return true");
|
assert_equals(s, s1, "set.add() should be a chainable method");
|
||||||
assert_equals(m.size, 1, "SimpleSet: size should be 1");
|
assert_equals(s.size, 1, "size should be 1");
|
||||||
iterable = false;
|
assert_true(s.has(testValue1), "has() should return true for the first test value");
|
||||||
for (let e of m) {
|
const testValue2 = testValues[1];
|
||||||
iterable = true;
|
s.add(testValue2);
|
||||||
assert_equals(e, "test", "SimpleSet: iterable first array element should be key");
|
assert_equals(s.size, 2, "size should be 2");
|
||||||
}
|
testIndex = 0;
|
||||||
assert_equals(m[Symbol.iterator].length, 0, "SimpleSet: @@iterator symbol is correct length");
|
s.forEach(function (v, k, o) {
|
||||||
assert_equals(m[Symbol.iterator].name, "values", "SimpleSet: @@iterator symbol has correct name");
|
"use strict";
|
||||||
assert_equals(m[Symbol.iterator], m.values, 'SimpleSet: @@iterator is an alias for "values"');
|
assert_equals(o, s, "forEach obj is correct");
|
||||||
assert_true(ok(iterable), "SimpleSet: @@iterator symbol resolved correctly");
|
assert_equals(k, testValues[testIndex], "forEach set key: " + k + " = " + testValues[testIndex]);
|
||||||
for (let k of m.keys()) {
|
testIndex += 1;
|
||||||
assert_equals(k, "test", "SimpleSet: first keys element should be 'test'");
|
});
|
||||||
}
|
assert_equals(testIndex, 2, "forEach ran correct number of times");
|
||||||
for (let v of m.values()) {
|
assert_true(s.has(testValue2), "maplike has should return true for second key");
|
||||||
assert_equals(v, "test", "SimpleSet: first values elements should be 'test'");
|
assert_equals(s.delete(testValue2), true, "maplike deletion should return true");
|
||||||
}
|
assert_equals(s.size, 1, "size should be 1");
|
||||||
for (let e of m.entries()) {
|
iterable = false;
|
||||||
assert_equals(e[0], "test", "SimpleSet: Entries first array element should be 'test'");
|
for (let e of s) {
|
||||||
assert_equals(e[1], "test", "SimpleSet: Entries second array element should be 'test'");
|
iterable = true;
|
||||||
}
|
assert_equals(e, testValue1, "iterable first array element should be first test key");
|
||||||
m.clear();
|
}
|
||||||
assert_equals(m.size, 0, "SimpleSet: size should be 0 after clear");
|
assert_equals(s[Symbol.iterator].length, 0, "@@iterator symbol is correct length");
|
||||||
}, "Simple set creation and functionality");
|
assert_equals(s[Symbol.iterator].name, "values", "@@iterator symbol has correct name");
|
||||||
|
assert_equals(s[Symbol.iterator], s.values, '@@iterator is an alias for "values"');
|
||||||
|
assert_true(ok(iterable), " @@iterator symbol resolved correctly");
|
||||||
|
for (let k of s.keys()) {
|
||||||
|
assert_equals(k, testValue1, "first element of keys() should be the first test key");
|
||||||
|
}
|
||||||
|
for (let v of s.values()) {
|
||||||
|
assert_equals(v, testValue1, "first element of values() should be the first test value");
|
||||||
|
}
|
||||||
|
for (let e of s.entries()) {
|
||||||
|
assert_equals(e[0], testValue1, "first element of entries() should be the first test value");
|
||||||
|
assert_equals(e[1], testValue1, "second element of entries() should be the second test value");
|
||||||
|
}
|
||||||
|
s.clear();
|
||||||
|
assert_equals(s.size, 0, "size should be 0 after clear");
|
||||||
|
}, `setlike<${memberType}> - Basic set operations`);
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
// Test this override for forEach
|
||||||
|
s = new setConstructor();
|
||||||
|
s.add(testValues[0]);
|
||||||
|
s.forEach(function (v, k, o) {
|
||||||
|
"use strict";
|
||||||
|
assert_equals(o, s, "forEach obj is correct");
|
||||||
|
assert_equals(this, 5, "'this' value should be correct");
|
||||||
|
}, 5);
|
||||||
|
}, `setke<${memberType}> - Test 'this' override for 'forEach'`);
|
||||||
|
|
||||||
|
// some iterable test ported to *like interfaces
|
||||||
|
test(function () {
|
||||||
|
var s = new setConstructor();
|
||||||
|
var empty = true;
|
||||||
|
s.forEach(function () { empty = false; });
|
||||||
|
assert_true(empty);
|
||||||
|
}, `Empty setlike<${memberType}>`);
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var s = new setConstructor();
|
||||||
|
function is_iterator(o) {
|
||||||
|
return o[Symbol.iterator]() === o;
|
||||||
|
}
|
||||||
|
assert_true(is_iterator(s.keys()));
|
||||||
|
assert_true(is_iterator(s.values()));
|
||||||
|
assert_true(is_iterator(s.entries()));
|
||||||
|
}, `setlike<${memberType}> are iterators`);
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var s = new setConstructor();
|
||||||
|
s.add(testValues[0]);
|
||||||
|
s.add(testValues[1]);
|
||||||
|
s.add(testValues[2]);
|
||||||
|
assert_array_equals(collect(s.keys()), collect(s.values()));
|
||||||
|
assert_array_equals(collect(s.values()), testValues.slice(0, 3));
|
||||||
|
var i = 0;
|
||||||
|
for (entry of s.entries()) {
|
||||||
|
assert_array_equals(entry, [testValues[i], testValues[i]]);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s.add(testValues[3]);
|
||||||
|
assert_array_equals(collect(s.keys()), collect(s.values()));
|
||||||
|
assert_array_equals(collect(s.values()), testValues);
|
||||||
|
var i = 0;
|
||||||
|
for (entry of s.entries()) {
|
||||||
|
assert_array_equals(entry, [testValues[i], testValues[i]]);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}, `setlike<${memberType}> - Iterators iterate over values`);
|
||||||
|
}
|
||||||
|
|
||||||
test(function () {
|
test(function () {
|
||||||
var m = new TestBindingSetlike();
|
var m = new TestBindingSetlikeWithPrimitive();
|
||||||
m.add();
|
m.add();
|
||||||
assert_equals(m.size, 1, "SetArgsDefault: should have 1 entry");
|
assert_equals(m.size, 1, "set should have 1 entry");
|
||||||
m.forEach(function (v, k) {
|
m.forEach(function (v, k) {
|
||||||
"use strict";
|
"use strict";
|
||||||
assert_equals(typeof k, "string", "SetArgsDefault: key is a string");
|
assert_equals(typeof k, "string", "key must be a string");
|
||||||
assert_equals(k, "undefined", "SetArgsDefault: key is the string undefined");
|
assert_equals(k, "undefined", "key is the string undefined");
|
||||||
});
|
});
|
||||||
m.delete();
|
m.delete();
|
||||||
assert_equals(m.size, 0, "SetArgsDefault: should have 0 entries");
|
assert_equals(m.size, 0, "after deleting key, set should have 0 entries");
|
||||||
}, "Test defaulting arguments on setlike to undefined");
|
}, "setlike<DOMString> - Default arguments for r/w methods is undefined");
|
||||||
|
|
||||||
test(function () {
|
let mapLikeTests = [
|
||||||
// Simple map creation and functionality test
|
{
|
||||||
m = new TestBindingMaplike();
|
mapConstructor: TestBindingMaplikeWithPrimitive,
|
||||||
assert_true(ok(m), "SimpleMap: got a TestBindingMaplike object");
|
testEntries: [["first", 1], ["second", 2], ["third", 3], ["fourth", 4]],
|
||||||
testExistence("SimpleMap: ", m, maplike_rw_properties);
|
valueType: "number"
|
||||||
assert_equals(m.size, 0, "SimpleMap: size should be zero");
|
},
|
||||||
assert_true(!m.has("test"), "SimpleMap: maplike has should return false");
|
{
|
||||||
assert_equals(m.get("test"), undefined, "SimpleMap: maplike get should return undefined on bogus lookup");
|
mapConstructor: TestBindingMaplikeWithInterface,
|
||||||
var m1 = m.set("test", 1);
|
testEntries: [
|
||||||
assert_equals(m, m1, "SimpleMap: return from set should be map object");
|
["first", new TestBinding()],
|
||||||
assert_equals(m.size, 1, "SimpleMap: size should be 1");
|
["second", new TestBinding()],
|
||||||
assert_true(m.has("test"), "SimpleMap: maplike has should return true");
|
["third", new TestBinding()],
|
||||||
assert_equals(m.get("test"), 1, "SimpleMap: maplike get should return value entered");
|
["fourth", new TestBinding()],
|
||||||
m.set("test2", 2);
|
],
|
||||||
assert_equals(m.size, 2, "SimpleMap: size should be 2");
|
valueType: "TestBinding"
|
||||||
testSet = [["test", 1], ["test2", 2]];
|
},
|
||||||
testIndex = 0;
|
];
|
||||||
m.forEach(function (v, k, o) {
|
|
||||||
"use strict";
|
|
||||||
assert_equals(o, m, "SimpleMap: foreach obj is correct");
|
|
||||||
assert_equals(k, testSet[testIndex][0], "SimpleMap: foreach map key: " + k + " = " + testSet[testIndex][0]);
|
|
||||||
assert_equals(v, testSet[testIndex][1], "SimpleMap: foreach map value: " + v + " = " + testSet[testIndex][1]);
|
|
||||||
testIndex += 1;
|
|
||||||
});
|
|
||||||
assert_equals(testIndex, 2, "SimpleMap: foreach ran correct number of times");
|
|
||||||
assert_true(m.has("test2"), "SimpleMap: maplike has should return true");
|
|
||||||
assert_equals(m.get("test2"), 2, "SimpleMap: maplike get should return value entered");
|
|
||||||
assert_equals(m.delete("test2"), true, "SimpleMap: maplike deletion should return boolean");
|
|
||||||
assert_equals(m.size, 1, "SimpleMap: size should be 1");
|
|
||||||
var iterable = false;
|
|
||||||
for (let e of m) {
|
|
||||||
iterable = true;
|
|
||||||
assert_equals(e[0], "test", "SimpleMap: iterable first array element should be key");
|
|
||||||
assert_equals(e[1], 1, "SimpleMap: iterable second array element should be value");
|
|
||||||
}
|
|
||||||
assert_equals(m[Symbol.iterator].length, 0, "SimpleMap: @@iterator symbol is correct length");
|
|
||||||
assert_equals(m[Symbol.iterator].name, "entries", "SimpleMap: @@iterator symbol has correct name");
|
|
||||||
assert_equals(m[Symbol.iterator], m.entries, 'SimpleMap: @@iterator is an alias for "entries"');
|
|
||||||
assert_true(ok(iterable), "SimpleMap: @@iterator symbol resolved correctly");
|
|
||||||
for (let k of m.keys()) {
|
|
||||||
assert_equals(k, "test", "SimpleMap: first keys element should be 'test'");
|
|
||||||
}
|
|
||||||
for (let v of m.values()) {
|
|
||||||
assert_equals(v, 1, "SimpleMap: first values elements should be 1");
|
|
||||||
}
|
|
||||||
for (let e of m.entries()) {
|
|
||||||
assert_equals(e[0], "test", "SimpleMap: entries first array element should be 'test'");
|
|
||||||
assert_equals(e[1], 1, "SimpleMap: entries second array element should be 1");
|
|
||||||
}
|
|
||||||
m.clear();
|
|
||||||
assert_equals(m.size, 0, "SimpleMap: size should be 0 after clear");
|
|
||||||
}, "Simple map creation and functionality test");
|
|
||||||
|
|
||||||
test(function () {
|
for (const { mapConstructor, testEntries, valueType } of mapLikeTests) {
|
||||||
// Map convenience function test
|
test(function () {
|
||||||
m = new TestBindingMaplike();
|
m = new mapConstructor();
|
||||||
assert_true(ok(m), "MapConvenience: got a TestBindingMaplike object");
|
assert_true(ok(m), `got a ${mapConstructor.name} object`);
|
||||||
assert_equals(m.size, 0, "MapConvenience: size should be zero");
|
assert_equals(m.get("test"), undefined, "get(bogusKey) is undefined");
|
||||||
assert_true(!m.hasInternal("test"), "MapConvenience: maplike hasInternal should return false");
|
}, `maplike<string, ${valueType}> - 'get' with a bogus key should return undefined`);
|
||||||
// It's fine to let getInternal to return 0 if the key doesn't exist
|
|
||||||
// because this API can only be used internally in C++ and we'd throw
|
|
||||||
// an error if the key doesn't exist.
|
|
||||||
//SimpleTest.doesThrow(() => m.getInternal("test"), 0, "MapConvenience: maplike getInternal should throw if the key doesn't exist");
|
|
||||||
m.setInternal("test", 1);
|
|
||||||
assert_equals(m.size, 1, "MapConvenience: size should be 1");
|
|
||||||
assert_true(m.hasInternal("test"), "MapConvenience: maplike hasInternal should return true");
|
|
||||||
assert_equals(m.get("test"), 1, "MapConvenience: maplike get should return value entered");
|
|
||||||
assert_equals(m.getInternal("test"), 1, "MapConvenience: maplike getInternal should return value entered");
|
|
||||||
m.setInternal("test2", 2);
|
|
||||||
assert_equals(m.size, 2, "size should be 2");
|
|
||||||
assert_true(m.hasInternal("test2"), "MapConvenience: maplike hasInternal should return true");
|
|
||||||
assert_equals(m.get("test2"), 2, "MapConvenience: maplike get should return value entered");
|
|
||||||
assert_equals(m.getInternal("test2"), 2, "MapConvenience: maplike getInternal should return value entered");
|
|
||||||
assert_equals(m.deleteInternal("test2"), true, "MapConvenience: maplike deleteInternal should return true");
|
|
||||||
assert_equals(m.size, 1, "MapConvenience: size should be 1");
|
|
||||||
m.clearInternal();
|
|
||||||
assert_equals(m.size, 0, "MapConvenience: size should be 0 after clearInternal");
|
|
||||||
}, "Map convenience function test");
|
|
||||||
|
|
||||||
// JS implemented map creation convenience function test
|
test(function () {
|
||||||
test(function () {
|
// Simple map creation and functionality test
|
||||||
// Test this override for forEach
|
m = new mapConstructor();
|
||||||
m = new TestBindingMaplike();
|
assert_true(ok(m), `got a ${mapConstructor.name} object`);
|
||||||
m.set("test", 1);
|
testExistence(mapConstructor.name, m, maplike_rw_properties);
|
||||||
m.forEach(function (v, k, o) {
|
assert_equals(m.size, 0, "size of new map should be zero");
|
||||||
"use strict";
|
let [testKey1, testValue1] = testEntries[0];
|
||||||
assert_equals(o, m, "ForEachThisOverride: foreach obj is correct");
|
assert_true(!m.has(testKey1), "maplike has should return false for bogus key");
|
||||||
assert_equals(this, 5, "ForEachThisOverride: 'this' value should be correct");
|
var m1 = m.set(testKey1, testValue1);
|
||||||
}, 5);
|
assert_equals(m, m1, "map.set should be a chainable method");
|
||||||
}, "Test this override for forEach");
|
assert_equals(m.size, 1, "size should be 1");
|
||||||
|
assert_true(m.has(testKey1), "has() should return true for key already added");
|
||||||
|
assert_equals(m.get(testKey1), testValue1, "get(testKey1) should return the same value provided to set()");
|
||||||
|
let [testKey2, testValue2] = testEntries[1];
|
||||||
|
m.set(testKey2, testValue2);
|
||||||
|
assert_equals(m.size, 2, "size should be 2");
|
||||||
|
testSet = testEntries.slice(0, 2);
|
||||||
|
testIndex = 0;
|
||||||
|
m.forEach(function (v, k, o) {
|
||||||
|
"use strict";
|
||||||
|
assert_equals(o, m, "forEach obj is correct");
|
||||||
|
assert_equals(k, testSet[testIndex][0], "forEach map key: " + k + " = " + testSet[testIndex][0]);
|
||||||
|
assert_equals(v, testSet[testIndex][1], "forEach map value: " + v + " = " + testSet[testIndex][1]);
|
||||||
|
testIndex += 1;
|
||||||
|
});
|
||||||
|
assert_equals(testIndex, 2, "forEach ran correct number of times");
|
||||||
|
assert_true(m.has(testKey2), "has() should return true for second test key");
|
||||||
|
assert_equals(m.get(testKey2), testValue2, "get(testKey2) should return the same value provided to set()");
|
||||||
|
assert_equals(m.delete(testKey2), true, "maplike deletion should return boolean");
|
||||||
|
assert_equals(m.size, 1, "size should be 1");
|
||||||
|
var iterable = false;
|
||||||
|
for (let e of m) {
|
||||||
|
iterable = true;
|
||||||
|
assert_equals(e[0], testKey1, "iterable's first array element should be the first test key");
|
||||||
|
assert_equals(e[1], testValue1, "iterable' second array element should be the first test value");
|
||||||
|
}
|
||||||
|
assert_equals(m[Symbol.iterator].length, 0, "@@iterator symbol is correct length");
|
||||||
|
assert_equals(m[Symbol.iterator].name, "entries", "@@iterator symbol has correct name");
|
||||||
|
assert_equals(m[Symbol.iterator], m.entries, '@@iterator is an alias for "entries"');
|
||||||
|
assert_true(ok(iterable), "@@iterator symbol resolved correctly");
|
||||||
|
for (let k of m.keys()) {
|
||||||
|
assert_equals(k, testKey1, "first element of keys() should be the first test key");
|
||||||
|
}
|
||||||
|
for (let v of m.values()) {
|
||||||
|
assert_equals(v, testValue1, "first element of values() should be 1");
|
||||||
|
}
|
||||||
|
for (let e of m.entries()) {
|
||||||
|
assert_equals(e[0], testKey1, "first element of entries() should have the first test key");
|
||||||
|
assert_equals(e[1], testValue1, "first element of entries() should have the second test value");
|
||||||
|
}
|
||||||
|
m.clear();
|
||||||
|
assert_equals(m.size, 0, "size should be 0 after clear");
|
||||||
|
}, `maplike<string, ${valueType}> - Simple map creation and functionality test`);
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
// Map convenience function test
|
||||||
|
m = new mapConstructor();
|
||||||
|
assert_true(ok(m), `got a ${mapConstructor.name} object`);
|
||||||
|
assert_equals(m.size, 0, "size should be zero");
|
||||||
|
assert_true(!m.hasInternal("test"), "hasInternal() should return false for bogus key");
|
||||||
|
// It's fine to let getInternal to return 0 if the key doesn't exist
|
||||||
|
// because this API can only be used internally in C++ and we'd throw
|
||||||
|
// an error if the key doesn't exist.
|
||||||
|
//SimpleTest.doesThrow(() => m.getInternal("test"), 0, "MapConvenience: maplike getInternal should throw if the key doesn't exist");
|
||||||
|
let [testKey1, testValue1] = testEntries[0];
|
||||||
|
m.setInternal(testKey1, testValue1);
|
||||||
|
assert_equals(m.size, 1, "size should be 1 after adding first test key/value");
|
||||||
|
assert_true(m.hasInternal(testKey1), "hasInternal() should return true");
|
||||||
|
assert_equals(m.get(testKey1), testValue1, "get() should return the value set using setInternal()");
|
||||||
|
assert_equals(m.getInternal(testKey1), testValue1, "getInternal() should return the value set using setInternal()");
|
||||||
|
let [testKey2, testValue2] = testEntries[1];
|
||||||
|
m.setInternal(testKey2, testValue2);
|
||||||
|
assert_equals(m.size, 2, "size should be 2");
|
||||||
|
assert_true(m.hasInternal(testKey2), "hasInternal() should return true for newly added second test key");
|
||||||
|
assert_equals(m.get(testKey2), testValue2, "get(testKey2) should return the value set using setInternal");
|
||||||
|
assert_equals(m.getInternal(testKey2), testValue2, "getInternal(testKey2) should return the value set using setInternal()");
|
||||||
|
assert_equals(m.deleteInternal(testKey2), true, "deleteInternal should return true when deleting existing key");
|
||||||
|
assert_equals(m.size, 1, "size should be 1");
|
||||||
|
m.clearInternal();
|
||||||
|
assert_equals(m.size, 0, "size should be 0 after clearInternal");
|
||||||
|
}, `Convenience methods for maplike<string, ${valueType}>`);
|
||||||
|
|
||||||
|
// JS implemented map creation convenience function test
|
||||||
|
test(function () {
|
||||||
|
// Test this override for forEach
|
||||||
|
m = new mapConstructor();
|
||||||
|
m.set(testEntries[0][0], testEntries[1][1]);
|
||||||
|
m.forEach(function (v, k, o) {
|
||||||
|
"use strict";
|
||||||
|
assert_equals(o, m, "forEach obj is correct");
|
||||||
|
assert_equals(this, 5, "'this' value should be correct");
|
||||||
|
}, 5);
|
||||||
|
}, `maplike<string, ${valueType}> - Test 'this' override for 'forEach'`);
|
||||||
|
|
||||||
|
// some iterable test ported to *like interfaces
|
||||||
|
test(function () {
|
||||||
|
var t = new mapConstructor();
|
||||||
|
var empty = true;
|
||||||
|
t.forEach(function () { empty = false; });
|
||||||
|
assert_true(empty);
|
||||||
|
}, `maplike<string, ${valueType}> - Empty maplike`);
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var t = new mapConstructor();
|
||||||
|
function is_iterator(o) {
|
||||||
|
return o[Symbol.iterator]() === o;
|
||||||
|
}
|
||||||
|
assert_true(is_iterator(t.keys()));
|
||||||
|
assert_true(is_iterator(t.values()));
|
||||||
|
assert_true(is_iterator(t.entries()));
|
||||||
|
}, `maplike<string, ${valueType}> - Maplike are iterators`);
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var t = new mapConstructor();
|
||||||
|
t.set(testEntries[0][0], testEntries[0][1]);
|
||||||
|
t.set(testEntries[1][0], testEntries[1][1]);
|
||||||
|
t.set(testEntries[2][0], testEntries[2][1]);
|
||||||
|
assert_array_equals(collect(t.keys()), [testEntries[0][0], testEntries[1][0], testEntries[2][0]]);
|
||||||
|
assert_array_equals(collect(t.values()), [testEntries[0][1], testEntries[1][1], testEntries[2][1]]);
|
||||||
|
var expected = testEntries.slice(0, 3);
|
||||||
|
var i = 0;
|
||||||
|
for (entry of t.entries()) {
|
||||||
|
assert_array_equals(entry, expected[i++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
t.set(testEntries[3][0], testEntries[3][1]);
|
||||||
|
assert_array_equals(collect(t.keys()), testEntries.map(entry => entry[0]));
|
||||||
|
assert_array_equals(collect(t.values()), testEntries.map(entry => entry[1]));
|
||||||
|
var expected = testEntries.slice();
|
||||||
|
var i = 0;
|
||||||
|
for (entry of t.entries()) {
|
||||||
|
assert_array_equals(entry, expected[i++]);
|
||||||
|
}
|
||||||
|
}, `maplike<string, ${valueType}> - Maplike iteratable over key/value pairs`);
|
||||||
|
}
|
||||||
|
|
||||||
test(function () {
|
test(function () {
|
||||||
// Test defaulting arguments on maplike to undefined
|
// Test defaulting arguments on maplike to undefined
|
||||||
m = new TestBindingMaplike();
|
m = new TestBindingMaplikeWithPrimitive();
|
||||||
m.set();
|
m.set();
|
||||||
assert_equals(m.size, 1, "MapArgsDefault: should have 1 entry");
|
assert_equals(m.size, 1, "should have 1 entry");
|
||||||
m.forEach(function (v, k) {
|
m.forEach(function (v, k) {
|
||||||
"use strict";
|
"use strict";
|
||||||
assert_equals(typeof k, "string", "MapArgsDefault: key is a string");
|
assert_equals(typeof k, "string", "defaulted key must be a string");
|
||||||
assert_equals(k, "undefined", "MapArgsDefault: key is the string undefined");
|
assert_equals(k, "undefined", "defaulted key must be the string undefined");
|
||||||
assert_equals(v, 0, "MapArgsDefault: value is 0");
|
assert_equals(v, 0, "defaulted value must be 0");
|
||||||
});
|
});
|
||||||
assert_equals(m.get(), 0, "MapArgsDefault: no argument to get() returns correct value");
|
assert_equals(m.get(), 0, "no argument to get() returns correct value");
|
||||||
m.delete();
|
m.delete();
|
||||||
assert_equals(m.size, 0, "MapArgsDefault: should have 0 entries");
|
assert_equals(m.size, 0, "MapArgsDefault: should have 0 entries");
|
||||||
}, "Test defaulting arguments on maplike to undefined");
|
}, "maplike<DOMString, number> - Default arguments for r/w methods is undefined");
|
||||||
|
|
||||||
// some iterable test ported to *like interfaces
|
|
||||||
test(function () {
|
|
||||||
var t = new TestBindingSetlike();
|
|
||||||
var empty = true;
|
|
||||||
t.forEach(function () { empty = false; });
|
|
||||||
assert_true(empty);
|
|
||||||
}, "Empty setlike");
|
|
||||||
|
|
||||||
test(function () {
|
|
||||||
var t = new TestBindingSetlike();
|
|
||||||
function is_iterator(o) {
|
|
||||||
return o[Symbol.iterator]() === o;
|
|
||||||
}
|
|
||||||
assert_true(is_iterator(t.keys()));
|
|
||||||
assert_true(is_iterator(t.values()));
|
|
||||||
assert_true(is_iterator(t.entries()));
|
|
||||||
}, "Setlike are iterators");
|
|
||||||
|
|
||||||
test(function () {
|
|
||||||
var t = new TestBindingSetlike();
|
|
||||||
t.add("first");
|
|
||||||
t.add("second");
|
|
||||||
t.add("third");
|
|
||||||
assert_array_equals(collect(t.keys()), collect(t.values()));
|
|
||||||
assert_array_equals(collect(t.values()), ["first", "second", "third"]);
|
|
||||||
var expected = [["first", "first"], ["second", "second"], ["third", "third"]];
|
|
||||||
var i = 0;
|
|
||||||
for (entry of t.entries()) {
|
|
||||||
assert_array_equals(entry, expected[i++]);
|
|
||||||
}
|
|
||||||
|
|
||||||
t.add("fourth");
|
|
||||||
assert_array_equals(collect(t.keys()), collect(t.values()));
|
|
||||||
assert_array_equals(collect(t.values()), ["first", "second", "third", "fourth"]);
|
|
||||||
var expected = [["first", "first"], ["second", "second"], ["third", "third"], ["fourth", "fourth"]];
|
|
||||||
var i = 0;
|
|
||||||
for (entry of t.entries()) {
|
|
||||||
assert_array_equals(entry, expected[i++]);
|
|
||||||
}
|
|
||||||
}, "Iterators iterate over values");
|
|
||||||
|
|
||||||
test(function () {
|
|
||||||
var t = new TestBindingMaplike();
|
|
||||||
var empty = true;
|
|
||||||
t.forEach(function () { empty = false; });
|
|
||||||
assert_true(empty);
|
|
||||||
}, "Empty maplike");
|
|
||||||
|
|
||||||
test(function () {
|
|
||||||
var t = new TestBindingMaplike();
|
|
||||||
function is_iterator(o) {
|
|
||||||
return o[Symbol.iterator]() === o;
|
|
||||||
}
|
|
||||||
assert_true(is_iterator(t.keys()));
|
|
||||||
assert_true(is_iterator(t.values()));
|
|
||||||
assert_true(is_iterator(t.entries()));
|
|
||||||
}, "Maplike are iterators");
|
|
||||||
|
|
||||||
test(function () {
|
|
||||||
var t = new TestBindingMaplike();
|
|
||||||
t.set("first", 0);
|
|
||||||
t.set("second", 1);
|
|
||||||
t.set("third", 2);
|
|
||||||
assert_array_equals(collect(t.keys()), ["first", "second", "third"]);
|
|
||||||
assert_array_equals(collect(t.values()), [0, 1, 2]);
|
|
||||||
var expected = [["first", 0], ["second", 1], ["third", 2]];
|
|
||||||
var i = 0;
|
|
||||||
for (entry of t.entries()) {
|
|
||||||
assert_array_equals(entry, expected[i++]);
|
|
||||||
}
|
|
||||||
|
|
||||||
t.set("fourth", 3);
|
|
||||||
assert_array_equals(collect(t.keys()), ["first", "second", "third", "fourth"]);
|
|
||||||
assert_array_equals(collect(t.values()), [0, 1, 2, 3]);
|
|
||||||
var expected = [["first", 0], ["second", 1], ["third", 2], ["fourth", 3]];
|
|
||||||
var i = 0;
|
|
||||||
for (entry of t.entries()) {
|
|
||||||
assert_array_equals(entry, expected[i++]);
|
|
||||||
}
|
|
||||||
}, "Maplike iterate over key/value pairs");
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue