Support value iterators in WebIDL interfaces.

This commit is contained in:
Josh Matthews 2016-07-28 18:41:24 -04:00
parent 221bc84693
commit 34bb937aee
7 changed files with 161 additions and 0 deletions

View file

@ -1519,6 +1519,46 @@ class MethodDefiner(PropertyDefiner):
"length": 0, "length": 0,
"condition": "Condition::Satisfied"}) "condition": "Condition::Satisfied"})
# Generate the keys/values/entries aliases for value iterables.
maplikeOrSetlikeOrIterable = descriptor.interface.maplikeOrSetlikeOrIterable
if (not static and not unforgeable and
(maplikeOrSetlikeOrIterable and
maplikeOrSetlikeOrIterable.isIterable() and
maplikeOrSetlikeOrIterable.isValueIterator())):
# Add our keys/values/entries/forEach
self.regular.append({
"name": "keys",
"methodInfo": False,
"selfHostedName": "ArrayKeys",
"length": 0,
"condition": PropertyDefiner.getControllingCondition(m,
descriptor)
})
self.regular.append({
"name": "values",
"methodInfo": False,
"selfHostedName": "ArrayValues",
"length": 0,
"condition": PropertyDefiner.getControllingCondition(m,
descriptor)
})
self.regular.append({
"name": "entries",
"methodInfo": False,
"selfHostedName": "ArrayEntries",
"length": 0,
"condition": PropertyDefiner.getControllingCondition(m,
descriptor)
})
self.regular.append({
"name": "forEach",
"methodInfo": False,
"selfHostedName": "ArrayForEach",
"length": 0,
"condition": PropertyDefiner.getControllingCondition(m,
descriptor)
})
isUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("Unforgeable")) isUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("Unforgeable"))
if not static and unforgeable == isUnforgeableInterface: if not static and unforgeable == isUnforgeableInterface:
stringifier = descriptor.operations['Stringifier'] stringifier = descriptor.operations['Stringifier']

View file

@ -384,6 +384,7 @@ pub mod storageevent;
pub mod stylesheet; pub mod stylesheet;
pub mod stylesheetlist; pub mod stylesheetlist;
pub mod testbinding; pub mod testbinding;
pub mod testbindingiterable;
pub mod testbindingproxy; pub mod testbindingproxy;
pub mod text; pub mod text;
pub mod textdecoder; pub mod textdecoder;

View file

@ -0,0 +1,43 @@
/* 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/. */
// check-tidy: no specs after this line
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::TestBindingIterableBinding::{self, TestBindingIterableMethods};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
#[dom_struct]
pub struct TestBindingIterable {
reflector: Reflector,
vals: DOMRefCell<Vec<DOMString>>,
}
impl TestBindingIterable {
fn new(global: GlobalRef) -> Root<TestBindingIterable> {
reflect_dom_object(box TestBindingIterable {
reflector: Reflector::new(),
vals: DOMRefCell::new(vec![]),
}, global, TestBindingIterableBinding::Wrap)
}
pub fn Constructor(global: GlobalRef) -> Fallible<Root<TestBindingIterable>> {
Ok(TestBindingIterable::new(global))
}
}
impl TestBindingIterableMethods for TestBindingIterable {
fn Add(&self, v: DOMString) { self.vals.borrow_mut().push(v); }
fn Length(&self) -> u32 { self.vals.borrow().len() as u32 }
fn GetItem(&self, n: u32) -> DOMString { self.vals.borrow().get(n as usize).unwrap().clone() }
fn IndexedGetter(&self, n: u32, found: &mut bool) -> DOMString {
let s = self.GetItem(n);
*found = true;
s
}
}

View file

@ -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 http://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), Constructor]
interface TestBindingIterable {
void add(DOMString arg);
readonly attribute unsigned long length;
getter DOMString getItem(unsigned long index);
iterable<DOMString>;
};

View file

@ -6858,6 +6858,12 @@
"url": "/_mozilla/mozilla/interfaces.worker" "url": "/_mozilla/mozilla/interfaces.worker"
} }
], ],
"mozilla/iterable.html": [
{
"path": "mozilla/iterable.html",
"url": "/_mozilla/mozilla/iterable.html"
}
],
"mozilla/lenient_this.html": [ "mozilla/lenient_this.html": [
{ {
"path": "mozilla/lenient_this.html", "path": "mozilla/lenient_this.html",

View file

@ -0,0 +1,3 @@
[iterable.html]
type: testharness
prefs: [dom.testbinding.enabled:true]

View file

@ -0,0 +1,54 @@
<!doctype html>
<meta charset="utf-8">
<title>Value and pair iterable bindings</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function collect(iter) {
var collection = [];
for (element of iter) {
collection.push(element);
}
return collection;
}
test(function() {
var t = new TestBindingIterable();
var empty = true;
t.forEach(function() { empty = false; });
assert_true(empty);
}, "Empty value iterator");
test(function() {
var t = new TestBindingIterable();
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()));
}, "Iterable iterators are iterators");
test(function() {
var t = new TestBindingIterable();
t.add("first");
t.add("second");
t.add("third");
assert_array_equals(collect(t.keys()), [0, 1, 2]);
assert_array_equals(collect(t.values()), ["first", "second", "third"]);
var expected = [[0, "first"], [1, "second"], [2, "third"]];
var i = 0;
for (entry of t.entries()) {
assert_array_equals(entry, expected[i++]);
}
t.add("fourth");
assert_array_equals(collect(t.keys()), [0, 1, 2, 3]);
assert_array_equals(collect(t.values()), ["first", "second", "third", "fourth"]);
var expected = [[0, "first"], [1, "second"], [2, "third"], [3, "fourth"]];
var i = 0;
for (entry of t.entries()) {
assert_array_equals(entry, expected[i++]);
}
}, "Iterators iterate over values");
</script>