Update web-platform-tests to revision 7da6acfd668e66adae5ab4e2d389810d3b1460be

This commit is contained in:
James Graham 2015-10-05 17:15:15 +01:00
parent 50db64a20e
commit bae87d193d
307 changed files with 35826 additions and 209 deletions

View file

@ -13,8 +13,10 @@ scripts.
From an HTML or SVG document, start by importing both `testharness.js` and
`testharnessreport.js` scripts into the document:
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
```html
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
```
Refer to the [Web Workers](#web-workers) section for details and an example on
testing within a web worker.
@ -37,12 +39,16 @@ are complete", below.
To create a synchronous test use the test() function:
test(test_function, name, properties)
```js
test(test_function, name, properties)
```
`test_function` is a function that contains the code to test. For example a
trivial passing test would be:
test(function() {assert_true(true)}, "assert_true with true")
```js
test(function() {assert_true(true)}, "assert_true with true")
```
The function passed in is run in the `test()` call.
@ -59,7 +65,9 @@ applicable to many situations.
To create a test, one starts by getting a Test object using async_test:
async_test(name, properties)
```js
async_test(name, properties)
```
e.g.
var t = async_test("Simple async test")
@ -67,21 +75,27 @@ e.g.
Assertions can be added to the test by calling the step method of the test
object with a function containing the test assertions:
t.step(function() {assert_true(true)});
```js
t.step(function() {assert_true(true)});
```
When all the steps are complete, the done() method must be called:
t.done();
```js
t.done();
```
As a convenience, async_test can also takes a function as first argument.
This function is called with the test object as both its `this` object and
first argument. The above example can be rewritten as:
async_test(function(t) {
object.some_event = function() {
t.step(function (){assert_true(true); t.done();});
};
}, "Simple async test");
```js
async_test(function(t) {
object.some_event = function() {
t.step(function (){assert_true(true); t.done();});
};
}, "Simple async test");
```
which avoids cluttering the global scope with references to async
tests instances.
@ -92,12 +106,16 @@ In many cases it is convenient to run a step in response to an event or a
callback. A convenient method of doing this is through the step_func method
which returns a function that, when called runs a test step. For example
object.some_event = t.step_func(function(e) {assert_true(e.a)});
```js
object.some_event = t.step_func(function(e) {assert_true(e.a)});
```
For asynchronous callbacks that should never execute, `unreached_func` can
be used. For example:
object.some_event = t.unreached_func("some_event should not fire");
```js
object.some_event = t.unreached_func("some_event should not fire");
```
Keep in mind that other tests could start executing before an Asynchronous
Test is finished.
@ -106,7 +124,9 @@ Test is finished.
`promise_test` can be used to test APIs that are based on Promises:
promise_test(test_function, name, properties)
```js
promise_test(test_function, name, properties)
```
`test_function` is a function that receives a test as an argument and returns a
promise. The test completes when the returned promise resolves. The test fails
@ -114,16 +134,18 @@ if the returned promise rejects.
E.g.:
function foo() {
return Promise.resolve("foo");
}
```js
function foo() {
return Promise.resolve("foo");
}
promise_test(function() {
return foo()
.then(function(result) {
assert_equals(result, "foo", "foo should return 'foo'");
});
}, "Simple example");
promise_test(function() {
return foo()
.then(function(result) {
assert_equals(result, "foo", "foo should return 'foo'");
});
}, "Simple example");
```
In the example above, `foo()` returns a Promise that resolves with the string
"foo". The `test_function` passed into `promise_test` invokes `foo` and attaches
@ -137,7 +159,9 @@ previous Promise Test finishes.
`promise_rejects` can be used to test Promises that need to reject:
promise_rejects(test_object, code, promise)
```js
promise_rejects(test_object, code, promise)
```
The `code` argument is equivalent to the same argument to the `assert_throws`
function.
@ -145,13 +169,15 @@ function.
Here's an example where the `bar()` function returns a Promise that rejects
with a TypeError:
function bar() {
return Promise.reject(new TypeError());
}
```js
function bar() {
return Promise.reject(new TypeError());
}
promise_test(function(t) {
return promise_rejects(t, new TypeError(), bar);
}, "Another example");
promise_test(function(t) {
return promise_rejects(t, new TypeError(), bar);
}, "Another example");
```
`EventWatcher` is a constructor function that allows DOM events to be handled
using Promises, which can make it a lot easier to test a very specific series
@ -159,25 +185,27 @@ of events, including ensuring that unexpected events are not fired at any point.
Here's an example of how to use `EventWatcher`:
var t = async_test("Event order on animation start");
```js
var t = async_test("Event order on animation start");
var animation = watchedNode.getAnimations()[0];
var eventWatcher = new EventWatcher(watchedNode, ['animationstart',
'animationiteration',
'animationend']);
var animation = watchedNode.getAnimations()[0];
var eventWatcher = new EventWatcher(watchedNode, ['animationstart',
'animationiteration',
'animationend']);
eventWatcher.wait_for(t, 'animationstart').then(t.step_func(function() {
assertExpectedStateAtStartOfAnimation();
animation.currentTime = END_TIME; // skip to end
// We expect two animationiteration events then an animationend event on
// skipping to the end of the animation.
return eventWatcher.wait_for(['animationiteration',
'animationiteration',
'animationend']);
})).then(t.step_func(function() {
assertExpectedStateAtEndOfAnimation();
test.done();
}));
eventWatcher.wait_for(t, 'animationstart').then(t.step_func(function() {
assertExpectedStateAtStartOfAnimation();
animation.currentTime = END_TIME; // skip to end
// We expect two animationiteration events then an animationend event on
// skipping to the end of the animation.
return eventWatcher.wait_for(['animationiteration',
'animationiteration',
'animationend']);
})).then(t.step_func(function() {
assertExpectedStateAtEndOfAnimation();
test.done();
}));
```
`wait_for` either takes the name of a single event and returns a Promise that
will resolve after that event is fired at the watched node, or else it takes an
@ -203,25 +231,29 @@ must call the `done()` function to indicate that the test is complete. All
the `assert_*` functions are avaliable as normal, but are called without
the normal step function wrapper. For example:
<!doctype html>
<title>Example single-page test</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
assert_equals(document.body, document.getElementsByTagName("body")[0])
done()
</script>
```html
<!doctype html>
<title>Example single-page test</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
assert_equals(document.body, document.getElementsByTagName("body")[0])
done()
</script>
```
The test title for sinple page tests is always taken from `document.title`.
## Making assertions ##
Functions for making assertions start `assert_`. The full list of
asserts avaliable is documented in the [asserts](#asserts) section
below.. The general signature is
asserts avaliable is documented in the [asserts](#list-of-assertions) section
below. The general signature is
assert_something(actual, expected, description)
```js
assert_something(actual, expected, description)
```
although not all assertions precisely match this pattern e.g. `assert_true`
only takes `actual` and `description` as arguments.
@ -243,11 +275,13 @@ callbacks to the test. Such callbacks are registered using the `add_cleanup`
function on the test object. All registered callbacks will be run as soon as
the test result is known. For example
test(function() {
window.some_global = "example";
this.add_cleanup(function() {delete window.some_global});
assert_true(false);
});
```js
test(function() {
window.some_global = "example";
this.add_cleanup(function() {delete window.some_global});
assert_true(false);
});
```
## Timeouts in Tests ##
@ -263,9 +297,11 @@ that only passes if some event is *not* fired). In this case it is
*not* permitted to use the standard `setTimeout` function. Instead one
must use the `step_timeout` function:
var t = async_test("Some test that does something after a timeout");
```js
var t = async_test("Some test that does something after a timeout");
t.step_timeout(function() {assert_true(true); this.done()}, 2000);
t.step_timeout(function() {assert_true(true); this.done()}, 2000);
```
The difference between `setTimeout` and `step_timeout` is that the
latter takes account of the timeout multiplier when computing the
@ -287,7 +323,9 @@ when the test is run on hardware with different performance
characteristics to a common desktop computer. In order to opt-in
to the longer test timeout, the test must specify a meta element:
<meta name="timeout" content="long">
```html
<meta name="timeout" content="long">
```
Occasionally tests may have a race between the harness timing out and
a particular test failing; typically when the test waits for some event
@ -302,7 +340,9 @@ Sometimes tests require non-trivial setup that may fail. For this purpose
there is a `setup()` function, that may be called with one or two arguments.
The two argument version is:
setup(func, properties)
```js
setup(func, properties)
```
The one argument versions may omit either argument.
func is a function to be run synchronously. `setup()` becomes a no-op once
@ -352,19 +392,25 @@ There are scenarios in which is is desirable to create a large number of
used. To make this easier, the `generate_tests` function allows a single
function to be called with each set of parameters in a list:
generate_tests(test_function, parameter_lists, properties)
```js
generate_tests(test_function, parameter_lists, properties)
```
For example:
generate_tests(assert_equals, [
["Sum one and one", 1+1, 2],
["Sum one and zero", 1+0, 1]
])
```js
generate_tests(assert_equals, [
["Sum one and one", 1+1, 2],
["Sum one and zero", 1+0, 1]
])
```
Is equivalent to:
test(function() {assert_equals(1+1, 2)}, "Sum one and one")
test(function() {assert_equals(1+0, 1)}, "Sum one and zero")
```js
test(function() {assert_equals(1+1, 2)}, "Sum one and one")
test(function() {assert_equals(1+0, 1)}, "Sum one and zero")
```
Note that the first item in each parameter list corresponds to the name of
the test.
@ -477,28 +523,32 @@ Here's an example that uses a dedicated worker.
`worker.js`:
importScripts("/resources/testharness.js");
```js
importScripts("/resources/testharness.js");
test(function(t) {
assert_true(true, "true is true");
}, "Simple test");
test(function(t) {
assert_true(true, "true is true");
}, "Simple test");
// done() is needed because the testharness is running as if explicit_done
// was specified.
done();
// done() is needed because the testharness is running as if explicit_done
// was specified.
done();
```
`test.html`:
<!DOCTYPE html>
<title>Simple test</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
```html
<!DOCTYPE html>
<title>Simple test</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
fetch_tests_from_worker(new Worker("worker.js"));
fetch_tests_from_worker(new Worker("worker.js"));
</script>
</script>
```
The argument to the `fetch_tests_from_worker` function can be a
[`Worker`](https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-worker-interface),

View file

@ -3,36 +3,42 @@
`idlharness.js` automatically generates browser tests for WebIDL interfaces, using
the testharness.js framework. To use, first include the following:
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/WebIDLParser.js></script>
<script src=/resources/idlharness.js></script>
```html
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/WebIDLParser.js></script>
<script src=/resources/idlharness.js></script>
```
Then you'll need some type of IDLs. Here's some script that can be run on a
spec written in HTML, which will grab all the elements with `class="idl"`,
concatenate them, and replace the body so you can copy-paste:
var s = "";
[].forEach.call(document.getElementsByClassName("idl"), function(idl) {
//https://www.w3.org/Bugs/Public/show_bug.cgi?id=14914
if (!idl.classList.contains("extract"))
{
s += idl.textContent + "\n\n";
}
});
document.body.innerHTML = '<pre></pre>';
document.body.firstChild.textContent = s;
```js
var s = "";
[].forEach.call(document.getElementsByClassName("idl"), function(idl) {
//https://www.w3.org/Bugs/Public/show_bug.cgi?id=14914
if (!idl.classList.contains("extract"))
{
s += idl.textContent + "\n\n";
}
});
document.body.innerHTML = '<pre></pre>';
document.body.firstChild.textContent = s;
```
Once you have that, put it in your script somehow. The easiest way is to
embed it literally in an HTML file with `<script type=text/plain>` or similar,
so that you don't have to do any escaping. Another possibility is to put it
in a separate .idl file that's fetched via XHR or similar. Sample usage:
var idl_array = new IdlArray();
idl_array.add_untested_idls("interface Node { readonly attribute DOMString nodeName; };");
idl_array.add_idls("interface Document : Node { readonly attribute DOMString URL; };");
idl_array.add_objects({Document: ["document"]});
idl_array.test();
```js
var idl_array = new IdlArray();
idl_array.add_untested_idls("interface Node { readonly attribute DOMString nodeName; };");
idl_array.add_idls("interface Document : Node { readonly attribute DOMString URL; };");
idl_array.add_objects({Document: ["document"]});
idl_array.test();
```
This tests that `window.Document` exists and meets all the requirements of
WebIDL. It also tests that window.document (the result of evaluating the
@ -96,12 +102,16 @@ and outside callers should not use it.
interfaces every single time. For instance, HTML defines many interfaces
that all inherit from `HTMLElement`, so the HTML test suite has something
like
`.add_objects({
HTMLHtmlElement: ['document.documentElement'],
HTMLHeadElement: ['document.head'],
HTMLBodyElement: ['document.body'],
...
})`
```js
.add_objects({
HTMLHtmlElement: ['document.documentElement'],
HTMLHeadElement: ['document.head'],
HTMLBodyElement: ['document.body'],
...
})
```
and so on for dozens of element types. This would mean that it would
retest that each and every one of those elements implements `HTMLElement`,
`Element`, and `Node`, which would be thousands of basically redundant tests.

View file

@ -1286,15 +1286,10 @@ IdlInterface.prototype.test_object = function(desc)
exception = e;
}
// TODO: WebIDLParser doesn't currently support named legacycallers, so I'm
// not sure what those would look like in the AST
var expected_typeof = this.members.some(function(member)
{
return member.legacycaller
|| ("idlType" in member && member.idlType.legacycaller)
|| ("idlType" in member && typeof member.idlType == "object"
&& "idlType" in member.idlType && member.idlType.idlType == "legacycaller");
}) ? "function" : "object";
var expected_typeof =
this.members.some(function(member) { return member.legacycaller; })
? "function"
: "object";
this.test_primary_interface_of(desc, obj, exception, expected_typeof);
var current_interface = this;

View file

@ -1106,7 +1106,7 @@ policies and contribution forms [3].
function _assert_inherits(name) {
return function (object, property_name, description)
{
assert(typeof object === "object",
assert(typeof object === "object" || typeof object === "function",
name, description,
"provided value is not an object");

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Robin Berjon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -61,6 +61,22 @@ In the browser:
var tree = WebIDL2.parse("string of WebIDL");
</script>
Advanced Parsing
----------------
`parse()` can optionally accept a second parameter, an options object, which can be used to
modify parsing behavior.
The following options are recognized:
```javascript
{
allowNestedTypedefs: false #
}
```
And their meanings are as follows:
* `allowNestedTypedefs`: Boolean indicating whether the parser should accept `typedef`s as valid members of `interface`s. This is non-standard syntax and therefore the default is `false`.
Errors
------
When there is a syntax error in the WebIDL, it throws an exception object with the following
@ -223,6 +239,7 @@ A dictionary looks like this:
{
"type": "field",
"name": "fillPattern",
"required": false,
"idlType": {
"sequence": false,
"generic": null,
@ -255,6 +272,7 @@ All the members are fields as follows:
* `type`: Always "field".
* `name`: The name of the field.
* `required`: Boolean indicating whether this is a [required](https://heycam.github.io/webidl/#required-dictionary-member) field.
* `idlType`: An [IDL Type](#idl-type) describing what field's type.
* `extAttrs`: A list of [extended attributes](#extended-attributes).
* `default`: A [default value](#default-and-const-values), absent if there is none.
@ -658,9 +676,8 @@ The fields are as follows:
whereas the lack thereof will yield a `null`. If there is an `rhs` field then
they are the right-hand side's arguments, otherwise they apply to the extended
attribute directly.
* `rhs`: If there is a right-hand side, this will capture its `type` (always
"identifier" in practice, though it may be extended in the future) and its
`value`.
* `rhs`: If there is a right-hand side, this will capture its `type` (which can be
"identifier" or "identifier-list") and its `value`.
* `typePair`: If the extended attribute is a `MapClass` this will capture the
map's key type and value type respectively.
@ -669,16 +686,34 @@ The fields are as follows:
Dictionary fields and operation arguments can take default values, and constants take
values, all of which have the following fields:
* `type`: One of string, number, boolean, null, Infinity, or NaN.
* `type`: One of string, number, boolean, null, Infinity, NaN, or sequence.
For string, number, and boolean:
For string, number, boolean, and sequence:
* `value`: The value of the given type.
* `value`: The value of the given type. For sequence, the only possible value is `[]`.
For Infinity:
* `negative`: Boolean indicating whether this is negative Infinity or not.
### `iterable<>`, `legacyiterable<>`, `maplike<>`, `setlike<>` declarations
These appear as members of interfaces that look like this:
{
"type": "maplike", // or "legacyiterable" / "iterable" / "setlike"
"idlType": /* One or two types */,
"readonly": false, // only for maplike and setlike
"extAttrs": []
}
The fields are as follows:
* `type`: Always one of "iterable", "legacyiterable", "maplike" or "setlike".
* `idlType`: An [IDL Type](#idl-type) (or an array of two types) representing the declared type arguments.
* `readonly`: Whether the maplike or setlike is declared as read only.
* `extAttrs`: A list of [extended attributes](#extended-attributes).
Testing
=======

View file

@ -214,8 +214,7 @@
ret.idlType = type() || error("Error parsing generic type " + value);
all_ws();
if (!consume(OTHER, ">")) error("Unterminated generic type " + value);
all_ws();
if (consume(OTHER, "?")) ret.nullable = true;
type_suffix(ret);
return ret;
}
else {
@ -331,8 +330,25 @@
all_ws();
var eq = consume(OTHER, "=");
if (eq) {
var rhs;
all_ws();
ret.rhs = consume(ID);
if (rhs = consume(ID)) {
ret.rhs = rhs
}
else if (consume(OTHER, "(")) {
// [Exposed=(Window,Worker)]
rhs = [];
var id = consume(ID);
if (id) {
rhs = [id.value];
}
identifiers(rhs);
consume(OTHER, ")") || error("Unexpected token in extended attribute argument list or type pair");
ret.rhs = {
type: "identifier-list",
value: rhs
};
}
if (!ret.rhs) return error("No right hand side to extended attribute assignment");
}
all_ws();
@ -380,6 +396,10 @@
if (def) {
return def;
}
else if (consume(OTHER, "[")) {
if (!consume(OTHER, "]")) error("Default sequence value must be empty");
return { type: "sequence", value: [] };
}
else {
var str = consume(STR) || error("No value for default");
str.value = str.value.replace(/^"/, "").replace(/"$/, "");
@ -562,7 +582,7 @@
return ret;
}
else if (consume(ID, "stringifier")) {
ret.stringifier = true;
ret.stringifier = true;-
all_ws();
if (consume(OTHER, ";")) return ret;
ret.idlType = return_type();
@ -667,6 +687,69 @@
}
return ret;
};
var iterable_type = function() {
if (consume(ID, "iterable")) return "iterable";
else if (consume(ID, "legacyiterable")) return "legacyiterable";
else if (consume(ID, "maplike")) return "maplike";
else if (consume(ID, "setlike")) return "setlike";
else return;
}
var readonly_iterable_type = function() {
if (consume(ID, "maplike")) return "maplike";
else if (consume(ID, "setlike")) return "setlike";
else return;
}
var iterable = function (store) {
all_ws(store, "pea");
var grabbed = [],
ret = {type: null, idlType: null, readonly: false};
if (consume(ID, "readonly")) {
ret.readonly = true;
grabbed.push(last_token);
var w = all_ws();
if (w) grabbed.push(w);
}
var consumeItType = ret.readonly ? readonly_iterable_type : iterable_type;
var ittype = consumeItType();
if (!ittype) {
tokens = grabbed.concat(tokens);
return;
}
var secondTypeRequired = ittype === "maplike";
var secondTypeAllowed = secondTypeRequired || ittype === "iterable";
ret.type = ittype;
if (ret.type !== 'maplike' && ret.type !== 'setlike')
delete ret.readonly;
all_ws();
if (consume(OTHER, "<")) {
ret.idlType = type() || error("Error parsing " + ittype + " declaration");
all_ws();
if (secondTypeAllowed) {
var type2 = null;
if (consume(OTHER, ",")) {
all_ws();
type2 = type();
all_ws();
}
if (type2)
ret.idlType = [ret.idlType, type2];
else if (secondTypeRequired)
error("Missing second type argument in " + ittype + " declaration");
}
if (!consume(OTHER, ">")) error("Unterminated " + ittype + " declaration");
all_ws();
if (!consume(OTHER, ";")) error("Missing semicolon after " + ittype + " declaration");
}
else
error("Error parsing " + ittype + " declaration");
return ret;
}
var interface_ = function (isPartial, store) {
all_ws(isPartial ? null : store, "pea");
@ -698,7 +781,9 @@
ret.members.push(cnt);
continue;
}
var mem = serialiser(store ? mems : null) ||
var mem = (opt.allowNestedTypedefs && typedef(store ? mems : null)) ||
iterable(store ? mems : null) ||
serialiser(store ? mems : null) ||
attribute(store ? mems : null) ||
operation(store ? mems : null) ||
error("Unknown member");
@ -741,15 +826,19 @@
}
var ea = extended_attrs(store ? mems : null);
all_ws(store ? mems : null, "pea");
var required = consume(ID, "required");
var typ = type() || error("No type for dictionary member");
all_ws();
var name = consume(ID) || error("No name for dictionary member");
var dflt = default_();
if (required && dflt) error("Required member must not have a default");
ret.members.push({
type: "field"
, name: name.value
, required: !!required
, idlType: typ
, extAttrs: ea
, "default": default_()
, "default": dflt
});
all_ws();
consume(OTHER, ";") || error("Unterminated dictionary member");
@ -818,7 +907,6 @@
all_ws(store ? vals : null);
if (consume(OTHER, "}")) {
all_ws();
if (saw_comma) error("Trailing comma in enum");
consume(OTHER, ";") || error("No semicolon after enum");
return ret;
}

View file

@ -1,22 +1,21 @@
{
"name": "webidl2"
, "description": "A WebIDL Parser"
, "version": "2.0.4"
, "author": "Robin Berjon <robin@berjon.com>"
, "license": "MIT"
, "dependencies": {
}
, "devDependencies": {
"mocha": "1.7.4"
, "expect.js": "0.2.0"
, "underscore": "1.4.3"
, "jsondiffpatch": "0.0.5"
, "benchmark": "*"
, "microtime": "*"
}
, "scripts": {
"test": "mocha"
}
, "repository": "git://github.com/darobin/webidl2.js"
, "main": "index"
"name": "webidl2",
"description": "A WebIDL Parser",
"version": "2.0.11",
"author": "Robin Berjon <robin@berjon.com>",
"license": "MIT",
"dependencies": {},
"devDependencies": {
"mocha": "2.2.5",
"expect.js": "0.3.1",
"underscore": "1.8.3",
"jsondiffpatch": "0.1.31",
"benchmark": "*",
"microtime": "1.4.2"
},
"scripts": {
"test": "mocha"
},
"repository": "git://github.com/darobin/webidl2.js",
"main": "index"
}

View file

@ -0,0 +1,5 @@
// https://heycam.github.io/webidl/#required-dictionary-member
// "A required dictionary member must not have a default value."
dictionary Dict {
required long member = 0;
};

View file

@ -0,0 +1,3 @@
interface MapLikeOneType {
maplike<long>;
}

View file

@ -0,0 +1,3 @@
interface ReadonlyIterable {
readonly iterable<long>;
}

View file

@ -0,0 +1,3 @@
interface SetLikeTwoTypes {
setlike<long, long>;
}

View file

@ -0,0 +1,22 @@
interface Point {
attribute float x;
attribute float y;
};
interface Rect {
attribute Point topleft;
attribute Point bottomright;
};
interface Widget {
typedef sequence<Point> PointSequence;
readonly attribute Rect bounds;
boolean pointWithinBounds(Point p);
boolean allPointsWithinBounds(PointSequence ps);
};
typedef [Clamp] octet value;

View file

@ -0,0 +1,4 @@
{
"message": "Required member must not have a default"
, "line": 4
}

View file

@ -0,0 +1,4 @@
{
"message": "Missing second type argument in maplike declaration",
"line": 2
}

View file

@ -0,0 +1,4 @@
{
"message": "Invalid operation",
"line": 2
}

View file

@ -0,0 +1,4 @@
{
"message": "Unterminated setlike declaration",
"line": 2
}

View file

@ -0,0 +1,4 @@
{
"message": "Invalid operation"
, "line": 14
}

View file

@ -17,11 +17,16 @@ describe("Parses all of the IDLs to produce the correct ASTs", function () {
for (var i = 0, n = idls.length; i < n; i++) {
var idl = idls[i], json = jsons[i];
var func = (function (idl, json) {
return function () {
try {
var optFile = pth.join(__dirname, "syntax/opt", pth.basename(json));
var opt = undefined;
if (fs.existsSync(optFile))
opt = JSON.parse(fs.readFileSync(optFile, "utf8"));
var diff = jdp.diff(JSON.parse(fs.readFileSync(json, "utf8")),
wp.parse(fs.readFileSync(idl, "utf8")));
wp.parse(fs.readFileSync(idl, "utf8"), opt));
if (diff && debug) console.log(JSON.stringify(diff, null, 4));
expect(diff).to.be(undefined);
}

View file

@ -2,4 +2,6 @@ callback AsyncOperationCallback = void (DOMString status);
callback interface EventHandler {
void eventOccurred(DOMString details);
};
};
callback SortCallback = boolean (any a, any b);

View file

@ -3,6 +3,10 @@ dictionary PaintOptions {
DOMString? fillPattern = "black";
DOMString? strokePattern = null;
Point position;
// https://heycam.github.io/webidl/#dfn-optional-argument-default-value allows sequences to default to "[]".
sequence<long> seq = [];
// https://heycam.github.io/webidl/#required-dictionary-member
required long reqSeq;
};
partial dictionary A {

View file

@ -5,4 +5,6 @@ interface Meal {
attribute float size; // in grams
void initialize(MealType type, float size);
};
};
enum AltMealType { "rice", "noodles", "other", };

View file

@ -0,0 +1,6 @@
// Extracted from http://www.w3.org/TR/2015/WD-service-workers-20150205/
[Global=(Worker,ServiceWorker), Exposed=ServiceWorker]
interface ServiceWorkerGlobalScope : WorkerGlobalScope {
};

View file

@ -1,5 +1,6 @@
interface Foo {
Promise<ResponsePromise<sequence<DOMString?>>> bar();
readonly attribute Promise<DOMString>[] baz;
};
// Extracted from https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ on 2014-05-08
@ -14,4 +15,3 @@ interface ServiceWorkerClients {
interface FetchEvent : Event {
ResponsePromise<any> default();
};

View file

@ -0,0 +1,7 @@
interface IterableOne {
iterable<long>;
};
interface IterableTwo {
iterable<short, double?>;
};

View file

@ -0,0 +1,3 @@
interface LegacyIterable {
legacyiterable<long>;
};

View file

@ -0,0 +1,7 @@
interface MapLike {
maplike<long, float>;
};
interface ReadOnlyMapLike {
readonly maplike<long, float>;
};

View file

@ -0,0 +1,7 @@
interface SetLike {
setlike<long>;
};
interface ReadOnlySetLike {
readonly setlike<long>;
};

View file

@ -0,0 +1,22 @@
interface Point {
attribute float x;
attribute float y;
};
interface Rect {
attribute Point topleft;
attribute Point bottomright;
};
interface Widget {
typedef sequence<Point> PointSequence;
readonly attribute Rect bounds;
boolean pointWithinBounds(Point p);
boolean allPointsWithinBounds(PointSequence ps);
};
typedef [Clamp] octet value;

View file

@ -72,5 +72,48 @@
],
"inheritance": null,
"extAttrs": []
},
{
"type": "callback",
"name": "SortCallback",
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "boolean"
},
"arguments": [
{
"optional": false,
"variadic": false,
"extAttrs": [],
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "any"
},
"name": "a"
},
{
"optional": false,
"variadic": false,
"extAttrs": [],
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "any"
},
"name": "b"
}
],
"extAttrs": []
}
]

View file

@ -7,6 +7,7 @@
{
"type": "field",
"name": "fillPattern",
"required": false,
"idlType": {
"sequence": false,
"generic": null,
@ -24,6 +25,7 @@
{
"type": "field",
"name": "strokePattern",
"required": false,
"idlType": {
"sequence": false,
"generic": null,
@ -40,6 +42,7 @@
{
"type": "field",
"name": "position",
"required": false,
"idlType": {
"sequence": false,
"generic": null,
@ -62,6 +65,7 @@
{
"type": "field",
"name": "hydrometry",
"required": false,
"idlType": {
"sequence": false,
"generic": null,

View file

@ -7,6 +7,7 @@
{
"type": "field",
"name": "fillPattern",
"required": false,
"idlType": {
"sequence": false,
"generic": null,
@ -24,6 +25,7 @@
{
"type": "field",
"name": "strokePattern",
"required": false,
"idlType": {
"sequence": false,
"generic": null,
@ -40,6 +42,7 @@
{
"type": "field",
"name": "position",
"required": false,
"idlType": {
"sequence": false,
"generic": null,
@ -49,6 +52,45 @@
"idlType": "Point"
},
"extAttrs": []
},
{
"type": "field",
"name": "seq",
"required": false,
"idlType": {
"sequence": true,
"generic": "sequence",
"nullable": false,
"array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "long"
}
},
"extAttrs": [],
"default": {
"type": "sequence",
"value": []
}
},
{
"type": "field",
"name": "reqSeq",
"required": true,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "long"
},
"extAttrs": []
}
],
"inheritance": null,
@ -62,6 +104,7 @@
{
"type": "field",
"name": "h",
"required": false,
"idlType": {
"sequence": false,
"generic": null,
@ -75,6 +118,7 @@
{
"type": "field",
"name": "d",
"required": false,
"idlType": {
"sequence": false,
"generic": null,

View file

@ -101,5 +101,15 @@
],
"inheritance": null,
"extAttrs": []
},
{
"type": "enum",
"name": "AltMealType",
"values": [
"rice",
"noodles",
"other"
],
"extAttrs": []
}
]

View file

@ -0,0 +1,30 @@
[
{
"type": "interface",
"name": "ServiceWorkerGlobalScope",
"partial": false,
"members": [],
"inheritance": "WorkerGlobalScope",
"extAttrs": [
{
"name": "Global",
"arguments": null,
"rhs": {
"type": "identifier-list",
"value": [
"Worker",
"ServiceWorker"
]
}
},
{
"name": "Exposed",
"arguments": null,
"rhs": {
"type": "identifier",
"value": "ServiceWorker"
}
}
]
}
]

View file

@ -45,6 +45,31 @@
"name": "bar",
"arguments": [],
"extAttrs": []
},
{
"type": "attribute",
"static": false,
"stringifier": false,
"inherit": false,
"readonly": true,
"idlType": {
"sequence": false,
"generic": "Promise",
"nullable": false,
"array": 1,
"nullableArray": [false],
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "DOMString"
}
},
"name": "baz",
"extAttrs": []
}
],
"inheritance": null,

View file

@ -0,0 +1,55 @@
[
{
"type": "interface",
"name": "IterableOne",
"partial": false,
"members": [
{
"type": "iterable",
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "long"
},
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
},
{
"type": "interface",
"name": "IterableTwo",
"partial": false,
"members": [
{
"type": "iterable",
"idlType": [
{
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "short"
},
{
"sequence": false,
"generic": null,
"nullable": true,
"array": false,
"union": false,
"idlType": "double"
}
],
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
}
]

View file

@ -0,0 +1,24 @@
[
{
"type": "interface",
"name": "LegacyIterable",
"partial": false,
"members": [
{
"type": "legacyiterable",
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "long"
},
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
}
]

View file

@ -0,0 +1,67 @@
[
{
"type": "interface",
"name": "MapLike",
"partial": false,
"members": [
{
"type": "maplike",
"idlType": [
{
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "long"
},
{
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "float"
}
],
"readonly": false,
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
},
{
"type": "interface",
"name": "ReadOnlyMapLike",
"partial": false,
"members": [
{
"type": "maplike",
"idlType": [
{
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "long"
},
{
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "float"
}
],
"readonly": true,
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
}
]

View file

@ -0,0 +1,47 @@
[
{
"type": "interface",
"name": "SetLike",
"partial": false,
"members": [
{
"type": "setlike",
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "long"
},
"readonly": false,
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
},
{
"type": "interface",
"name": "ReadOnlySetLike",
"partial": false,
"members": [
{
"type": "setlike",
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "long"
},
"readonly": true,
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
}
]

View file

@ -0,0 +1,226 @@
[
{
"type": "interface",
"name": "Point",
"partial": false,
"members": [
{
"type": "attribute",
"static": false,
"stringifier": false,
"inherit": false,
"readonly": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "float"
},
"name": "x",
"extAttrs": []
},
{
"type": "attribute",
"static": false,
"stringifier": false,
"inherit": false,
"readonly": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "float"
},
"name": "y",
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
},
{
"type": "interface",
"name": "Rect",
"partial": false,
"members": [
{
"type": "attribute",
"static": false,
"stringifier": false,
"inherit": false,
"readonly": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "Point"
},
"name": "topleft",
"extAttrs": []
},
{
"type": "attribute",
"static": false,
"stringifier": false,
"inherit": false,
"readonly": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "Point"
},
"name": "bottomright",
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
},
{
"type": "interface",
"name": "Widget",
"partial": false,
"members": [
{
"type": "typedef",
"typeExtAttrs": [],
"idlType": {
"sequence": true,
"generic": "sequence",
"nullable": false,
"array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "Point"
}
},
"name": "PointSequence",
"extAttrs": []
},
{
"type": "attribute",
"static": false,
"stringifier": false,
"inherit": false,
"readonly": true,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "Rect"
},
"name": "bounds",
"extAttrs": []
},
{
"type": "operation",
"getter": false,
"setter": false,
"creator": false,
"deleter": false,
"legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "boolean"
},
"name": "pointWithinBounds",
"arguments": [
{
"optional": false,
"variadic": false,
"extAttrs": [],
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "Point"
},
"name": "p"
}
],
"extAttrs": []
},
{
"type": "operation",
"getter": false,
"setter": false,
"creator": false,
"deleter": false,
"legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "boolean"
},
"name": "allPointsWithinBounds",
"arguments": [
{
"optional": false,
"variadic": false,
"extAttrs": [],
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "PointSequence"
},
"name": "ps"
}
],
"extAttrs": []
}
],
"inheritance": null,
"extAttrs": []
},
{
"type": "typedef",
"typeExtAttrs": [
{
"name": "Clamp",
"arguments": null
}
],
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
"array": false,
"union": false,
"idlType": "octet"
},
"name": "value",
"extAttrs": []
}
]

View file

@ -0,0 +1,3 @@
{
"allowNestedTypedefs": true
}