Bug 885107 - Sync testharness with the latest upstream. r=Ms2ger

This commit is contained in:
Masatoshi Kimura 2013-10-01 00:35:32 +09:00
parent 8344dc84a9
commit 3744fe8a6a
6 changed files with 1168 additions and 6123 deletions

File diff suppressed because it is too large Load Diff

View File

@ -11,80 +11,80 @@
"MutationObserver interface: operation observe(Node,MutationObserverInit)": true, "MutationObserver interface: operation observe(Node,MutationObserverInit)": true,
"Node interface: existence and properties of interface object": true, "Node interface: existence and properties of interface object": true,
"Document interface: existence and properties of interface object": true, "Document interface: existence and properties of interface object": true,
"Document interface: operation prepend(union)": true, "Document interface: operation prepend([object Object],[object Object])": true,
"Document interface: operation append(union)": true, "Document interface: operation append([object Object],[object Object])": true,
"XMLDocument interface: existence and properties of interface object": true, "XMLDocument interface: existence and properties of interface object": true,
"Document interface: xmlDoc must inherit property \"prepend\" with the proper type (28)": true, "Document interface: xmlDoc must inherit property \"prepend\" with the proper type (28)": true,
"Document interface: calling prepend(union) on xmlDoc with too few arguments must throw TypeError": true, "Document interface: calling prepend([object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError": true,
"Document interface: xmlDoc must inherit property \"append\" with the proper type (29)": true, "Document interface: xmlDoc must inherit property \"append\" with the proper type (29)": true,
"Document interface: calling append(union) on xmlDoc with too few arguments must throw TypeError": true, "Document interface: calling append([object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError": true,
"DOMImplementation interface: operation createDocument(DOMString,DOMString,DocumentType)": true, "DOMImplementation interface: operation createDocument(DOMString,DOMString,DocumentType)": true,
"DOMImplementation interface: calling createDocument(DOMString,DOMString,DocumentType) on document.implementation with too few arguments must throw TypeError": true, "DOMImplementation interface: calling createDocument(DOMString,DOMString,DocumentType) on document.implementation with too few arguments must throw TypeError": true,
"DocumentFragment interface: existence and properties of interface object": true, "DocumentFragment interface: existence and properties of interface object": true,
"DocumentFragment interface: operation prepend(union)": true, "DocumentFragment interface: operation prepend([object Object],[object Object])": true,
"DocumentFragment interface: operation append(union)": true, "DocumentFragment interface: operation append([object Object],[object Object])": true,
"DocumentFragment interface: document.createDocumentFragment() must inherit property \"prepend\" with the proper type (4)": true, "DocumentFragment interface: document.createDocumentFragment() must inherit property \"prepend\" with the proper type (4)": true,
"DocumentFragment interface: calling prepend(union) on document.createDocumentFragment() with too few arguments must throw TypeError": true, "DocumentFragment interface: calling prepend([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError": true,
"DocumentFragment interface: document.createDocumentFragment() must inherit property \"append\" with the proper type (5)": true, "DocumentFragment interface: document.createDocumentFragment() must inherit property \"append\" with the proper type (5)": true,
"DocumentFragment interface: calling append(union) on document.createDocumentFragment() with too few arguments must throw TypeError": true, "DocumentFragment interface: calling append([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError": true,
"DocumentType interface: existence and properties of interface object": true, "DocumentType interface: existence and properties of interface object": true,
"DocumentType interface: operation before(union)": true, "DocumentType interface: operation before([object Object],[object Object])": true,
"DocumentType interface: operation after(union)": true, "DocumentType interface: operation after([object Object],[object Object])": true,
"DocumentType interface: operation replace(union)": true, "DocumentType interface: operation replace([object Object],[object Object])": true,
"DocumentType interface: document.doctype must inherit property \"before\" with the proper type (5)": true, "DocumentType interface: document.doctype must inherit property \"before\" with the proper type (5)": true,
"DocumentType interface: calling before(union) on document.doctype with too few arguments must throw TypeError": true, "DocumentType interface: calling before([object Object],[object Object]) on document.doctype with too few arguments must throw TypeError": true,
"DocumentType interface: document.doctype must inherit property \"after\" with the proper type (6)": true, "DocumentType interface: document.doctype must inherit property \"after\" with the proper type (6)": true,
"DocumentType interface: calling after(union) on document.doctype with too few arguments must throw TypeError": true, "DocumentType interface: calling after([object Object],[object Object]) on document.doctype with too few arguments must throw TypeError": true,
"DocumentType interface: document.doctype must inherit property \"replace\" with the proper type (7)": true, "DocumentType interface: document.doctype must inherit property \"replace\" with the proper type (7)": true,
"DocumentType interface: calling replace(union) on document.doctype with too few arguments must throw TypeError": true, "DocumentType interface: calling replace([object Object],[object Object]) on document.doctype with too few arguments must throw TypeError": true,
"Element interface: existence and properties of interface object": true, "Element interface: existence and properties of interface object": true,
"Element interface: attribute namespaceURI": true, "Element interface: attribute namespaceURI": true,
"Element interface: attribute prefix": true, "Element interface: attribute prefix": true,
"Element interface: attribute localName": true, "Element interface: attribute localName": true,
"Element interface: attribute className": true, "Element interface: attribute className": true,
"Element interface: operation prepend(union)": true, "Element interface: operation prepend([object Object],[object Object])": true,
"Element interface: operation append(union)": true, "Element interface: operation append([object Object],[object Object])": true,
"Element interface: operation before(union)": true, "Element interface: operation before([object Object],[object Object])": true,
"Element interface: operation after(union)": true, "Element interface: operation after([object Object],[object Object])": true,
"Element interface: operation replace(union)": true, "Element interface: operation replace([object Object],[object Object])": true,
"Element interface: element must inherit property \"className\" with the proper type (5)": true, "Element interface: element must inherit property \"className\" with the proper type (5)": true,
"Element interface: element must inherit property \"prepend\" with the proper type (23)": true, "Element interface: element must inherit property \"prepend\" with the proper type (23)": true,
"Element interface: calling prepend(union) on element with too few arguments must throw TypeError": true, "Element interface: calling prepend([object Object],[object Object]) on element with too few arguments must throw TypeError": true,
"Element interface: element must inherit property \"append\" with the proper type (24)": true, "Element interface: element must inherit property \"append\" with the proper type (24)": true,
"Element interface: calling append(union) on element with too few arguments must throw TypeError": true, "Element interface: calling append([object Object],[object Object]) on element with too few arguments must throw TypeError": true,
"Element interface: element must inherit property \"before\" with the proper type (27)": true, "Element interface: element must inherit property \"before\" with the proper type (27)": true,
"Element interface: calling before(union) on element with too few arguments must throw TypeError": true, "Element interface: calling before([object Object],[object Object]) on element with too few arguments must throw TypeError": true,
"Element interface: element must inherit property \"after\" with the proper type (28)": true, "Element interface: element must inherit property \"after\" with the proper type (28)": true,
"Element interface: calling after(union) on element with too few arguments must throw TypeError": true, "Element interface: calling after([object Object],[object Object]) on element with too few arguments must throw TypeError": true,
"Element interface: element must inherit property \"replace\" with the proper type (29)": true, "Element interface: element must inherit property \"replace\" with the proper type (29)": true,
"Element interface: calling replace(union) on element with too few arguments must throw TypeError": true, "Element interface: calling replace([object Object],[object Object]) on element with too few arguments must throw TypeError": true,
"Attr interface: existence and properties of interface object": true, "Attr interface: existence and properties of interface object": true,
"Attr interface: existence and properties of interface prototype object": true, "Attr interface: existence and properties of interface prototype object": true,
"CharacterData interface: existence and properties of interface object": true, "CharacterData interface: existence and properties of interface object": true,
"CharacterData interface: operation before(union)": true, "CharacterData interface: operation before([object Object],[object Object])": true,
"CharacterData interface: operation after(union)": true, "CharacterData interface: operation after([object Object],[object Object])": true,
"CharacterData interface: operation replace(union)": true, "CharacterData interface: operation replace([object Object],[object Object])": true,
"Text interface: existence and properties of interface object": true, "Text interface: existence and properties of interface object": true,
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"before\" with the proper type (9)": true, "CharacterData interface: document.createTextNode(\"abc\") must inherit property \"before\" with the proper type (9)": true,
"CharacterData interface: calling before(union) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true, "CharacterData interface: calling before([object Object],[object Object]) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true,
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"after\" with the proper type (10)": true, "CharacterData interface: document.createTextNode(\"abc\") must inherit property \"after\" with the proper type (10)": true,
"CharacterData interface: calling after(union) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true, "CharacterData interface: calling after([object Object],[object Object]) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true,
"CharacterData interface: document.createTextNode(\"abc\") must inherit property \"replace\" with the proper type (11)": true, "CharacterData interface: document.createTextNode(\"abc\") must inherit property \"replace\" with the proper type (11)": true,
"CharacterData interface: calling replace(union) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true, "CharacterData interface: calling replace([object Object],[object Object]) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true,
"ProcessingInstruction interface: existence and properties of interface object": true, "ProcessingInstruction interface: existence and properties of interface object": true,
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"before\" with the proper type (9)": true, "CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"before\" with the proper type (9)": true,
"CharacterData interface: calling before(union) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true, "CharacterData interface: calling before([object Object],[object Object]) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true,
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"after\" with the proper type (10)": true, "CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"after\" with the proper type (10)": true,
"CharacterData interface: calling after(union) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true, "CharacterData interface: calling after([object Object],[object Object]) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true,
"CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"replace\" with the proper type (11)": true, "CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"replace\" with the proper type (11)": true,
"CharacterData interface: calling replace(union) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true, "CharacterData interface: calling replace([object Object],[object Object]) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true,
"Comment interface: existence and properties of interface object": true, "Comment interface: existence and properties of interface object": true,
"CharacterData interface: document.createComment(\"abc\") must inherit property \"before\" with the proper type (9)": true, "CharacterData interface: document.createComment(\"abc\") must inherit property \"before\" with the proper type (9)": true,
"CharacterData interface: calling before(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true, "CharacterData interface: calling before([object Object],[object Object]) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
"CharacterData interface: document.createComment(\"abc\") must inherit property \"after\" with the proper type (10)": true, "CharacterData interface: document.createComment(\"abc\") must inherit property \"after\" with the proper type (10)": true,
"CharacterData interface: calling after(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true, "CharacterData interface: calling after([object Object],[object Object]) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
"CharacterData interface: document.createComment(\"abc\") must inherit property \"replace\" with the proper type (11)": true, "CharacterData interface: document.createComment(\"abc\") must inherit property \"replace\" with the proper type (11)": true,
"CharacterData interface: calling replace(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true, "CharacterData interface: calling replace([object Object],[object Object]) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
"NodeFilter interface: existence and properties of interface object": true, "NodeFilter interface: existence and properties of interface object": true,
"NodeList interface: existence and properties of interface prototype object": true, "NodeList interface: existence and properties of interface prototype object": true,
"DOMTokenList interface: operation add(DOMString)": true, "DOMTokenList interface: operation add(DOMString)": true,

View File

@ -334,7 +334,7 @@ interface Range {
void setStartAfter(Node refNode); void setStartAfter(Node refNode);
void setEndBefore(Node refNode); void setEndBefore(Node refNode);
void setEndAfter(Node refNode); void setEndAfter(Node refNode);
void collapse(optional boolean toStart /* = false */); void collapse(optional boolean toStart = false);
void selectNode(Node refNode); void selectNode(Node refNode);
void selectNodeContents(Node refNode); void selectNodeContents(Node refNode);

View File

@ -14,7 +14,7 @@ policies and contribution forms [3].
* *
* <script src=/resources/testharness.js></script> * <script src=/resources/testharness.js></script>
* <script src=/resources/testharnessreport.js></script> * <script src=/resources/testharnessreport.js></script>
* <script src=/resources/WebIDLParser.js></script> * <script src=/resources/webidl2.js></script>
* <script src=/resources/idlharness.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 * Then you'll need some type of IDLs. Here's some script that can be run on a
@ -170,8 +170,16 @@ policies and contribution forms [3].
* The members and methods of the classes defined by this file are all at least * The members and methods of the classes defined by this file are all at least
* briefly documented, hopefully. * briefly documented, hopefully.
*/ */
"use strict";
(function(){ (function(){
"use strict";
/// Helpers ///
function constValue (cnt) {
if (cnt.type === "null") return null;
if (cnt.type === "NaN") return NaN;
if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity;
return cnt.value;
}
/// IdlArray /// /// IdlArray ///
// Entry point // Entry point
window.IdlArray = function() window.IdlArray = function()
@ -213,15 +221,15 @@ window.IdlArray = function()
* results in { A: ["B", "C"], D: ["E"] }. * results in { A: ["B", "C"], D: ["E"] }.
*/ */
this.partials = []; this.partials = [];
this.implements = {}; this["implements"] = {};
} };
//@} //@}
IdlArray.prototype.add_idls = function(raw_idls) IdlArray.prototype.add_idls = function(raw_idls)
//@{ //@{
{ {
/** Entry point. See documentation at beginning of file. */ /** Entry point. See documentation at beginning of file. */
this.internal_add_idls(WebIDLParser.parse(raw_idls)); this.internal_add_idls(WebIDL2.parse(raw_idls));
}; };
//@} //@}
@ -229,7 +237,7 @@ IdlArray.prototype.add_untested_idls = function(raw_idls)
//@{ //@{
{ {
/** Entry point. See documentation at beginning of file. */ /** Entry point. See documentation at beginning of file. */
var parsed_idls = WebIDLParser.parse(raw_idls); var parsed_idls = WebIDL2.parse(raw_idls);
for (var i = 0; i < parsed_idls.length; i++) for (var i = 0; i < parsed_idls.length; i++)
{ {
parsed_idls[i].untested = true; parsed_idls[i].untested = true;
@ -242,7 +250,7 @@ IdlArray.prototype.add_untested_idls = function(raw_idls)
} }
} }
this.internal_add_idls(parsed_idls); this.internal_add_idls(parsed_idls);
} };
//@} //@}
IdlArray.prototype.internal_add_idls = function(parsed_idls) IdlArray.prototype.internal_add_idls = function(parsed_idls)
@ -258,7 +266,7 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls)
*/ */
parsed_idls.forEach(function(parsed_idl) parsed_idls.forEach(function(parsed_idl)
{ {
if (parsed_idl.type == "partialinterface") if (parsed_idl.type == "interface" && parsed_idl.partial)
{ {
this.partials.push(parsed_idl); this.partials.push(parsed_idl);
return; return;
@ -266,11 +274,11 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls)
if (parsed_idl.type == "implements") if (parsed_idl.type == "implements")
{ {
if (!(parsed_idl.target in this.implements)) if (!(parsed_idl.target in this["implements"]))
{ {
this.implements[parsed_idl.target] = []; this["implements"][parsed_idl.target] = [];
} }
this.implements[parsed_idl.target].push(parsed_idl.implements); this["implements"][parsed_idl.target].push(parsed_idl["implements"]);
return; return;
} }
@ -297,10 +305,16 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls)
case "typedef": case "typedef":
// TODO // TODO
console.log("typedef not yet supported");
break;
case "callback":
// TODO
console.log("callback not yet supported");
break; break;
case "enum": case "enum":
// TODO this.members[parsed_idl.name] = new IdlEnum(parsed_idl);
break; break;
case "callback": case "callback":
@ -311,7 +325,7 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls)
throw parsed_idl.name + ": " + parsed_idl.type + " not yet supported"; throw parsed_idl.name + ": " + parsed_idl.type + " not yet supported";
} }
}.bind(this)); }.bind(this));
} };
//@} //@}
IdlArray.prototype.add_objects = function(dict) IdlArray.prototype.add_objects = function(dict)
@ -329,7 +343,7 @@ IdlArray.prototype.add_objects = function(dict)
this.objects[k] = dict[k]; this.objects[k] = dict[k];
} }
} }
} };
//@} //@}
IdlArray.prototype.prevent_multiple_testing = function(name) IdlArray.prototype.prevent_multiple_testing = function(name)
@ -337,7 +351,7 @@ IdlArray.prototype.prevent_multiple_testing = function(name)
{ {
/** Entry point. See documentation at beginning of file. */ /** Entry point. See documentation at beginning of file. */
this.members[name].prevent_multiple_testing = true; this.members[name].prevent_multiple_testing = true;
} };
//@} //@}
IdlArray.prototype.recursively_get_implements = function(interface_name) IdlArray.prototype.recursively_get_implements = function(interface_name)
@ -353,12 +367,12 @@ IdlArray.prototype.recursively_get_implements = function(interface_name)
* *
* then recursively_get_implements("A") should return ["B", "C", "D"]. * then recursively_get_implements("A") should return ["B", "C", "D"].
*/ */
var ret = this.implements[interface_name]; var ret = this["implements"][interface_name];
if (ret === undefined) if (ret === undefined)
{ {
return []; return [];
} }
for (var i = 0; i < this.implements[interface_name].length; i++) for (var i = 0; i < this["implements"][interface_name].length; i++)
{ {
ret = ret.concat(this.recursively_get_implements(ret[i])); ret = ret.concat(this.recursively_get_implements(ret[i]));
if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i])) if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
@ -367,7 +381,7 @@ IdlArray.prototype.recursively_get_implements = function(interface_name)
} }
} }
return ret; return ret;
} };
//@} //@}
IdlArray.prototype.test = function() IdlArray.prototype.test = function()
@ -398,24 +412,22 @@ IdlArray.prototype.test = function()
}.bind(this)); }.bind(this));
this.partials = []; this.partials = [];
for (var lhs in this.implements) for (var lhs in this["implements"])
{ {
this.recursively_get_implements(lhs).forEach(function(rhs) this.recursively_get_implements(lhs).forEach(function(rhs)
{ {
if (!(lhs in this.members) var errStr = lhs + " implements " + rhs + ", but ";
|| !(this.members[lhs] instanceof IdlInterface) if (!(lhs in this.members)) throw errStr + lhs + " is undefined.";
|| !(rhs in this.members) if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + " is not an interface.";
|| !(this.members[rhs] instanceof IdlInterface)) if (!(rhs in this.members)) throw errStr + rhs + " is undefined.";
{ if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface.";
throw lhs + " implements " + rhs + ", but one is undefined or not an interface";
}
this.members[rhs].members.forEach(function(member) this.members[rhs].members.forEach(function(member)
{ {
this.members[lhs].members.push(new IdlInterfaceMember(member)); this.members[lhs].members.push(new IdlInterfaceMember(member));
}.bind(this)); }.bind(this));
}.bind(this)); }.bind(this));
} }
this.implements = {}; this["implements"] = {};
// Now run test() on every member, and test_object() for every object. // Now run test() on every member, and test_object() for every object.
for (var name in this.members) for (var name in this.members)
@ -564,6 +576,10 @@ IdlArray.prototype.assert_type_is = function(value, type)
assert_true(value instanceof window[type], "not instanceof " + type); assert_true(value instanceof window[type], "not instanceof " + type);
} }
} }
else if (this.members[type] instanceof IdlEnum)
{
assert_equals(typeof value, "string");
}
else if (this.members[type] instanceof IdlDictionary) else if (this.members[type] instanceof IdlDictionary)
{ {
// TODO: Test when we actually have something to test this on // TODO: Test when we actually have something to test this on
@ -622,10 +638,7 @@ function IdlDictionary(obj)
* The name (as a string) of the dictionary type we inherit from, or null * The name (as a string) of the dictionary type we inherit from, or null
* if there is none. * if there is none.
*/ */
if (obj.inheritance.length > 1) { this.base = obj.inheritance;
throw "Multiple inheritance is no longer supported in WebIDL";
}
this.base = obj.inheritance.length ? obj.inheritance[0] : null;
} }
//@} //@}
@ -658,16 +671,13 @@ function IdlExceptionOrInterface(obj)
this.extAttrs = obj.extAttrs; this.extAttrs = obj.extAttrs;
/** An array of IdlInterfaceMembers. */ /** An array of IdlInterfaceMembers. */
this.members = obj.members.map(function(m){return new IdlInterfaceMember(m)}); this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); });
/** /**
* The name (as a string) of the type we inherit from, or null if there is * The name (as a string) of the type we inherit from, or null if there is
* none. * none.
*/ */
if (obj.inheritance.length > 1) { this.base = obj.inheritance;
throw "Multiple inheritance is no longer supported in WebIDL";
}
this.base = obj.inheritance.length ? obj.inheritance[0] : null;
} }
//@} //@}
@ -697,7 +707,7 @@ IdlExceptionOrInterface.prototype.test = function()
// members will be marked as untested, but the members added by the partial // members will be marked as untested, but the members added by the partial
// interface are still tested. // interface are still tested.
this.test_members(); this.test_members();
} };
//@} //@}
@ -851,7 +861,7 @@ IdlException.prototype.test_self = function()
assert_equals(window[this.name].prototype.constructor, window[this.name], assert_equals(window[this.name].prototype.constructor, window[this.name],
this.name + '.prototype.constructor is not the same object as ' + this.name); this.name + '.prototype.constructor is not the same object as ' + this.name);
}.bind(this), this.name + " exception: existence and properties of exception interface prototype object's \"constructor\" property"); }.bind(this), this.name + " exception: existence and properties of exception interface prototype object's \"constructor\" property");
} };
//@} //@}
IdlException.prototype.test_members = function() IdlException.prototype.test_members = function()
@ -879,7 +889,7 @@ IdlException.prototype.test_members = function()
// "The value of the property is the ECMAScript value that is // "The value of the property is the ECMAScript value that is
// equivalent to the constants IDL value, according to the // equivalent to the constants IDL value, according to the
// rules in section 4.2 above." // rules in section 4.2 above."
assert_equals(window[this.name][member.name], eval(member.value), assert_equals(window[this.name][member.name], constValue(member.value),
"property has wrong value"); "property has wrong value");
// "The property has attributes { [[Writable]]: false, // "The property has attributes { [[Writable]]: false,
// [[Enumerable]]: true, [[Configurable]]: false }." // [[Enumerable]]: true, [[Configurable]]: false }."
@ -900,7 +910,7 @@ IdlException.prototype.test_members = function()
'exception "' + this.name + '" does not have own property "prototype"'); 'exception "' + this.name + '" does not have own property "prototype"');
assert_own_property(window[this.name].prototype, member.name); assert_own_property(window[this.name].prototype, member.name);
assert_equals(window[this.name].prototype[member.name], eval(member.value), assert_equals(window[this.name].prototype[member.name], constValue(member.value),
"property has wrong value"); "property has wrong value");
var desc = Object.getOwnPropertyDescriptor(window[this.name].prototype, member.name); var desc = Object.getOwnPropertyDescriptor(window[this.name].prototype, member.name);
assert_false("get" in desc, "property has getter"); assert_false("get" in desc, "property has getter");
@ -959,7 +969,7 @@ IdlException.prototype.test_members = function()
}.bind(this), this.name + " exception: field " + member.name + " on exception interface prototype object"); }.bind(this), this.name + " exception: field " + member.name + " on exception interface prototype object");
} }
} }
} };
//@} //@}
IdlException.prototype.test_object = function(desc) IdlException.prototype.test_object = function(desc)
@ -1019,7 +1029,7 @@ IdlException.prototype.test_object = function(desc)
assert_inherits(obj, member.name); assert_inherits(obj, member.name);
if (member.type == "const") if (member.type == "const")
{ {
assert_equals(obj[member.name], eval(member.value)); assert_equals(obj[member.name], constValue(member.value));
} }
if (member.type == "field") if (member.type == "field")
{ {
@ -1027,7 +1037,7 @@ IdlException.prototype.test_object = function(desc)
} }
}.bind(this), this.name + " exception: " + desc + ' must inherit property "' + member.name + '" with the proper type'); }.bind(this), this.name + " exception: " + desc + ' must inherit property "' + member.name + '" with the proper type');
} }
} };
//@} //@}
/// IdlInterface /// /// IdlInterface ///
@ -1037,7 +1047,7 @@ IdlInterface.prototype.is_callback = function()
//@{ //@{
{ {
return this.has_extended_attribute("Callback"); return this.has_extended_attribute("Callback");
} };
//@} //@}
IdlInterface.prototype.has_constants = function() IdlInterface.prototype.has_constants = function()
@ -1046,7 +1056,7 @@ IdlInterface.prototype.has_constants = function()
return this.members.some(function(member) { return this.members.some(function(member) {
return member.type === "const"; return member.type === "const";
}); });
} };
//@} //@}
IdlInterface.prototype.test_self = function() IdlInterface.prototype.test_self = function()
@ -1150,14 +1160,14 @@ IdlInterface.prototype.test_self = function()
// works for testing operation length too (currently we just don't // works for testing operation length too (currently we just don't
// support multiple operations with the same identifier). // support multiple operations with the same identifier).
var expected_length = this.extAttrs var expected_length = this.extAttrs
.filter(function(attr) { return attr.name == "Constructor" }) .filter(function(attr) { return attr.name == "Constructor"; })
.map(function(attr) { .map(function(attr) {
return attr.arguments ? attr.arguments.filter( return attr.arguments ? attr.arguments.filter(
function(arg) { function(arg) {
return !arg.optional; return !arg.optional;
}).length : 0 }).length : 0;
}) })
.reduce(function(m, n) { return Math.min(m, n) }); .reduce(function(m, n) { return Math.min(m, n); });
assert_own_property(window[this.name], "length"); assert_own_property(window[this.name], "length");
assert_equals(window[this.name].length, expected_length, "wrong value for " + this.name + ".length"); assert_equals(window[this.name].length, expected_length, "wrong value for " + this.name + ".length");
var desc = Object.getOwnPropertyDescriptor(window[this.name], "length"); var desc = Object.getOwnPropertyDescriptor(window[this.name], "length");
@ -1289,7 +1299,7 @@ IdlInterface.prototype.test_self = function()
assert_equals(window[this.name].prototype.constructor, window[this.name], assert_equals(window[this.name].prototype.constructor, window[this.name],
this.name + '.prototype.constructor is not the same object as ' + this.name); this.name + '.prototype.constructor is not the same object as ' + this.name);
}.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property'); }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property');
} };
//@} //@}
IdlInterface.prototype.test_members = function() IdlInterface.prototype.test_members = function()
@ -1316,7 +1326,7 @@ IdlInterface.prototype.test_members = function()
// "The value of the property is that which is obtained by // "The value of the property is that which is obtained by
// converting the constants IDL value to an ECMAScript // converting the constants IDL value to an ECMAScript
// value." // value."
assert_equals(window[this.name][member.name], eval(member.value), assert_equals(window[this.name][member.name], constValue(member.value),
"property has wrong value"); "property has wrong value");
// "The property has attributes { [[Writable]]: false, // "The property has attributes { [[Writable]]: false,
// [[Enumerable]]: true, [[Configurable]]: false }." // [[Enumerable]]: true, [[Configurable]]: false }."
@ -1344,7 +1354,7 @@ IdlInterface.prototype.test_members = function()
'interface "' + this.name + '" does not have own property "prototype"'); 'interface "' + this.name + '" does not have own property "prototype"');
assert_own_property(window[this.name].prototype, member.name); assert_own_property(window[this.name].prototype, member.name);
assert_equals(window[this.name].prototype[member.name], eval(member.value), assert_equals(window[this.name].prototype[member.name], constValue(member.value),
"property has wrong value"); "property has wrong value");
var desc = Object.getOwnPropertyDescriptor(window[this.name], member.name); var desc = Object.getOwnPropertyDescriptor(window[this.name], member.name);
assert_false("get" in desc, "property has getter"); assert_false("get" in desc, "property has getter");
@ -1367,6 +1377,9 @@ IdlInterface.prototype.test_members = function()
"window does not have own property " + format_value(this.name)); "window does not have own property " + format_value(this.name));
assert_own_property(window[this.name], "prototype", assert_own_property(window[this.name], "prototype",
'interface "' + this.name + '" does not have own property "prototype"'); 'interface "' + this.name + '" does not have own property "prototype"');
assert_true(member.name in window[this.name].prototype,
"The prototype object must have a property " +
format_value(member.name));
// TODO: Needs to test for LenientThis. // TODO: Needs to test for LenientThis.
assert_throws(new TypeError(), function() { assert_throws(new TypeError(), function() {
@ -1438,7 +1451,7 @@ IdlInterface.prototype.test_members = function()
// Make some suitable arguments // Make some suitable arguments
var args = member.arguments.map(function(arg) { var args = member.arguments.map(function(arg) {
return create_suitable_object(arg.type); return create_suitable_object(arg.idlType);
}); });
// "Let O be a value determined as follows: // "Let O be a value determined as follows:
@ -1462,12 +1475,12 @@ IdlInterface.prototype.test_members = function()
window[this.name].prototype[member.name].apply({}, args); window[this.name].prototype[member.name].apply({}, args);
}, "calling operation with this = {} didn't throw TypeError"); }, "calling operation with this = {} didn't throw TypeError");
}.bind(this), this.name + " interface: operation " + member.name + }.bind(this), this.name + " interface: operation " + member.name +
"(" + member.arguments.map(function(m) { return m.type.idlType; }) + "(" + member.arguments.map(function(m) { return m.idlType.idlType; }) +
")"); ")");
} }
// TODO: check more member types, like stringifier // TODO: check more member types, like stringifier
} }
} };
//@} //@}
IdlInterface.prototype.test_object = function(desc) IdlInterface.prototype.test_object = function(desc)
@ -1508,7 +1521,7 @@ IdlInterface.prototype.test_object = function(desc)
current_interface.test_interface_of(desc, obj, exception, expected_typeof); current_interface.test_interface_of(desc, obj, exception, expected_typeof);
current_interface = this.array.members[current_interface.base]; current_interface = this.array.members[current_interface.base];
} }
} };
//@} //@}
IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception, expected_typeof) IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception, expected_typeof)
@ -1553,7 +1566,7 @@ IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception
assert_equals(String(obj), "[object " + this.name + "]", "String(" + desc + ")"); assert_equals(String(obj), "[object " + this.name + "]", "String(" + desc + ")");
} }
}.bind(this), "Stringification of " + desc); }.bind(this), "Stringification of " + desc);
} };
//@} //@}
IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof) IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof)
@ -1586,7 +1599,7 @@ IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expect
assert_inherits(obj, member.name); assert_inherits(obj, member.name);
if (member.type == "const") if (member.type == "const")
{ {
assert_equals(obj[member.name], eval(member.value)); assert_equals(obj[member.name], constValue(member.value));
} }
if (member.type == "attribute") if (member.type == "attribute")
{ {
@ -1635,20 +1648,20 @@ IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expect
obj[member.name].apply(obj, args); obj[member.name].apply(obj, args);
}.bind(this), "Called with " + i + " arguments"); }.bind(this), "Called with " + i + " arguments");
args.push(create_suitable_object(member.arguments[i].type)); args.push(create_suitable_object(member.arguments[i].idlType));
} }
}.bind(this), this.name + " interface: calling " + member.name + }.bind(this), this.name + " interface: calling " + member.name +
"(" + member.arguments.map(function(m) { return m.type.idlType; }) + "(" + member.arguments.map(function(m) { return m.idlType.idlType; }) +
") on " + desc + " with too few arguments must throw TypeError"); ") on " + desc + " with too few arguments must throw TypeError");
} }
} }
} };
//@} //@}
IdlInterface.prototype.has_stringifier = function() IdlInterface.prototype.has_stringifier = function()
//@{ //@{
{ {
if (this.members.some(function(member) { return member.stringifier })) { if (this.members.some(function(member) { return member.stringifier; })) {
return true; return true;
} }
if (this.base && if (this.base &&
@ -1656,7 +1669,7 @@ IdlInterface.prototype.has_stringifier = function()
return true; return true;
} }
return false; return false;
} };
//@} //@}
function do_interface_attribute_asserts(obj, member) function do_interface_attribute_asserts(obj, member)
@ -1786,5 +1799,39 @@ function create_suitable_object(type)
return null; return null;
} }
//@} //@}
})();
/// IdlEnum ///
// Used for IdlArray.prototype.assert_type_is
function IdlEnum(obj)
//@{
{
/**
* obj is an object produced by the WebIDLParser.js "dictionary"
* production.
*/
/** Self-explanatory. */
this.name = obj.name;
console.log("Name is " + this.name);
/** An array of values produced by the "enum" production. */
this.values = obj.values;
}
//@}
IdlEnum.prototype = Object.create(IdlObject.prototype);
IdlEnum.prototype.test = function()
//@{
{
test(function()
{
// NOTHING to test
return;
});
}
//@}
}());
// vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker: // vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:

View File

@ -59,21 +59,18 @@ policies and contribution forms [3].
* would run test_function with a timeout of 1s. * would run test_function with a timeout of 1s.
* *
* Additionally, test-specific metadata can be passed in the properties. These * Additionally, test-specific metadata can be passed in the properties. These
* are used when the individual test has different metadata from that stored * are used when the individual test has different metadata from that stored
* in the <head>. * in the <head>.
* The recognized metadata properties are: * The recognized metadata properties are:
* *
* help - The url of the part of the specification being tested * help - The url of the part of the specification being tested
* *
* assert - A human readable description of what the test is attempting * assert - A human readable description of what the test is attempting
* to prove * to prove
* *
* author - Name and contact information for the author of the test in the * author - Name and contact information for the author of the test in the
* format: "Name <email_addr>" or "Name http://contact/url" * format: "Name <email_addr>" or "Name http://contact/url"
* *
* flags - space separated list of test flags in addition to any present in
* the head metadata
*
* == Asynchronous Tests == * == Asynchronous Tests ==
* *
* Testing asynchronous features is somewhat more complex since the result of * Testing asynchronous features is somewhat more complex since the result of
@ -166,6 +163,10 @@ policies and contribution forms [3].
* use when integrating with some existing test framework * use when integrating with some existing test framework
* that has its own timeout mechanism). * that has its own timeout mechanism).
* *
* allow_uncaught_exception - don't treat an uncaught exception as an error;
* needed when e.g. testing the window.onerror
* handler.
*
* == Determining when all tests are complete == * == Determining when all tests are complete ==
* *
* By default the test harness will assume there are no more results to come * By default the test harness will assume there are no more results to come
@ -204,7 +205,7 @@ policies and contribution forms [3].
* Note that the first item in each parameter list corresponds to the name of * Note that the first item in each parameter list corresponds to the name of
* the test. * the test.
* *
* The properties argument is identical to that for test(). This may be a * The properties argument is identical to that for test(). This may be a
* single object (used for all generated tests) or an array. * single object (used for all generated tests) or an array.
* *
* == Callback API == * == Callback API ==
@ -290,6 +291,18 @@ policies and contribution forms [3].
* assert_approx_equals(actual, expected, epsilon, description) * assert_approx_equals(actual, expected, epsilon, description)
* asserts that /actual/ is a number within +/- /epsilon/ of /expected/ * asserts that /actual/ is a number within +/- /epsilon/ of /expected/
* *
* assert_less_than(actual, expected, description)
* asserts that /actual/ is a number less than /expected/
*
* assert_greater_than(actual, expected, description)
* asserts that /actual/ is a number greater than /expected/
*
* assert_less_than_equal(actual, expected, description)
* asserts that /actual/ is a number less than or equal to /expected/
*
* assert_greater_than_equal(actual, expected, description)
* asserts that /actual/ is a number greater than or equal to /expected/
*
* assert_regexp_match(actual, expected, description) * assert_regexp_match(actual, expected, description)
* asserts that /actual/ matches the regexp /expected/ * asserts that /actual/ matches the regexp /expected/
* *
@ -331,7 +344,7 @@ policies and contribution forms [3].
* is true for some expected_array_N in expected_array. This only works for assert_func * is true for some expected_array_N in expected_array. This only works for assert_func
* with signature assert_func(actual, expected, args_1, ..., args_N). Note that tests * with signature assert_func(actual, expected, args_1, ..., args_N). Note that tests
* with multiple allowed pass conditions are bad practice unless the spec specifically * with multiple allowed pass conditions are bad practice unless the spec specifically
* allows multiple behaviours. Test authors should not use this method simply to hide * allows multiple behaviours. Test authors should not use this method simply to hide
* UA bugs. * UA bugs.
* *
* assert_exists(object, property_name, description) * assert_exists(object, property_name, description)
@ -389,9 +402,8 @@ policies and contribution forms [3].
function next_default_name() function next_default_name()
{ {
//Don't use document.title to work around an Opera bug in XHTML documents //Don't use document.title to work around an Opera bug in XHTML documents
var prefix = document.getElementsByTagName("title").length > 0 ? var title = document.getElementsByTagName("title")[0];
document.getElementsByTagName("title")[0].firstChild.data : var prefix = (title && title.firstChild && title.firstChild.data) || "Untitled";
"Untitled";
var suffix = name_counter > 0 ? " " + name_counter : ""; var suffix = name_counter > 0 ? " " + name_counter : "";
name_counter++; name_counter++;
return prefix + suffix; return prefix + suffix;
@ -451,8 +463,8 @@ policies and contribution forms [3].
test(function() test(function()
{ {
func.apply(this, x.slice(1)); func.apply(this, x.slice(1));
}, },
name, name,
Array.isArray(properties) ? properties[i] : properties); Array.isArray(properties) ? properties[i] : properties);
}); });
} }
@ -484,11 +496,22 @@ policies and contribution forms [3].
/* /*
* Convert a value to a nice, human-readable string * Convert a value to a nice, human-readable string
*/ */
function format_value(val) function format_value(val, seen)
{ {
if (!seen) {
seen = [];
}
if (typeof val === "object" && val !== null)
{
if (seen.indexOf(val) >= 0)
{
return "[...]";
}
seen.push(val);
}
if (Array.isArray(val)) if (Array.isArray(val))
{ {
return "[" + val.map(format_value).join(", ") + "]"; return "[" + val.map(function(x) {return format_value(x, seen)}).join(", ") + "]";
} }
switch (typeof val) switch (typeof val)
@ -748,6 +771,74 @@ policies and contribution forms [3].
}; };
expose(assert_approx_equals, "assert_approx_equals"); expose(assert_approx_equals, "assert_approx_equals");
function assert_less_than(actual, expected, description)
{
/*
* Test if a primitive number is less than another
*/
assert(typeof actual === "number",
"assert_less_than", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
assert(actual < expected,
"assert_less_than", description,
"expected a number less than ${expected} but got ${actual}",
{expected:expected, actual:actual});
};
expose(assert_less_than, "assert_less_than");
function assert_greater_than(actual, expected, description)
{
/*
* Test if a primitive number is greater than another
*/
assert(typeof actual === "number",
"assert_greater_than", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
assert(actual > expected,
"assert_greater_than", description,
"expected a number greater than ${expected} but got ${actual}",
{expected:expected, actual:actual});
};
expose(assert_greater_than, "assert_greater_than");
function assert_less_than_equal(actual, expected, description)
{
/*
* Test if a primitive number is less than or equal to another
*/
assert(typeof actual === "number",
"assert_less_than_equal", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
assert(actual <= expected,
"assert_less_than", description,
"expected a number less than or equal to ${expected} but got ${actual}",
{expected:expected, actual:actual});
};
expose(assert_less_than_equal, "assert_less_than_equal");
function assert_greater_than_equal(actual, expected, description)
{
/*
* Test if a primitive number is greater than or equal to another
*/
assert(typeof actual === "number",
"assert_greater_than_equal", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
assert(actual >= expected,
"assert_greater_than_equal", description,
"expected a number greater than or equal to ${expected} but got ${actual}",
{expected:expected, actual:actual});
};
expose(assert_greater_than_equal, "assert_greater_than_equal");
function assert_regexp_match(actual, expected, description) { function assert_regexp_match(actual, expected, description) {
/* /*
* Test if a string (actual) matches a regexp (expected) * Test if a string (actual) matches a regexp (expected)
@ -955,12 +1046,12 @@ policies and contribution forms [3].
} }
expose(assert_unreached, "assert_unreached"); expose(assert_unreached, "assert_unreached");
function assert_any(assert_func, actual, expected_array) function assert_any(assert_func, actual, expected_array)
{ {
var args = [].slice.call(arguments, 3) var args = [].slice.call(arguments, 3)
var errors = [] var errors = []
var passed = false; var passed = false;
forEach(expected_array, forEach(expected_array,
function(expected) function(expected)
{ {
try { try {
@ -1041,7 +1132,7 @@ policies and contribution forms [3].
try try
{ {
func.apply(this_obj, Array.prototype.slice.call(arguments, 2)); return func.apply(this_obj, Array.prototype.slice.call(arguments, 2));
} }
catch(e) catch(e)
{ {
@ -1185,6 +1276,8 @@ policies and contribution forms [3].
this.wait_for_finish = false; this.wait_for_finish = false;
this.processing_callbacks = false; this.processing_callbacks = false;
this.allow_uncaught_exception = false;
this.timeout_length = settings.timeout; this.timeout_length = settings.timeout;
this.timeout_id = null; this.timeout_id = null;
@ -1205,6 +1298,8 @@ policies and contribution forms [3].
this_obj.complete(); this_obj.complete();
} }
}); });
this.set_timeout();
} }
Tests.prototype.setup = function(func, properties) Tests.prototype.setup = function(func, properties)
@ -1218,26 +1313,30 @@ policies and contribution forms [3].
this.phase = this.phases.SETUP; this.phase = this.phases.SETUP;
} }
this.properties = properties;
for (var p in properties) for (var p in properties)
{ {
if (properties.hasOwnProperty(p)) if (properties.hasOwnProperty(p))
{ {
this.properties[p] = properties[p]; var value = properties[p]
if (p == "timeout")
{
this.timeout_length = value;
}
else if (p == "allow_uncaught_exception") {
this.allow_uncaught_exception = value;
}
else if (p == "explicit_done" && value)
{
this.wait_for_finish = true;
}
else if (p == "explicit_timeout" && value) {
this.timeout_length = null;
}
} }
} }
if (properties.timeout)
{
this.timeout_length = properties.timeout;
}
if (properties.explicit_done)
{
this.wait_for_finish = true;
}
if (properties.explicit_timeout) {
this.timeout_length = null;
}
if (func) if (func)
{ {
try try
@ -1449,6 +1548,15 @@ policies and contribution forms [3].
var tests = new Tests(); var tests = new Tests();
window.onerror = function(msg) {
if (!tests.allow_uncaught_exception)
{
tests.status.status = tests.status.ERROR;
tests.status.message = msg;
tests.complete();
}
}
function timeout() { function timeout() {
if (tests.timeout_length === null) if (tests.timeout_length === null)
{ {
@ -1602,6 +1710,11 @@ policies and contribution forms [3].
} }
} }
var status_text_harness = {};
status_text_harness[harness_status.OK] = "OK";
status_text_harness[harness_status.ERROR] = "Error";
status_text_harness[harness_status.TIMEOUT] = "Timeout";
var status_text = {}; var status_text = {};
status_text[Test.prototype.PASS] = "Pass"; status_text[Test.prototype.PASS] = "Pass";
status_text[Test.prototype.FAIL] = "Fail"; status_text[Test.prototype.FAIL] = "Fail";
@ -1626,6 +1739,34 @@ policies and contribution forms [3].
var summary_template = ["section", {"id":"summary"}, var summary_template = ["section", {"id":"summary"},
["h2", {}, "Summary"], ["h2", {}, "Summary"],
function(vars)
{
if (harness_status.status === harness_status.OK)
{
return null;
}
else
{
var status = status_text_harness[harness_status.status];
var rv = [["p", {"class":status_class(status)}]];
if (harness_status.status === harness_status.ERROR)
{
rv[0].push("Harness encountered an error:");
rv.push(["pre", {}, harness_status.message]);
}
else if (harness_status.status === harness_status.TIMEOUT)
{
rv[0].push("Harness timed out.");
}
else
{
rv[0].push("Harness got an unexpected status.");
}
return rv;
}
},
["p", {}, "Found ${num_tests} tests"], ["p", {}, "Found ${num_tests} tests"],
function(vars) { function(vars) {
var rv = [["div", {}]]; var rv = [["div", {}]];
@ -1691,7 +1832,7 @@ policies and contribution forms [3].
} }
return false; return false;
} }
function get_assertion(test) function get_assertion(test)
{ {
if (test.properties.hasOwnProperty("assert")) { if (test.properties.hasOwnProperty("assert")) {
@ -1702,7 +1843,7 @@ policies and contribution forms [3].
} }
return ''; return '';
} }
log.appendChild(document.createElementNS(xhtml_ns, "section")); log.appendChild(document.createElementNS(xhtml_ns, "section"));
var assertions = has_assertions(); var assertions = has_assertions();
var html = "<h2>Details</h2><table id='results' " + (assertions ? "class='assertions'" : "" ) + ">" var html = "<h2>Details</h2><table id='results' " + (assertions ? "class='assertions'" : "" ) + ">"

View File

@ -7,13 +7,19 @@ from __future__ import unicode_literals
import subprocess import subprocess
repo = "https://dvcs.w3.org/hg/resources" repo = "https://github.com/w3c/testharness.js"
dest = "resources-upstream" dest = "resources-upstream"
files = ["testharness.js", "testharness.css", "idlharness.js", "WebIDLParser.js"] files = [{"f":"testharness.js"},
{"f":"testharness.css"},
{"f":"idlharness.js"},
{"d":"webidl2/lib/webidl2.js", "f":"WebIDLParser.js"}]
subprocess.check_call(["hg", "clone", repo, dest]) subprocess.check_call(["git", "clone", repo, dest])
subprocess.check_call(["git", "submodule", "init"], cwd=dest)
subprocess.check_call(["git", "submodule", "update"], cwd=dest)
for f in files: for f in files:
subprocess.check_call(["cp", "%s/%s" % (dest, f), f]) path = f["d"] if "d" in f else f["f"]
subprocess.check_call(["hg", "add", f]) subprocess.check_call(["cp", "%s/%s" % (dest, path), f["f"]])
subprocess.check_call(["hg", "add", f["f"]])
subprocess.check_call(["rm", "-rf", dest]) subprocess.check_call(["rm", "-rf", dest])