<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[213081] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/213081">213081</a></dd>
<dt>Author</dt> <dd>jiewen_tan@apple.com</dd>
<dt>Date</dt> <dd>2017-02-27 11:01:13 -0800 (Mon, 27 Feb 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[CredentialManagement] Add IDL definitions for Credential, SiteBoundCredential, and PasswordCredential
https://bugs.webkit.org/show_bug.cgi?id=168616
&lt;rdar://problem/30167149&gt;

Reviewed by Daniel Bates.

Source/WebCore:

This patch adds IDL definitions for:
1. Credential(https://w3c.github.io/webappsec-credential-management/#interfaces-credential-types-credential),
2. SiteBoundCredential(https://w3c.github.io/webappsec-credential-management/#interfaces-credential-types-siteboundcredential), and
3. PasswordCredential(https://w3c.github.io/webappsec-credential-management/#interfaces-credential-types-passwordcredential).

Test: credentials/idlharness.html

* CMakeLists.txt:
* DerivedSources.make:
* Modules/credentials/BasicCredential.cpp: Added.
(WebCore::BasicCredential::BasicCredential):
(WebCore::BasicCredential::~BasicCredential):
(WebCore::BasicCredential::type):
* Modules/credentials/BasicCredential.h: Added.
(WebCore::BasicCredential::id):
* Modules/credentials/BasicCredential.idl: Added.
* Modules/credentials/CredentialData.h: Added.
* Modules/credentials/CredentialData.idl: Added.
* Modules/credentials/PasswordCredential.cpp: Added.
(WebCore::PasswordCredential::PasswordCredential):
(WebCore::PasswordCredential::PasswordCredential):
Dummy constructors for now.
* Modules/credentials/PasswordCredential.h: Added.
(WebCore::PasswordCredential::create):
(WebCore::PasswordCredential::create):
(WebCore::PasswordCredential::setIdName):
(WebCore::PasswordCredential::idName):
(WebCore::PasswordCredential::setPasswordName):
(WebCore::PasswordCredential::passwordName):
(WebCore::PasswordCredential::setAdditionalData):
(WebCore::PasswordCredential::additionalData):
* Modules/credentials/PasswordCredential.idl: Added.
* Modules/credentials/SiteBoundCredential.cpp: Added.
(WebCore::SiteBoundCredential::SiteBoundCredential):
(WebCore::SiteBoundCredential::~SiteBoundCredential):
* Modules/credentials/SiteBoundCredential.h: Added.
(WebCore::SiteBoundCredential::name):
(WebCore::SiteBoundCredential::iconURL):
(WebCore::SiteBoundCredential::setOrigin):
(WebCore::SiteBoundCredential::origin):
* Modules/credentials/SiteBoundCredential.idl: Added.
* Modules/credentials/SiteBoundCredentialData.h: Added.
* Modules/credentials/SiteBoundCredentialData.idl: Added.
* WebCore.xcodeproj/project.pbxproj:

LayoutTests:

* credentials/idlharness-expected.txt: Added.
* credentials/idlharness.html: Added.
* platform/mac-elcapitan/js/dom/global-constructors-attributes-expected.txt:
* platform/mac-wk1/js/dom/global-constructors-attributes-expected.txt:
* platform/mac-yosemite/js/dom/global-constructors-attributes-expected.txt:
* platform/mac/js/dom/global-constructors-attributes-expected.txt:
* resources/WebIDLParser.js: Added.
* resources/idlharness.js: Renamed from LayoutTests/imported/w3c/resources/idlharness.js.
Removed LayoutTests/imported/w3c/resources/idlharness.js since it is not needed any more.
Added resources/idlharness.js for idl harness.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformmacjsdomglobalconstructorsattributesexpectedtxt">trunk/LayoutTests/platform/mac/js/dom/global-constructors-attributes-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacelcapitanjsdomglobalconstructorsattributesexpectedtxt">trunk/LayoutTests/platform/mac-elcapitan/js/dom/global-constructors-attributes-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacwk1jsdomglobalconstructorsattributesexpectedtxt">trunk/LayoutTests/platform/mac-wk1/js/dom/global-constructors-attributes-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacyosemitejsdomglobalconstructorsattributesexpectedtxt">trunk/LayoutTests/platform/mac-yosemite/js/dom/global-constructors-attributes-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreDerivedSourcesmake">trunk/Source/WebCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/LayoutTests/credentials/</li>
<li><a href="#trunkLayoutTestscredentialsidlharnessexpectedtxt">trunk/LayoutTests/credentials/idlharness-expected.txt</a></li>
<li><a href="#trunkLayoutTestscredentialsidlharnesshtml">trunk/LayoutTests/credentials/idlharness.html</a></li>
<li><a href="#trunkLayoutTestsresourcesWebIDLParserjs">trunk/LayoutTests/resources/WebIDLParser.js</a></li>
<li><a href="#trunkLayoutTestsresourcesidlharnessjs">trunk/LayoutTests/resources/idlharness.js</a></li>
<li>trunk/Source/WebCore/Modules/credentials/</li>
<li><a href="#trunkSourceWebCoreModulescredentialsBasicCredentialcpp">trunk/Source/WebCore/Modules/credentials/BasicCredential.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsBasicCredentialh">trunk/Source/WebCore/Modules/credentials/BasicCredential.h</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsBasicCredentialidl">trunk/Source/WebCore/Modules/credentials/BasicCredential.idl</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsCredentialDatah">trunk/Source/WebCore/Modules/credentials/CredentialData.h</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsCredentialDataidl">trunk/Source/WebCore/Modules/credentials/CredentialData.idl</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsPasswordCredentialcpp">trunk/Source/WebCore/Modules/credentials/PasswordCredential.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsPasswordCredentialh">trunk/Source/WebCore/Modules/credentials/PasswordCredential.h</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsPasswordCredentialidl">trunk/Source/WebCore/Modules/credentials/PasswordCredential.idl</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsSiteBoundCredentialcpp">trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsSiteBoundCredentialh">trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.h</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsSiteBoundCredentialidl">trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.idl</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsSiteBoundCredentialDatah">trunk/Source/WebCore/Modules/credentials/SiteBoundCredentialData.h</a></li>
<li><a href="#trunkSourceWebCoreModulescredentialsSiteBoundCredentialDataidl">trunk/Source/WebCore/Modules/credentials/SiteBoundCredentialData.idl</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsimportedw3cresourcesidlharnessjs">trunk/LayoutTests/imported/w3c/resources/idlharness.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/LayoutTests/ChangeLog        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2017-02-27  Jiewen Tan  &lt;jiewen_tan@apple.com&gt;
+
+        [CredentialManagement] Add IDL definitions for Credential, SiteBoundCredential, and PasswordCredential
+        https://bugs.webkit.org/show_bug.cgi?id=168616
+        &lt;rdar://problem/30167149&gt;
+
+        Reviewed by Daniel Bates.
+
+        * credentials/idlharness-expected.txt: Added.
+        * credentials/idlharness.html: Added.
+        * platform/mac-elcapitan/js/dom/global-constructors-attributes-expected.txt:
+        * platform/mac-wk1/js/dom/global-constructors-attributes-expected.txt:
+        * platform/mac-yosemite/js/dom/global-constructors-attributes-expected.txt:
+        * platform/mac/js/dom/global-constructors-attributes-expected.txt:
+        * resources/WebIDLParser.js: Added.
+        * resources/idlharness.js: Renamed from LayoutTests/imported/w3c/resources/idlharness.js.
+        Removed LayoutTests/imported/w3c/resources/idlharness.js since it is not needed any more.
+        Added resources/idlharness.js for idl harness.
+
</ins><span class="cx"> 2017-02-27  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebRTC] Fix remote audio rendering
</span></span></pre></div>
<a id="trunkLayoutTestscredentialsidlharnessexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/credentials/idlharness-expected.txt (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/credentials/idlharness-expected.txt                                (rev 0)
+++ trunk/LayoutTests/credentials/idlharness-expected.txt        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+idlharness test
+
+This test validates the WebIDL included in the Credential Management API.
+
+
+PASS Credential interface: existence and properties of interface object 
+PASS Credential interface object length 
+PASS Credential interface object name 
+PASS Credential interface: existence and properties of interface prototype object 
+PASS Credential interface: existence and properties of interface prototype object's &quot;constructor&quot; property 
+PASS Credential interface: attribute id 
+PASS Credential interface: attribute type 
+PASS SiteBoundCredential interface: existence and properties of interface object 
+PASS SiteBoundCredential interface object length 
+PASS SiteBoundCredential interface object name 
+PASS SiteBoundCredential interface: existence and properties of interface prototype object 
+PASS SiteBoundCredential interface: existence and properties of interface prototype object's &quot;constructor&quot; property 
+PASS SiteBoundCredential interface: attribute name 
+PASS SiteBoundCredential interface: attribute iconURL 
+PASS PasswordCredential interface: existence and properties of interface object 
+PASS PasswordCredential interface object length 
+PASS PasswordCredential interface object name 
+PASS PasswordCredential interface: existence and properties of interface prototype object 
+PASS PasswordCredential interface: existence and properties of interface prototype object's &quot;constructor&quot; property 
+PASS PasswordCredential interface: attribute idName 
+PASS PasswordCredential interface: attribute passwordName 
+PASS PasswordCredential interface: attribute additionalData 
+PASS PasswordCredential must be primary interface of new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; }) 
+PASS Stringification of new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; }) 
+PASS PasswordCredential interface: new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; }) must inherit property &quot;idName&quot; with the proper type (0) 
+PASS PasswordCredential interface: new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; }) must inherit property &quot;passwordName&quot; with the proper type (1) 
+PASS PasswordCredential interface: new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; }) must inherit property &quot;additionalData&quot; with the proper type (2) 
+PASS SiteBoundCredential interface: new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; }) must inherit property &quot;name&quot; with the proper type (0) 
+PASS SiteBoundCredential interface: new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; }) must inherit property &quot;iconURL&quot; with the proper type (1) 
+PASS Credential interface: new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; }) must inherit property &quot;id&quot; with the proper type (0) 
+PASS Credential interface: new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; }) must inherit property &quot;type&quot; with the proper type (1) 
+
</ins></span></pre></div>
<a id="trunkLayoutTestscredentialsidlharnesshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/credentials/idlharness.html (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/credentials/idlharness.html                                (rev 0)
+++ trunk/LayoutTests/credentials/idlharness.html        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,76 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;script src=&quot;../resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/WebIDLParser.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/idlharness.js&quot;&gt;&lt;/script&gt;
+
+&lt;h1&gt;idlharness test&lt;/h1&gt;
+&lt;p&gt;This test validates the WebIDL included in the Credential Management API.&lt;/p&gt;
+
+&lt;script type=&quot;text/plain&quot; class=&quot;untested-idl&quot;&gt;
+interface Window {};
+&lt;/script&gt;
+
+&lt;script type=&quot;text/plain&quot; class=&quot;idl&quot;&gt;
+// 3.1.1 Credential
+
+dictionary CredentialData {
+  required USVString id;
+};
+
+[SecureContext] interface Credential {
+  readonly attribute USVString id;
+  readonly attribute DOMString type;
+};
+
+// No Transferable at this moment
+// Credential implements Transferable;
+
+dictionary SiteBoundCredentialData : CredentialData {
+  USVString name;
+  USVString iconURL;
+};
+
+[SecureContext] interface SiteBoundCredential : Credential {
+  readonly attribute USVString name;
+  readonly attribute USVString iconURL;
+};
+
+// 3.1.3 PasswordCredential
+
+dictionary PasswordCredentialData : SiteBoundCredentialData {
+  required USVString password;
+};
+
+typedef (FormData or URLSearchParams) CredentialBodyType;
+
+[Constructor(PasswordCredentialData data),
+ Constructor(HTMLFormElement form),
+ Exposed=Window,
+ SecureContext]
+interface PasswordCredential : SiteBoundCredential {
+  attribute USVString idName;
+  attribute USVString passwordName;
+
+  attribute CredentialBodyType? additionalData;
+};
+
+&lt;/script&gt;
+
+&lt;script&gt;
+function select(selector) {
+  return [].slice.call(document.querySelectorAll(selector))
+    .map(function(e) { return e.textContent; })
+    .join('\n\n');
+}
+
+var idl = select('.idl')
+var untested = select('.untested-idl');
+var idl_array = new IdlArray();
+idl_array.add_untested_idls(untested);
+idl_array.add_idls(idl);
+idl_array.add_objects({
+  PasswordCredential: ['new PasswordCredential({ password: &quot;12345&quot;, id: &quot;12345&quot; })'],
+});
+idl_array.test();
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cresourcesidlharnessjs"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/imported/w3c/resources/idlharness.js (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/resources/idlharness.js        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/LayoutTests/imported/w3c/resources/idlharness.js        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -1,1850 +0,0 @@
</span><del>-/*
-Distributed under both the W3C Test Suite License [1] and the W3C
-3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
-policies and contribution forms [3].
-
-[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
-[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
-[3] http://www.w3.org/2004/10/27-testcases
-*/
-
-/* For user documentation see docs/idlharness.md */
-
-/**
- * Notes for people who want to edit this file (not just use it as a library):
- *
- * Most of the interesting stuff happens in the derived classes of IdlObject,
- * especially IdlInterface.  The entry point for all IdlObjects is .test(),
- * which is called by IdlArray.test().  An IdlObject is conceptually just
- * &quot;thing we want to run tests on&quot;, and an IdlArray is an array of IdlObjects
- * with some additional data thrown in.
- *
- * The object model is based on what WebIDLParser.js produces, which is in turn
- * based on its pegjs grammar.  If you want to figure out what properties an
- * object will have from WebIDLParser.js, the best way is to look at the
- * grammar:
- *
- *   https://github.com/darobin/webidl.js/blob/master/lib/grammar.peg
- *
- * So for instance:
- *
- *   // interface definition
- *   interface
- *       =   extAttrs:extendedAttributeList? S? &quot;interface&quot; S name:identifier w herit:ifInheritance? w &quot;{&quot; w mem:ifMember* w &quot;}&quot; w &quot;;&quot; w
- *           { return { type: &quot;interface&quot;, name: name, inheritance: herit, members: mem, extAttrs: extAttrs }; }
- *
- * This means that an &quot;interface&quot; object will have a .type property equal to
- * the string &quot;interface&quot;, a .name property equal to the identifier that the
- * parser found, an .inheritance property equal to either null or the result of
- * the &quot;ifInheritance&quot; production found elsewhere in the grammar, and so on.
- * After each grammatical production is a JavaScript function in curly braces
- * that gets called with suitable arguments and returns some JavaScript value.
- *
- * (Note that the version of WebIDLParser.js we use might sometimes be
- * out-of-date or forked.)
- *
- * The members and methods of the classes defined by this file are all at least
- * briefly documented, hopefully.
- */
-(function(){
-&quot;use strict&quot;;
-/// Helpers ///
-function constValue (cnt) {
-    if (cnt.type === &quot;null&quot;) return null;
-    if (cnt.type === &quot;NaN&quot;) return NaN;
-    if (cnt.type === &quot;Infinity&quot;) return cnt.negative ? -Infinity : Infinity;
-    return cnt.value;
-}
-
-function minOverloadLength(overloads) {
-    if (!overloads.length) {
-        return 0;
-    }
-
-    return overloads.map(function(attr) {
-        return attr.arguments ? attr.arguments.filter(function(arg) {
-            return !arg.optional &amp;&amp; !arg.variadic;
-        }).length : 0;
-    })
-    .reduce(function(m, n) { return Math.min(m, n); });
-}
-
-function throwOrReject(a_test, operation, fn, obj, args,  message, cb) {
-    if (operation.idlType.generic !== &quot;Promise&quot;) {
-        assert_throws(new TypeError(), function() {
-            fn.apply(obj, args);
-        }, message);
-        cb();
-    } else {
-        try {
-            promise_rejects(a_test, new TypeError(), fn.apply(obj, args)).then(cb, cb);
-        } catch (e){
-            a_test.step(function() {
-                assert_unreached(&quot;Throws \&quot;&quot; + e + &quot;\&quot; instead of rejecting promise&quot;);
-                cb();
-            });
-        }
-    }
-}
-
-function awaitNCallbacks(n, cb, ctx) {
-    var counter = 0;
-    return function() {
-        counter++;
-        if (counter &gt;= n) {
-            cb();
-        }
-    };
-}
-
-var fround = (function(){
-    if (Math.fround) return Math.fround;
-
-    var arr = new Float32Array(1);
-    return function fround(n) {
-        arr[0] = n;
-        return arr[0];
-    };
-})();
-
-/// IdlArray ///
-// Entry point
-self.IdlArray = function()
-//@{
-{
-    /**
-     * A map from strings to the corresponding named IdlObject, such as
-     * IdlInterface or IdlException.  These are the things that test() will run
-     * tests on.
-     */
-    this.members = {};
-
-    /**
-     * A map from strings to arrays of strings.  The keys are interface or
-     * exception names, and are expected to also exist as keys in this.members
-     * (otherwise they'll be ignored).  This is populated by add_objects() --
-     * see documentation at the start of the file.  The actual tests will be
-     * run by calling this.members[name].test_object(obj) for each obj in
-     * this.objects[name].  obj is a string that will be eval'd to produce a
-     * JavaScript value, which is supposed to be an object implementing the
-     * given IdlObject (interface, exception, etc.).
-     */
-    this.objects = {};
-
-    /**
-     * When adding multiple collections of IDLs one at a time, an earlier one
-     * might contain a partial interface or implements statement that depends
-     * on a later one.  Save these up and handle them right before we run
-     * tests.
-     *
-     * .partials is simply an array of objects from WebIDLParser.js'
-     * &quot;partialinterface&quot; production.  .implements maps strings to arrays of
-     * strings, such that
-     *
-     *   A implements B;
-     *   A implements C;
-     *   D implements E;
-     *
-     * results in { A: [&quot;B&quot;, &quot;C&quot;], D: [&quot;E&quot;] }.
-     */
-    this.partials = [];
-    this[&quot;implements&quot;] = {};
-};
-
-//@}
-IdlArray.prototype.add_idls = function(raw_idls)
-//@{
-{
-    /** Entry point.  See documentation at beginning of file. */
-    this.internal_add_idls(WebIDL2.parse(raw_idls));
-};
-
-//@}
-IdlArray.prototype.add_untested_idls = function(raw_idls)
-//@{
-{
-    /** Entry point.  See documentation at beginning of file. */
-    var parsed_idls = WebIDL2.parse(raw_idls);
-    for (var i = 0; i &lt; parsed_idls.length; i++)
-    {
-        parsed_idls[i].untested = true;
-        if (&quot;members&quot; in parsed_idls[i])
-        {
-            for (var j = 0; j &lt; parsed_idls[i].members.length; j++)
-            {
-                parsed_idls[i].members[j].untested = true;
-            }
-        }
-    }
-    this.internal_add_idls(parsed_idls);
-};
-
-//@}
-IdlArray.prototype.internal_add_idls = function(parsed_idls)
-//@{
-{
-    /**
-     * Internal helper called by add_idls() and add_untested_idls().
-     * parsed_idls is an array of objects that come from WebIDLParser.js's
-     * &quot;definitions&quot; production.  The add_untested_idls() entry point
-     * additionally sets an .untested property on each object (and its
-     * .members) so that they'll be skipped by test() -- they'll only be
-     * used for base interfaces of tested interfaces, return types, etc.
-     */
-    parsed_idls.forEach(function(parsed_idl)
-    {
-        if (parsed_idl.type == &quot;interface&quot; &amp;&amp; parsed_idl.partial)
-        {
-            this.partials.push(parsed_idl);
-            return;
-        }
-
-        if (parsed_idl.type == &quot;implements&quot;)
-        {
-            if (!(parsed_idl.target in this[&quot;implements&quot;]))
-            {
-                this[&quot;implements&quot;][parsed_idl.target] = [];
-            }
-            this[&quot;implements&quot;][parsed_idl.target].push(parsed_idl[&quot;implements&quot;]);
-            return;
-        }
-
-        parsed_idl.array = this;
-        if (parsed_idl.name in this.members)
-        {
-            throw &quot;Duplicate identifier &quot; + parsed_idl.name;
-        }
-        switch(parsed_idl.type)
-        {
-        case &quot;interface&quot;:
-            this.members[parsed_idl.name] =
-                new IdlInterface(parsed_idl, /* is_callback = */ false);
-            break;
-
-        case &quot;dictionary&quot;:
-            // Nothing to test, but we need the dictionary info around for type
-            // checks
-            this.members[parsed_idl.name] = new IdlDictionary(parsed_idl);
-            break;
-
-        case &quot;typedef&quot;:
-            this.members[parsed_idl.name] = new IdlTypedef(parsed_idl);
-            break;
-
-        case &quot;callback&quot;:
-            // TODO
-            console.log(&quot;callback not yet supported&quot;);
-            break;
-
-        case &quot;enum&quot;:
-            this.members[parsed_idl.name] = new IdlEnum(parsed_idl);
-            break;
-
-        case &quot;callback interface&quot;:
-            this.members[parsed_idl.name] =
-                new IdlInterface(parsed_idl, /* is_callback = */ true);
-            break;
-
-        default:
-            throw parsed_idl.name + &quot;: &quot; + parsed_idl.type + &quot; not yet supported&quot;;
-        }
-    }.bind(this));
-};
-
-//@}
-IdlArray.prototype.add_objects = function(dict)
-//@{
-{
-    /** Entry point.  See documentation at beginning of file. */
-    for (var k in dict)
-    {
-        if (k in this.objects)
-        {
-            this.objects[k] = this.objects[k].concat(dict[k]);
-        }
-        else
-        {
-            this.objects[k] = dict[k];
-        }
-    }
-};
-
-//@}
-IdlArray.prototype.prevent_multiple_testing = function(name)
-//@{
-{
-    /** Entry point.  See documentation at beginning of file. */
-    this.members[name].prevent_multiple_testing = true;
-};
-
-//@}
-IdlArray.prototype.recursively_get_implements = function(interface_name)
-//@{
-{
-    /**
-     * Helper function for test().  Returns an array of things that implement
-     * interface_name, so if the IDL contains
-     *
-     *   A implements B;
-     *   B implements C;
-     *   B implements D;
-     *
-     * then recursively_get_implements(&quot;A&quot;) should return [&quot;B&quot;, &quot;C&quot;, &quot;D&quot;].
-     */
-    var ret = this[&quot;implements&quot;][interface_name];
-    if (ret === undefined)
-    {
-        return [];
-    }
-    for (var i = 0; i &lt; this[&quot;implements&quot;][interface_name].length; i++)
-    {
-        ret = ret.concat(this.recursively_get_implements(ret[i]));
-        if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
-        {
-            throw &quot;Circular implements statements involving &quot; + ret[i];
-        }
-    }
-    return ret;
-};
-
-function exposed_in(globals) {
-    if ('document' in self) {
-        return globals.indexOf(&quot;Window&quot;) &gt;= 0;
-    }
-    if ('DedicatedWorkerGlobalScope' in self &amp;&amp;
-        self instanceof DedicatedWorkerGlobalScope) {
-        return globals.indexOf(&quot;Worker&quot;) &gt;= 0 ||
-               globals.indexOf(&quot;DedicatedWorker&quot;) &gt;= 0;
-    }
-    if ('SharedWorkerGlobalScope' in self &amp;&amp;
-        self instanceof SharedWorkerGlobalScope) {
-        return globals.indexOf(&quot;Worker&quot;) &gt;= 0 ||
-               globals.indexOf(&quot;SharedWorker&quot;) &gt;= 0;
-    }
-    if ('ServiceWorkerGlobalScope' in self &amp;&amp;
-        self instanceof ServiceWorkerGlobalScope) {
-        return globals.indexOf(&quot;Worker&quot;) &gt;= 0 ||
-               globals.indexOf(&quot;ServiceWorker&quot;) &gt;= 0;
-    }
-    throw &quot;Unexpected global object&quot;;
-}
-
-//@}
-IdlArray.prototype.test = function()
-//@{
-{
-    /** Entry point.  See documentation at beginning of file. */
-
-    // First merge in all the partial interfaces and implements statements we
-    // encountered.
-    this.partials.forEach(function(parsed_idl)
-    {
-        if (!(parsed_idl.name in this.members)
-        || !(this.members[parsed_idl.name] instanceof IdlInterface))
-        {
-            throw &quot;Partial interface &quot; + parsed_idl.name + &quot; with no original interface&quot;;
-        }
-        if (parsed_idl.extAttrs)
-        {
-            parsed_idl.extAttrs.forEach(function(extAttr)
-            {
-                this.members[parsed_idl.name].extAttrs.push(extAttr);
-            }.bind(this));
-        }
-        parsed_idl.members.forEach(function(member)
-        {
-            this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member));
-        }.bind(this));
-    }.bind(this));
-    this.partials = [];
-
-    for (var lhs in this[&quot;implements&quot;])
-    {
-        this.recursively_get_implements(lhs).forEach(function(rhs)
-        {
-            var errStr = lhs + &quot; implements &quot; + rhs + &quot;, but &quot;;
-            if (!(lhs in this.members)) throw errStr + lhs + &quot; is undefined.&quot;;
-            if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + &quot; is not an interface.&quot;;
-            if (!(rhs in this.members)) throw errStr + rhs + &quot; is undefined.&quot;;
-            if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + &quot; is not an interface.&quot;;
-            this.members[rhs].members.forEach(function(member)
-            {
-                this.members[lhs].members.push(new IdlInterfaceMember(member));
-            }.bind(this));
-        }.bind(this));
-    }
-    this[&quot;implements&quot;] = {};
-
-    Object.getOwnPropertyNames(this.members).forEach(function(memberName) {
-        var member = this.members[memberName];
-        if (!(member instanceof IdlInterface)) {
-            return;
-        }
-
-        var exposed = member.extAttrs.filter(function(a) { return a.name == &quot;Exposed&quot; });
-        if (exposed.length &gt; 1) {
-            throw &quot;Unexpected Exposed extended attributes on &quot; + memberName + &quot;: &quot; + exposed;
-        }
-
-        var globals = exposed.length === 1
-                    ? exposed[0].rhs.value
-                    : [&quot;Window&quot;];
-        member.exposed = exposed_in(globals);
-    }.bind(this));
-
-    // Now run test() on every member, and test_object() for every object.
-    for (var name in this.members)
-    {
-        this.members[name].test();
-        if (name in this.objects)
-        {
-            this.objects[name].forEach(function(str)
-            {
-                this.members[name].test_object(str);
-            }.bind(this));
-        }
-    }
-};
-
-//@}
-IdlArray.prototype.assert_type_is = function(value, type)
-//@{
-{
-    /**
-     * Helper function that tests that value is an instance of type according
-     * to the rules of WebIDL.  value is any JavaScript value, and type is an
-     * object produced by WebIDLParser.js' &quot;type&quot; production.  That production
-     * is fairly elaborate due to the complexity of WebIDL's types, so it's
-     * best to look at the grammar to figure out what properties it might have.
-     */
-    if (type.idlType == &quot;any&quot;)
-    {
-        // No assertions to make
-        return;
-    }
-
-    if (type.nullable &amp;&amp; value === null)
-    {
-        // This is fine
-        return;
-    }
-
-    if (type.array)
-    {
-        // TODO: not supported yet
-        return;
-    }
-
-    if (type.sequence)
-    {
-        assert_true(Array.isArray(value), &quot;is not array&quot;);
-        if (!value.length)
-        {
-            // Nothing we can do.
-            return;
-        }
-        this.assert_type_is(value[0], type.idlType.idlType);
-        return;
-    }
-
-    type = type.idlType;
-
-    switch(type)
-    {
-        case &quot;void&quot;:
-            assert_equals(value, undefined);
-            return;
-
-        case &quot;boolean&quot;:
-            assert_equals(typeof value, &quot;boolean&quot;);
-            return;
-
-        case &quot;byte&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
-            assert_true(-128 &lt;= value &amp;&amp; value &lt;= 127, &quot;byte &quot; + value + &quot; not in range [-128, 127]&quot;);
-            return;
-
-        case &quot;octet&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
-            assert_true(0 &lt;= value &amp;&amp; value &lt;= 255, &quot;octet &quot; + value + &quot; not in range [0, 255]&quot;);
-            return;
-
-        case &quot;short&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
-            assert_true(-32768 &lt;= value &amp;&amp; value &lt;= 32767, &quot;short &quot; + value + &quot; not in range [-32768, 32767]&quot;);
-            return;
-
-        case &quot;unsigned short&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
-            assert_true(0 &lt;= value &amp;&amp; value &lt;= 65535, &quot;unsigned short &quot; + value + &quot; not in range [0, 65535]&quot;);
-            return;
-
-        case &quot;long&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
-            assert_true(-2147483648 &lt;= value &amp;&amp; value &lt;= 2147483647, &quot;long &quot; + value + &quot; not in range [-2147483648, 2147483647]&quot;);
-            return;
-
-        case &quot;unsigned long&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
-            assert_true(0 &lt;= value &amp;&amp; value &lt;= 4294967295, &quot;unsigned long &quot; + value + &quot; not in range [0, 4294967295]&quot;);
-            return;
-
-        case &quot;long long&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            return;
-
-        case &quot;unsigned long long&quot;:
-        case &quot;DOMTimeStamp&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_true(0 &lt;= value, &quot;unsigned long long is negative&quot;);
-            return;
-
-        case &quot;float&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_equals(value, fround(value), &quot;float rounded to 32-bit float should be itself&quot;);
-            assert_not_equals(value, Infinity);
-            assert_not_equals(value, -Infinity);
-            assert_not_equals(value, NaN);
-            return;
-
-        case &quot;DOMHighResTimeStamp&quot;:
-        case &quot;double&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_not_equals(value, Infinity);
-            assert_not_equals(value, -Infinity);
-            assert_not_equals(value, NaN);
-            return;
-
-        case &quot;unrestricted float&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            assert_equals(value, fround(value), &quot;unrestricted float rounded to 32-bit float should be itself&quot;);
-            return;
-
-        case &quot;unrestricted double&quot;:
-            assert_equals(typeof value, &quot;number&quot;);
-            return;
-
-        case &quot;DOMString&quot;:
-            assert_equals(typeof value, &quot;string&quot;);
-            return;
-
-        case &quot;ByteString&quot;:
-            assert_equals(typeof value, &quot;string&quot;);
-            assert_regexp_match(value, /^[\x00-\x7F]*$/);
-            return;
-
-        case &quot;USVString&quot;:
-            assert_equals(typeof value, &quot;string&quot;);
-            assert_regexp_match(value, /^([\x00-\ud7ff\ue000-\uffff]|[\ud800-\udbff][\udc00-\udfff])*$/);
-            return;
-
-        case &quot;object&quot;:
-            assert_true(typeof value == &quot;object&quot; || typeof value == &quot;function&quot;, &quot;wrong type: not object or function&quot;);
-            return;
-    }
-
-    if (!(type in this.members))
-    {
-        throw &quot;Unrecognized type &quot; + type;
-    }
-
-    if (this.members[type] instanceof IdlInterface)
-    {
-        // We don't want to run the full
-        // IdlInterface.prototype.test_instance_of, because that could result
-        // in an infinite loop.  TODO: This means we don't have tests for
-        // NoInterfaceObject interfaces, and we also can't test objects that
-        // come from another self.
-        assert_true(typeof value == &quot;object&quot; || typeof value == &quot;function&quot;, &quot;wrong type: not object or function&quot;);
-        if (value instanceof Object
-        &amp;&amp; !this.members[type].has_extended_attribute(&quot;NoInterfaceObject&quot;)
-        &amp;&amp; type in self)
-        {
-            assert_true(value instanceof self[type], &quot;not instanceof &quot; + type);
-        }
-    }
-    else if (this.members[type] instanceof IdlEnum)
-    {
-        assert_equals(typeof value, &quot;string&quot;);
-    }
-    else if (this.members[type] instanceof IdlDictionary)
-    {
-        // TODO: Test when we actually have something to test this on
-    }
-    else if (this.members[type] instanceof IdlTypedef)
-    {
-        // TODO: Test when we actually have something to test this on
-    }
-    else
-    {
-        throw &quot;Type &quot; + type + &quot; isn't an interface or dictionary&quot;;
-    }
-};
-//@}
-
-/// IdlObject ///
-function IdlObject() {}
-IdlObject.prototype.test = function()
-//@{
-{
-    /**
-     * By default, this does nothing, so no actual tests are run for IdlObjects
-     * that don't define any (e.g., IdlDictionary at the time of this writing).
-     */
-};
-
-//@}
-IdlObject.prototype.has_extended_attribute = function(name)
-//@{
-{
-    /**
-     * This is only meaningful for things that support extended attributes,
-     * such as interfaces, exceptions, and members.
-     */
-    return this.extAttrs.some(function(o)
-    {
-        return o.name == name;
-    });
-};
-
-//@}
-
-/// IdlDictionary ///
-// Used for IdlArray.prototype.assert_type_is
-function IdlDictionary(obj)
-//@{
-{
-    /**
-     * obj is an object produced by the WebIDLParser.js &quot;dictionary&quot;
-     * production.
-     */
-
-    /** Self-explanatory. */
-    this.name = obj.name;
-
-    /** An array of objects produced by the &quot;dictionaryMember&quot; production. */
-    this.members = obj.members;
-
-    /**
-     * The name (as a string) of the dictionary type we inherit from, or null
-     * if there is none.
-     */
-    this.base = obj.inheritance;
-}
-
-//@}
-IdlDictionary.prototype = Object.create(IdlObject.prototype);
-
-/// IdlInterface ///
-function IdlInterface(obj, is_callback) {
-    /**
-     * obj is an object produced by the WebIDLParser.js &quot;interface&quot; production.
-     */
-
-    /** Self-explanatory. */
-    this.name = obj.name;
-
-    /** A back-reference to our IdlArray. */
-    this.array = obj.array;
-
-    /**
-     * An indicator of whether we should run tests on the interface object and
-     * interface prototype object. Tests on members are controlled by .untested
-     * on each member, not this.
-     */
-    this.untested = obj.untested;
-
-    /** An array of objects produced by the &quot;ExtAttr&quot; production. */
-    this.extAttrs = obj.extAttrs;
-
-    /** An array of IdlInterfaceMembers. */
-    this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); });
-    if (this.has_extended_attribute(&quot;Unforgeable&quot;)) {
-        this.members
-            .filter(function(m) { return !m[&quot;static&quot;] &amp;&amp; (m.type == &quot;attribute&quot; || m.type == &quot;operation&quot;); })
-            .forEach(function(m) { return m.isUnforgeable = true; });
-    }
-
-    /**
-     * The name (as a string) of the type we inherit from, or null if there is
-     * none.
-     */
-    this.base = obj.inheritance;
-
-    this._is_callback = is_callback;
-}
-IdlInterface.prototype = Object.create(IdlObject.prototype);
-IdlInterface.prototype.is_callback = function()
-//@{
-{
-    return this._is_callback;
-};
-//@}
-
-IdlInterface.prototype.has_constants = function()
-//@{
-{
-    return this.members.some(function(member) {
-        return member.type === &quot;const&quot;;
-    });
-};
-//@}
-
-IdlInterface.prototype.is_global = function()
-//@{
-{
-    return this.extAttrs.some(function(attribute) {
-        return attribute.name === &quot;Global&quot; ||
-               attribute.name === &quot;PrimaryGlobal&quot;;
-    });
-};
-//@}
-
-IdlInterface.prototype.test = function()
-//@{
-{
-    if (this.has_extended_attribute(&quot;NoInterfaceObject&quot;))
-    {
-        // No tests to do without an instance.  TODO: We should still be able
-        // to run tests on the prototype object, if we obtain one through some
-        // other means.
-        return;
-    }
-
-    if (!this.exposed) {
-        test(function() {
-            assert_false(this.name in self);
-        }.bind(this), this.name + &quot; interface: existence and properties of interface object&quot;);
-        return;
-    }
-
-    if (!this.untested)
-    {
-        // First test things to do with the exception/interface object and
-        // exception/interface prototype object.
-        this.test_self();
-    }
-    // Then test things to do with its members (constants, fields, attributes,
-    // operations, . . .).  These are run even if .untested is true, because
-    // members might themselves be marked as .untested.  This might happen to
-    // interfaces if the interface itself is untested but a partial interface
-    // that extends it is tested -- then the interface itself and its initial
-    // members will be marked as untested, but the members added by the partial
-    // interface are still tested.
-    this.test_members();
-};
-//@}
-
-IdlInterface.prototype.test_self = function()
-//@{
-{
-    test(function()
-    {
-        // This function tests WebIDL as of 2015-01-13.
-
-        // &quot;For every interface that is exposed in a given ECMAScript global
-        // environment and:
-        // * is a callback interface that has constants declared on it, or
-        // * is a non-callback interface that is not declared with the
-        //   [NoInterfaceObject] extended attribute,
-        // a corresponding property MUST exist on the ECMAScript global object.
-        // The name of the property is the identifier of the interface, and its
-        // value is an object called the interface object.
-        // The property has the attributes { [[Writable]]: true,
-        // [[Enumerable]]: false, [[Configurable]]: true }.&quot;
-        if (this.is_callback() &amp;&amp; !this.has_constants()) {
-            return;
-        }
-
-        // TODO: Should we test here that the property is actually writable
-        // etc., or trust getOwnPropertyDescriptor?
-        assert_own_property(self, this.name,
-                            &quot;self does not have own property &quot; + format_value(this.name));
-        var desc = Object.getOwnPropertyDescriptor(self, this.name);
-        assert_false(&quot;get&quot; in desc, &quot;self's property &quot; + format_value(this.name) + &quot; has getter&quot;);
-        assert_false(&quot;set&quot; in desc, &quot;self's property &quot; + format_value(this.name) + &quot; has setter&quot;);
-        assert_true(desc.writable, &quot;self's property &quot; + format_value(this.name) + &quot; is not writable&quot;);
-        assert_false(desc.enumerable, &quot;self's property &quot; + format_value(this.name) + &quot; is enumerable&quot;);
-        assert_true(desc.configurable, &quot;self's property &quot; + format_value(this.name) + &quot; is not configurable&quot;);
-
-        if (this.is_callback()) {
-            // &quot;The internal [[Prototype]] property of an interface object for
-            // a callback interface MUST be the Object.prototype object.&quot;
-            assert_equals(Object.getPrototypeOf(self[this.name]), Object.prototype,
-                          &quot;prototype of self's property &quot; + format_value(this.name) + &quot; is not Object.prototype&quot;);
-
-            return;
-        }
-
-        // &quot;The interface object for a given non-callback interface is a
-        // function object.&quot;
-        // &quot;If an object is defined to be a function object, then it has
-        // characteristics as follows:&quot;
-
-        // Its [[Prototype]] internal property is otherwise specified (see
-        // below).
-
-        // &quot;* Its [[Get]] internal property is set as described in ECMA-262
-        //    section 9.1.8.&quot;
-        // Not much to test for this.
-
-        // &quot;* Its [[Construct]] internal property is set as described in
-        //    ECMA-262 section 19.2.2.3.&quot;
-        // Tested below if no constructor is defined.  TODO: test constructors
-        // if defined.
-
-        // &quot;* Its @@hasInstance property is set as described in ECMA-262
-        //    section 19.2.3.8, unless otherwise specified.&quot;
-        // TODO
-
-        // ES6 (rev 30) 19.1.3.6:
-        // &quot;Else, if O has a [[Call]] internal method, then let builtinTag be
-        // &quot;Function&quot;.&quot;
-        assert_class_string(self[this.name], &quot;Function&quot;, &quot;class string of &quot; + this.name);
-
-        // &quot;The [[Prototype]] internal property of an interface object for a
-        // non-callback interface is determined as follows:&quot;
-        var prototype = Object.getPrototypeOf(self[this.name]);
-        if (this.base) {
-            // &quot;* If the interface inherits from some other interface, the
-            //    value of [[Prototype]] is the interface object for that other
-            //    interface.&quot;
-            var has_interface_object =
-                !this.array
-                     .members[this.base]
-                     .has_extended_attribute(&quot;NoInterfaceObject&quot;);
-            if (has_interface_object) {
-                assert_own_property(self, this.base,
-                                    'should inherit from ' + this.base +
-                                    ', but self has no such property');
-                assert_equals(prototype, self[this.base],
-                              'prototype of ' + this.name + ' is not ' +
-                              this.base);
-            }
-        } else {
-            // &quot;If the interface doesn't inherit from any other interface, the
-            // value of [[Prototype]] is %FunctionPrototype% ([ECMA-262],
-            // section 6.1.7.4).&quot;
-            assert_equals(prototype, Function.prototype,
-                          &quot;prototype of self's property &quot; + format_value(this.name) + &quot; is not Function.prototype&quot;);
-        }
-
-        if (!this.has_extended_attribute(&quot;Constructor&quot;)) {
-            // &quot;The internal [[Call]] method of the interface object behaves as
-            // follows . . .
-            //
-            // &quot;If I was not declared with a [Constructor] extended attribute,
-            // then throw a TypeError.&quot;
-            assert_throws(new TypeError(), function() {
-                self[this.name]();
-            }.bind(this), &quot;interface object didn't throw TypeError when called as a function&quot;);
-            assert_throws(new TypeError(), function() {
-                new self[this.name]();
-            }.bind(this), &quot;interface object didn't throw TypeError when called as a constructor&quot;);
-        }
-    }.bind(this), this.name + &quot; interface: existence and properties of interface object&quot;);
-
-    if (!this.is_callback()) {
-        test(function() {
-            // This function tests WebIDL as of 2014-10-25.
-            // https://heycam.github.io/webidl/#es-interface-call
-
-            assert_own_property(self, this.name,
-                                &quot;self does not have own property &quot; + format_value(this.name));
-
-            // &quot;Interface objects for non-callback interfaces MUST have a
-            // property named “length” with attributes { [[Writable]]: false,
-            // [[Enumerable]]: false, [[Configurable]]: true } whose value is
-            // a Number.&quot;
-            assert_own_property(self[this.name], &quot;length&quot;);
-            var desc = Object.getOwnPropertyDescriptor(self[this.name], &quot;length&quot;);
-            assert_false(&quot;get&quot; in desc, this.name + &quot;.length has getter&quot;);
-            assert_false(&quot;set&quot; in desc, this.name + &quot;.length has setter&quot;);
-            assert_false(desc.writable, this.name + &quot;.length is writable&quot;);
-            assert_false(desc.enumerable, this.name + &quot;.length is enumerable&quot;);
-            assert_true(desc.configurable, this.name + &quot;.length is not configurable&quot;);
-
-            var constructors = this.extAttrs
-                .filter(function(attr) { return attr.name == &quot;Constructor&quot;; });
-            var expected_length = minOverloadLength(constructors);
-            assert_equals(self[this.name].length, expected_length, &quot;wrong value for &quot; + this.name + &quot;.length&quot;);
-        }.bind(this), this.name + &quot; interface object length&quot;);
-    }
-
-    if (!this.is_callback() || this.has_constants()) {
-        test(function() {
-            // This function tests WebIDL as of 2015-11-17.
-            // https://heycam.github.io/webidl/#interface-object
-
-            assert_own_property(self, this.name,
-                                &quot;self does not have own property &quot; + format_value(this.name));
-
-            // &quot;All interface objects must have a property named “name” with
-            // attributes { [[Writable]]: false, [[Enumerable]]: false,
-            // [[Configurable]]: true } whose value is the identifier of the
-            // corresponding interface.&quot;
-
-            assert_own_property(self[this.name], &quot;name&quot;);
-            var desc = Object.getOwnPropertyDescriptor(self[this.name], &quot;name&quot;);
-            assert_false(&quot;get&quot; in desc, this.name + &quot;.name has getter&quot;);
-            assert_false(&quot;set&quot; in desc, this.name + &quot;.name has setter&quot;);
-            assert_false(desc.writable, this.name + &quot;.name is writable&quot;);
-            assert_false(desc.enumerable, this.name + &quot;.name is enumerable&quot;);
-            assert_true(desc.configurable, this.name + &quot;.name is not configurable&quot;);
-            assert_equals(self[this.name].name, this.name, &quot;wrong value for &quot; + this.name + &quot;.name&quot;);
-        }.bind(this), this.name + &quot; interface object name&quot;);
-    }
-
-    // TODO: Test named constructors if I find any interfaces that have them.
-
-    test(function()
-    {
-        // This function tests WebIDL as of 2015-01-21.
-        // https://heycam.github.io/webidl/#interface-object
-
-        if (this.is_callback() &amp;&amp; !this.has_constants()) {
-            return;
-        }
-
-        assert_own_property(self, this.name,
-                            &quot;self does not have own property &quot; + format_value(this.name));
-
-        if (this.is_callback()) {
-            assert_false(&quot;prototype&quot; in self[this.name],
-                         this.name + ' should not have a &quot;prototype&quot; property');
-            return;
-        }
-
-        // &quot;An interface object for a non-callback interface must have a
-        // property named “prototype” with attributes { [[Writable]]: false,
-        // [[Enumerable]]: false, [[Configurable]]: false } whose value is an
-        // object called the interface prototype object. This object has
-        // properties that correspond to the regular attributes and regular
-        // operations defined on the interface, and is described in more detail
-        // in section 4.5.4 below.&quot;
-        assert_own_property(self[this.name], &quot;prototype&quot;,
-                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
-        var desc = Object.getOwnPropertyDescriptor(self[this.name], &quot;prototype&quot;);
-        assert_false(&quot;get&quot; in desc, this.name + &quot;.prototype has getter&quot;);
-        assert_false(&quot;set&quot; in desc, this.name + &quot;.prototype has setter&quot;);
-        assert_false(desc.writable, this.name + &quot;.prototype is writable&quot;);
-        assert_false(desc.enumerable, this.name + &quot;.prototype is enumerable&quot;);
-        assert_false(desc.configurable, this.name + &quot;.prototype is configurable&quot;);
-
-        // Next, test that the [[Prototype]] of the interface prototype object
-        // is correct. (This is made somewhat difficult by the existence of
-        // [NoInterfaceObject].)
-        // TODO: Aryeh thinks there's at least other place in this file where
-        //       we try to figure out if an interface prototype object is
-        //       correct. Consolidate that code.
-
-        // &quot;The interface prototype object for a given interface A must have an
-        // internal [[Prototype]] property whose value is returned from the
-        // following steps:
-        // &quot;If A is declared with the [Global] or [PrimaryGlobal] extended
-        // attribute, and A supports named properties, then return the named
-        // properties object for A, as defined in section 4.5.5 below.
-        // &quot;Otherwise, if A is declared to inherit from another interface, then
-        // return the interface prototype object for the inherited interface.
-        // &quot;Otherwise, if A is declared with the [ArrayClass] extended
-        // attribute, then return %ArrayPrototype% ([ECMA-262], section
-        // 6.1.7.4).
-        // &quot;Otherwise, return %ObjectPrototype% ([ECMA-262], section 6.1.7.4).
-        // ([ECMA-262], section 15.2.4).
-        if (this.name === &quot;Window&quot;) {
-            assert_class_string(Object.getPrototypeOf(self[this.name].prototype),
-                                'WindowProperties',
-                                'Class name for prototype of Window' +
-                                '.prototype is not &quot;WindowProperties&quot;');
-        } else {
-            var inherit_interface, inherit_interface_has_interface_object;
-            if (this.base) {
-                inherit_interface = this.base;
-                inherit_interface_has_interface_object =
-                    !this.array
-                         .members[inherit_interface]
-                         .has_extended_attribute(&quot;NoInterfaceObject&quot;);
-            } else if (this.has_extended_attribute('ArrayClass')) {
-                inherit_interface = 'Array';
-                inherit_interface_has_interface_object = true;
-            } else {
-                inherit_interface = 'Object';
-                inherit_interface_has_interface_object = true;
-            }
-            if (inherit_interface_has_interface_object) {
-                assert_own_property(self, inherit_interface,
-                                    'should inherit from ' + inherit_interface + ', but self has no such property');
-                assert_own_property(self[inherit_interface], 'prototype',
-                                    'should inherit from ' + inherit_interface + ', but that object has no &quot;prototype&quot; property');
-                assert_equals(Object.getPrototypeOf(self[this.name].prototype),
-                              self[inherit_interface].prototype,
-                              'prototype of ' + this.name + '.prototype is not ' + inherit_interface + '.prototype');
-            } else {
-                // We can't test that we get the correct object, because this is the
-                // only way to get our hands on it. We only test that its class
-                // string, at least, is correct.
-                assert_class_string(Object.getPrototypeOf(self[this.name].prototype),
-                                    inherit_interface + 'Prototype',
-                                    'Class name for prototype of ' + this.name +
-                                    '.prototype is not &quot;' + inherit_interface + 'Prototype&quot;');
-            }
-        }
-
-        // &quot;The class string of an interface prototype object is the
-        // concatenation of the interface’s identifier and the string
-        // “Prototype”.&quot;
-        assert_class_string(self[this.name].prototype, this.name + &quot;Prototype&quot;,
-                            &quot;class string of &quot; + this.name + &quot;.prototype&quot;);
-        // String() should end up calling {}.toString if nothing defines a
-        // stringifier.
-        if (!this.has_stringifier()) {
-            assert_equals(String(self[this.name].prototype), &quot;[object &quot; + this.name + &quot;Prototype]&quot;,
-                    &quot;String(&quot; + this.name + &quot;.prototype)&quot;);
-        }
-    }.bind(this), this.name + &quot; interface: existence and properties of interface prototype object&quot;);
-
-    test(function()
-    {
-        if (this.is_callback() &amp;&amp; !this.has_constants()) {
-            return;
-        }
-
-        assert_own_property(self, this.name,
-                            &quot;self does not have own property &quot; + format_value(this.name));
-
-        if (this.is_callback()) {
-            assert_false(&quot;prototype&quot; in self[this.name],
-                         this.name + ' should not have a &quot;prototype&quot; property');
-            return;
-        }
-
-        assert_own_property(self[this.name], &quot;prototype&quot;,
-                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
-
-        // &quot;If the [NoInterfaceObject] extended attribute was not specified on
-        // the interface, then the interface prototype object must also have a
-        // property named “constructor” with attributes { [[Writable]]: true,
-        // [[Enumerable]]: false, [[Configurable]]: true } whose value is a
-        // reference to the interface object for the interface.&quot;
-        assert_own_property(self[this.name].prototype, &quot;constructor&quot;,
-                            this.name + '.prototype does not have own property &quot;constructor&quot;');
-        var desc = Object.getOwnPropertyDescriptor(self[this.name].prototype, &quot;constructor&quot;);
-        assert_false(&quot;get&quot; in desc, this.name + &quot;.prototype.constructor has getter&quot;);
-        assert_false(&quot;set&quot; in desc, this.name + &quot;.prototype.constructor has setter&quot;);
-        assert_true(desc.writable, this.name + &quot;.prototype.constructor is not writable&quot;);
-        assert_false(desc.enumerable, this.name + &quot;.prototype.constructor is enumerable&quot;);
-        assert_true(desc.configurable, this.name + &quot;.prototype.constructor in not configurable&quot;);
-        assert_equals(self[this.name].prototype.constructor, self[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 &quot;constructor&quot; property');
-};
-
-//@}
-IdlInterface.prototype.test_member_const = function(member)
-//@{
-{
-    if (!this.has_constants()) {
-        throw &quot;Internal error: test_member_const called without any constants&quot;;
-    }
-
-    test(function()
-    {
-        assert_own_property(self, this.name,
-                            &quot;self does not have own property &quot; + format_value(this.name));
-
-        // &quot;For each constant defined on an interface A, there must be
-        // a corresponding property on the interface object, if it
-        // exists.&quot;
-        assert_own_property(self[this.name], member.name);
-        // &quot;The value of the property is that which is obtained by
-        // converting the constant’s IDL value to an ECMAScript
-        // value.&quot;
-        assert_equals(self[this.name][member.name], constValue(member.value),
-                      &quot;property has wrong value&quot;);
-        // &quot;The property has attributes { [[Writable]]: false,
-        // [[Enumerable]]: true, [[Configurable]]: false }.&quot;
-        var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);
-        assert_false(&quot;get&quot; in desc, &quot;property has getter&quot;);
-        assert_false(&quot;set&quot; in desc, &quot;property has setter&quot;);
-        assert_false(desc.writable, &quot;property is writable&quot;);
-        assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
-        assert_false(desc.configurable, &quot;property is configurable&quot;);
-    }.bind(this), this.name + &quot; interface: constant &quot; + member.name + &quot; on interface object&quot;);
-
-    // &quot;In addition, a property with the same characteristics must
-    // exist on the interface prototype object.&quot;
-    test(function()
-    {
-        assert_own_property(self, this.name,
-                            &quot;self does not have own property &quot; + format_value(this.name));
-
-        if (this.is_callback()) {
-            assert_false(&quot;prototype&quot; in self[this.name],
-                         this.name + ' should not have a &quot;prototype&quot; property');
-            return;
-        }
-
-        assert_own_property(self[this.name], &quot;prototype&quot;,
-                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
-
-        assert_own_property(self[this.name].prototype, member.name);
-        assert_equals(self[this.name].prototype[member.name], constValue(member.value),
-                      &quot;property has wrong value&quot;);
-        var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);
-        assert_false(&quot;get&quot; in desc, &quot;property has getter&quot;);
-        assert_false(&quot;set&quot; in desc, &quot;property has setter&quot;);
-        assert_false(desc.writable, &quot;property is writable&quot;);
-        assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
-        assert_false(desc.configurable, &quot;property is configurable&quot;);
-    }.bind(this), this.name + &quot; interface: constant &quot; + member.name + &quot; on interface prototype object&quot;);
-};
-
-
-//@}
-IdlInterface.prototype.test_member_attribute = function(member)
-//@{
-{
-    test(function()
-    {
-        if (this.is_callback() &amp;&amp; !this.has_constants()) {
-            return;
-        }
-
-        assert_own_property(self, this.name,
-                            &quot;self does not have own property &quot; + format_value(this.name));
-        assert_own_property(self[this.name], &quot;prototype&quot;,
-                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
-
-        if (member[&quot;static&quot;]) {
-            assert_own_property(self[this.name], member.name,
-                &quot;The interface object must have a property &quot; +
-                format_value(member.name));
-        } else if (this.is_global()) {
-            assert_own_property(self, member.name,
-                &quot;The global object must have a property &quot; +
-                format_value(member.name));
-            assert_false(member.name in self[this.name].prototype,
-                &quot;The prototype object must not have a property &quot; +
-                format_value(member.name));
-
-            var getter = Object.getOwnPropertyDescriptor(self, member.name).get;
-            assert_equals(typeof(getter), &quot;function&quot;,
-                          format_value(member.name) + &quot; must have a getter&quot;);
-
-            // Try/catch around the get here, since it can legitimately throw.
-            // If it does, we obviously can't check for equality with direct
-            // invocation of the getter.
-            var gotValue;
-            var propVal;
-            try {
-                propVal = self[member.name];
-                gotValue = true;
-            } catch (e) {
-                gotValue = false;
-            }
-            if (gotValue) {
-                assert_equals(propVal, getter.call(undefined),
-                              &quot;Gets on a global should not require an explicit this&quot;);
-            }
-
-            this.do_interface_attribute_asserts(self, member);
-        } else {
-            assert_true(member.name in self[this.name].prototype,
-                &quot;The prototype object must have a property &quot; +
-                format_value(member.name));
-
-            if (!member.has_extended_attribute(&quot;LenientThis&quot;)) {
-                assert_throws(new TypeError(), function() {
-                    self[this.name].prototype[member.name];
-                }.bind(this), &quot;getting property on prototype object must throw TypeError&quot;);
-            } else {
-                assert_equals(self[this.name].prototype[member.name], undefined,
-                              &quot;getting property on prototype object must return undefined&quot;);
-            }
-            this.do_interface_attribute_asserts(self[this.name].prototype, member);
-        }
-    }.bind(this), this.name + &quot; interface: attribute &quot; + member.name);
-};
-
-//@}
-IdlInterface.prototype.test_member_operation = function(member)
-//@{
-{
-    var a_test = async_test(this.name + &quot; interface: operation &quot; + member.name +
-                            &quot;(&quot; + member.arguments.map(
-                                function(m) {return m.idlType.idlType; } )
-                            +&quot;)&quot;);
-    a_test.step(function()
-    {
-        // This function tests WebIDL as of 2015-12-29.
-        // https://heycam.github.io/webidl/#es-operations
-
-        if (this.is_callback() &amp;&amp; !this.has_constants()) {
-            a_test.done();
-            return;
-        }
-
-        assert_own_property(self, this.name,
-                            &quot;self does not have own property &quot; + format_value(this.name));
-
-        if (this.is_callback()) {
-            assert_false(&quot;prototype&quot; in self[this.name],
-                         this.name + ' should not have a &quot;prototype&quot; property');
-            a_test.done();
-            return;
-        }
-
-        assert_own_property(self[this.name], &quot;prototype&quot;,
-                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
-
-        // &quot;For each unique identifier of an exposed operation defined on the
-        // interface, there must exist a corresponding property, unless the
-        // effective overload set for that identifier and operation and with an
-        // argument count of 0 has no entries.&quot;
-
-        // TODO: Consider [Exposed].
-
-        // &quot;The location of the property is determined as follows:&quot;
-        var memberHolderObject;
-        // &quot;* If the operation is static, then the property exists on the
-        //    interface object.&quot;
-        if (member[&quot;static&quot;]) {
-            assert_own_property(self[this.name], member.name,
-                    &quot;interface object missing static operation&quot;);
-            memberHolderObject = self[this.name];
-        // &quot;* Otherwise, [...] if the interface was declared with the [Global]
-        //    or [PrimaryGlobal] extended attribute, then the property exists
-        //    on every object that implements the interface.&quot;
-        } else if (this.is_global()) {
-            assert_own_property(self, member.name,
-                    &quot;global object missing non-static operation&quot;);
-            memberHolderObject = self;
-        // &quot;* Otherwise, the property exists solely on the interface’s
-        //    interface prototype object.&quot;
-        } else {
-            assert_own_property(self[this.name].prototype, member.name,
-                    &quot;interface prototype object missing non-static operation&quot;);
-            memberHolderObject = self[this.name].prototype;
-        }
-        this.do_member_operation_asserts(memberHolderObject, member, a_test);
-    }.bind(this));
-};
-
-//@}
-IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject, member, a_test)
-//@{
-{
-    var done = a_test.done.bind(a_test);
-    var operationUnforgeable = member.isUnforgeable;
-    var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);
-    // &quot;The property has attributes { [[Writable]]: B,
-    // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
-    // operation is unforgeable on the interface, and true otherwise&quot;.
-    assert_false(&quot;get&quot; in desc, &quot;property has getter&quot;);
-    assert_false(&quot;set&quot; in desc, &quot;property has setter&quot;);
-    assert_equals(desc.writable, !operationUnforgeable,
-                  &quot;property should be writable if and only if not unforgeable&quot;);
-    assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
-    assert_equals(desc.configurable, !operationUnforgeable,
-                  &quot;property should be configurable if and only if not unforgeable&quot;);
-    // &quot;The value of the property is a Function object whose
-    // behavior is as follows . . .&quot;
-    assert_equals(typeof memberHolderObject[member.name], &quot;function&quot;,
-                  &quot;property must be a function&quot;);
-    // &quot;The value of the Function object’s “length” property is
-    // a Number determined as follows:
-    // &quot;. . .
-    // &quot;Return the length of the shortest argument list of the
-    // entries in S.&quot;
-    assert_equals(memberHolderObject[member.name].length,
-        minOverloadLength(this.members.filter(function(m) {
-            return m.type == &quot;operation&quot; &amp;&amp; m.name == member.name;
-        })),
-        &quot;property has wrong .length&quot;);
-
-    // Make some suitable arguments
-    var args = member.arguments.map(function(arg) {
-        return create_suitable_object(arg.idlType);
-    });
-
-    // &quot;Let O be a value determined as follows:
-    // &quot;. . .
-    // &quot;Otherwise, throw a TypeError.&quot;
-    // This should be hit if the operation is not static, there is
-    // no [ImplicitThis] attribute, and the this value is null.
-    //
-    // TODO: We currently ignore the [ImplicitThis] case.  Except we manually
-    // check for globals, since otherwise we'll invoke window.close().  And we
-    // have to skip this test for anything that on the proto chain of &quot;self&quot;,
-    // since that does in fact have implicit-this behavior.
-    if (!member[&quot;static&quot;]) {
-        var cb;
-        if (!this.is_global() &amp;&amp;
-            memberHolderObject[member.name] != self[member.name])
-        {
-            cb = awaitNCallbacks(2, done);
-            throwOrReject(a_test, member, memberHolderObject[member.name], null, args,
-                          &quot;calling operation with this = null didn't throw TypeError&quot;, cb);
-        } else {
-            cb = awaitNCallbacks(1, done);
-        }
-
-        // &quot;. . . If O is not null and is also not a platform object
-        // that implements interface I, throw a TypeError.&quot;
-        //
-        // TODO: Test a platform object that implements some other
-        // interface.  (Have to be sure to get inheritance right.)
-        throwOrReject(a_test, member, memberHolderObject[member.name], {}, args,
-                      &quot;calling operation with this = {} didn't throw TypeError&quot;, cb);
-    } else {
-        done();
-    }
-}
-
-//@}
-IdlInterface.prototype.test_member_stringifier = function(member)
-//@{
-{
-    test(function()
-    {
-        if (this.is_callback() &amp;&amp; !this.has_constants()) {
-            return;
-        }
-
-        assert_own_property(self, this.name,
-                            &quot;self does not have own property &quot; + format_value(this.name));
-
-        if (this.is_callback()) {
-            assert_false(&quot;prototype&quot; in self[this.name],
-                         this.name + ' should not have a &quot;prototype&quot; property');
-            return;
-        }
-
-        assert_own_property(self[this.name], &quot;prototype&quot;,
-                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
-
-        // &quot;. . . the property exists on the interface prototype object.&quot;
-        var interfacePrototypeObject = self[this.name].prototype;
-        assert_own_property(self[this.name].prototype, &quot;toString&quot;,
-                &quot;interface prototype object missing non-static operation&quot;);
-
-        var stringifierUnforgeable = member.isUnforgeable;
-        var desc = Object.getOwnPropertyDescriptor(interfacePrototypeObject, &quot;toString&quot;);
-        // &quot;The property has attributes { [[Writable]]: B,
-        // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
-        // stringifier is unforgeable on the interface, and true otherwise.&quot;
-        assert_false(&quot;get&quot; in desc, &quot;property has getter&quot;);
-        assert_false(&quot;set&quot; in desc, &quot;property has setter&quot;);
-        assert_equals(desc.writable, !stringifierUnforgeable,
-                      &quot;property should be writable if and only if not unforgeable&quot;);
-        assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
-        assert_equals(desc.configurable, !stringifierUnforgeable,
-                      &quot;property should be configurable if and only if not unforgeable&quot;);
-        // &quot;The value of the property is a Function object, which behaves as
-        // follows . . .&quot;
-        assert_equals(typeof interfacePrototypeObject.toString, &quot;function&quot;,
-                      &quot;property must be a function&quot;);
-        // &quot;The value of the Function object’s “length” property is the Number
-        // value 0.&quot;
-        assert_equals(interfacePrototypeObject.toString.length, 0,
-            &quot;property has wrong .length&quot;);
-
-        // &quot;Let O be the result of calling ToObject on the this value.&quot;
-        assert_throws(new TypeError(), function() {
-            self[this.name].prototype.toString.apply(null, []);
-        }, &quot;calling stringifier with this = null didn't throw TypeError&quot;);
-
-        // &quot;If O is not an object that implements the interface on which the
-        // stringifier was declared, then throw a TypeError.&quot;
-        //
-        // TODO: Test a platform object that implements some other
-        // interface.  (Have to be sure to get inheritance right.)
-        assert_throws(new TypeError(), function() {
-            self[this.name].prototype.toString.apply({}, []);
-        }, &quot;calling stringifier with this = {} didn't throw TypeError&quot;);
-    }.bind(this), this.name + &quot; interface: stringifier&quot;);
-};
-
-//@}
-IdlInterface.prototype.test_members = function()
-//@{
-{
-    for (var i = 0; i &lt; this.members.length; i++)
-    {
-        var member = this.members[i];
-        if (member.untested) {
-            continue;
-        }
-
-        switch (member.type) {
-        case &quot;const&quot;:
-            this.test_member_const(member);
-            break;
-
-        case &quot;attribute&quot;:
-            // For unforgeable attributes, we do the checks in
-            // test_interface_of instead.
-            if (!member.isUnforgeable)
-            {
-                this.test_member_attribute(member);
-            }
-            break;
-
-        case &quot;operation&quot;:
-            // TODO: Need to correctly handle multiple operations with the same
-            // identifier.
-            // For unforgeable operations, we do the checks in
-            // test_interface_of instead.
-            if (member.name) {
-                if (!member.isUnforgeable)
-                {
-                    this.test_member_operation(member);
-                }
-            } else if (member.stringifier) {
-                this.test_member_stringifier(member);
-            }
-            break;
-
-        default:
-            // TODO: check more member types.
-            break;
-        }
-    }
-};
-
-//@}
-IdlInterface.prototype.test_object = function(desc)
-//@{
-{
-    var obj, exception = null;
-    try
-    {
-        obj = eval(desc);
-    }
-    catch(e)
-    {
-        exception = e;
-    }
-
-    var expected_typeof =
-        this.members.some(function(member) { return member.legacycaller; })
-        ? &quot;function&quot;
-        : &quot;object&quot;;
-
-    this.test_primary_interface_of(desc, obj, exception, expected_typeof);
-    var current_interface = this;
-    while (current_interface)
-    {
-        if (!(current_interface.name in this.array.members))
-        {
-            throw &quot;Interface &quot; + current_interface.name + &quot; not found (inherited by &quot; + this.name + &quot;)&quot;;
-        }
-        if (current_interface.prevent_multiple_testing &amp;&amp; current_interface.already_tested)
-        {
-            return;
-        }
-        current_interface.test_interface_of(desc, obj, exception, expected_typeof);
-        current_interface = this.array.members[current_interface.base];
-    }
-};
-
-//@}
-IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception, expected_typeof)
-//@{
-{
-    // We can't easily test that its prototype is correct if there's no
-    // interface object, or the object is from a different global environment
-    // (not instanceof Object).  TODO: test in this case that its prototype at
-    // least looks correct, even if we can't test that it's actually correct.
-    if (!this.has_extended_attribute(&quot;NoInterfaceObject&quot;)
-    &amp;&amp; (typeof obj != expected_typeof || obj instanceof Object))
-    {
-        test(function()
-        {
-            assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
-            assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
-            assert_own_property(self, this.name,
-                                &quot;self does not have own property &quot; + format_value(this.name));
-            assert_own_property(self[this.name], &quot;prototype&quot;,
-                                'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
-
-            // &quot;The value of the internal [[Prototype]] property of the
-            // platform object is the interface prototype object of the primary
-            // interface from the platform object’s associated global
-            // environment.&quot;
-            assert_equals(Object.getPrototypeOf(obj),
-                          self[this.name].prototype,
-                          desc + &quot;'s prototype is not &quot; + this.name + &quot;.prototype&quot;);
-        }.bind(this), this.name + &quot; must be primary interface of &quot; + desc);
-    }
-
-    // &quot;The class string of a platform object that implements one or more
-    // interfaces must be the identifier of the primary interface of the
-    // platform object.&quot;
-    test(function()
-    {
-        assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
-        assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
-        assert_class_string(obj, this.name, &quot;class string of &quot; + desc);
-        if (!this.has_stringifier())
-        {
-            assert_equals(String(obj), &quot;[object &quot; + this.name + &quot;]&quot;, &quot;String(&quot; + desc + &quot;)&quot;);
-        }
-    }.bind(this), &quot;Stringification of &quot; + desc);
-};
-
-//@}
-IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof)
-//@{
-{
-    // TODO: Indexed and named properties, more checks on interface members
-    this.already_tested = true;
-
-    for (var i = 0; i &lt; this.members.length; i++)
-    {
-        var member = this.members[i];
-        if (member.type == &quot;attribute&quot; &amp;&amp; member.isUnforgeable)
-        {
-            test(function()
-            {
-                assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
-                assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
-                this.do_interface_attribute_asserts(obj, member);
-            }.bind(this), this.name + &quot; interface: &quot; + desc + ' must have own property &quot;' + member.name + '&quot;');
-        }
-        else if (member.type == &quot;operation&quot; &amp;&amp;
-                 member.name &amp;&amp;
-                 member.isUnforgeable)
-        {
-            var a_test = async_test(this.name + &quot; interface: &quot; + desc + ' must have own property &quot;' + member.name + '&quot;');
-            a_test.step(function()
-            {
-                assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
-                assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
-                assert_own_property(obj, member.name,
-                                    &quot;Doesn't have the unforgeable operation property&quot;);
-                this.do_member_operation_asserts(obj, member, a_test);
-            }.bind(this));
-        }
-        else if ((member.type == &quot;const&quot;
-        || member.type == &quot;attribute&quot;
-        || member.type == &quot;operation&quot;)
-        &amp;&amp; member.name)
-        {
-            test(function()
-            {
-                assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
-                assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
-                if (!member[&quot;static&quot;]) {
-                    if (!this.is_global()) {
-                        assert_inherits(obj, member.name);
-                    } else {
-                        assert_own_property(obj, member.name);
-                    }
-
-                    if (member.type == &quot;const&quot;)
-                    {
-                        assert_equals(obj[member.name], constValue(member.value));
-                    }
-                    if (member.type == &quot;attribute&quot;)
-                    {
-                        // Attributes are accessor properties, so they might
-                        // legitimately throw an exception rather than returning
-                        // anything.
-                        var property, thrown = false;
-                        try
-                        {
-                            property = obj[member.name];
-                        }
-                        catch (e)
-                        {
-                            thrown = true;
-                        }
-                        if (!thrown)
-                        {
-                            this.array.assert_type_is(property, member.idlType);
-                        }
-                    }
-                    if (member.type == &quot;operation&quot;)
-                    {
-                        assert_equals(typeof obj[member.name], &quot;function&quot;);
-                    }
-                }
-            }.bind(this), this.name + &quot; interface: &quot; + desc + ' must inherit property &quot;' + member.name + '&quot; with the proper type (' + i + ')');
-        }
-        // TODO: This is wrong if there are multiple operations with the same
-        // identifier.
-        // TODO: Test passing arguments of the wrong type.
-        if (member.type == &quot;operation&quot; &amp;&amp; member.name &amp;&amp; member.arguments.length)
-        {
-            var a_test = async_test( this.name + &quot; interface: calling &quot; + member.name +
-            &quot;(&quot; + member.arguments.map(function(m) { return m.idlType.idlType; }) +
-            &quot;) on &quot; + desc + &quot; with too few arguments must throw TypeError&quot;);
-            a_test.step(function()
-            {
-                assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
-                assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
-                if (!member[&quot;static&quot;]) {
-                    if (!this.is_global() &amp;&amp; !member.isUnforgeable) {
-                        assert_inherits(obj, member.name);
-                    } else {
-                        assert_own_property(obj, member.name);
-                    }
-                }
-                else
-                {
-                    assert_false(member.name in obj);
-                }
-
-                var minLength = minOverloadLength(this.members.filter(function(m) {
-                    return m.type == &quot;operation&quot; &amp;&amp; m.name == member.name;
-                }));
-                var args = [];
-                var cb = awaitNCallbacks(minLength, a_test.done.bind(a_test));
-                for (var i = 0; i &lt; minLength; i++) {
-                    throwOrReject(a_test, member, obj[member.name], obj, args,  &quot;Called with &quot; + i + &quot; arguments&quot;, cb);
-
-                    args.push(create_suitable_object(member.arguments[i].idlType));
-                }
-                if (minLength === 0) {
-                    cb();
-                }
-            }.bind(this));
-        }
-    }
-};
-
-//@}
-IdlInterface.prototype.has_stringifier = function()
-//@{
-{
-    if (this.members.some(function(member) { return member.stringifier; })) {
-        return true;
-    }
-    if (this.base &amp;&amp;
-        this.array.members[this.base].has_stringifier()) {
-        return true;
-    }
-    return false;
-};
-
-//@}
-IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member)
-//@{
-{
-    // This function tests WebIDL as of 2015-01-27.
-    // TODO: Consider [Exposed].
-
-    // This is called by test_member_attribute() with the prototype as obj if
-    // it is not a global, and the global otherwise, and by test_interface_of()
-    // with the object as obj.
-
-    // &quot;For each exposed attribute of the interface, whether it was declared on
-    // the interface itself or one of its consequential interfaces, there MUST
-    // exist a corresponding property. The characteristics of this property are
-    // as follows:&quot;
-
-    // &quot;The name of the property is the identifier of the attribute.&quot;
-    assert_own_property(obj, member.name);
-
-    // &quot;The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
-    // true, [[Configurable]]: configurable }, where:
-    // &quot;configurable is false if the attribute was declared with the
-    // [Unforgeable] extended attribute and true otherwise;
-    // &quot;G is the attribute getter, defined below; and
-    // &quot;S is the attribute setter, also defined below.&quot;
-    var desc = Object.getOwnPropertyDescriptor(obj, member.name);
-    assert_false(&quot;value&quot; in desc, 'property descriptor has value but is supposed to be accessor');
-    assert_false(&quot;writable&quot; in desc, 'property descriptor has &quot;writable&quot; field but is supposed to be accessor');
-    assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
-    if (member.isUnforgeable)
-    {
-        assert_false(desc.configurable, &quot;[Unforgeable] property must not be configurable&quot;);
-    }
-    else
-    {
-        assert_true(desc.configurable, &quot;property must be configurable&quot;);
-    }
-
-
-    // &quot;The attribute getter is a Function object whose behavior when invoked
-    // is as follows:&quot;
-    assert_equals(typeof desc.get, &quot;function&quot;, &quot;getter must be Function&quot;);
-
-    // &quot;If the attribute is a regular attribute, then:&quot;
-    if (!member[&quot;static&quot;]) {
-        // &quot;If O is not a platform object that implements I, then:
-        // &quot;If the attribute was specified with the [LenientThis] extended
-        // attribute, then return undefined.
-        // &quot;Otherwise, throw a TypeError.&quot;
-        if (!member.has_extended_attribute(&quot;LenientThis&quot;)) {
-            assert_throws(new TypeError(), function() {
-                desc.get.call({});
-            }.bind(this), &quot;calling getter on wrong object type must throw TypeError&quot;);
-        } else {
-            assert_equals(desc.get.call({}), undefined,
-                          &quot;calling getter on wrong object type must return undefined&quot;);
-        }
-    }
-
-    // &quot;The value of the Function object’s “length” property is the Number
-    // value 0.&quot;
-    assert_equals(desc.get.length, 0, &quot;getter length must be 0&quot;);
-
-
-    // TODO: Test calling setter on the interface prototype (should throw
-    // TypeError in most cases).
-    if (member.readonly
-    &amp;&amp; !member.has_extended_attribute(&quot;PutForwards&quot;)
-    &amp;&amp; !member.has_extended_attribute(&quot;Replaceable&quot;))
-    {
-        // &quot;The attribute setter is undefined if the attribute is declared
-        // readonly and has neither a [PutForwards] nor a [Replaceable]
-        // extended attribute declared on it.&quot;
-        assert_equals(desc.set, undefined, &quot;setter must be undefined for readonly attributes&quot;);
-    }
-    else
-    {
-        // &quot;Otherwise, it is a Function object whose behavior when
-        // invoked is as follows:&quot;
-        assert_equals(typeof desc.set, &quot;function&quot;, &quot;setter must be function for PutForwards, Replaceable, or non-readonly attributes&quot;);
-
-        // &quot;If the attribute is a regular attribute, then:&quot;
-        if (!member[&quot;static&quot;]) {
-            // &quot;If /validThis/ is false and the attribute was not specified
-            // with the [LenientThis] extended attribute, then throw a
-            // TypeError.&quot;
-            // &quot;If the attribute is declared with a [Replaceable] extended
-            // attribute, then: ...&quot;
-            // &quot;If validThis is false, then return.&quot;
-            if (!member.has_extended_attribute(&quot;LenientThis&quot;)) {
-                assert_throws(new TypeError(), function() {
-                    desc.set.call({});
-                }.bind(this), &quot;calling setter on wrong object type must throw TypeError&quot;);
-            } else {
-                assert_equals(desc.set.call({}), undefined,
-                              &quot;calling setter on wrong object type must return undefined&quot;);
-            }
-        }
-
-        // &quot;The value of the Function object’s “length” property is the Number
-        // value 1.&quot;
-        assert_equals(desc.set.length, 1, &quot;setter length must be 1&quot;);
-    }
-}
-//@}
-
-/// IdlInterfaceMember ///
-function IdlInterfaceMember(obj)
-//@{
-{
-    /**
-     * obj is an object produced by the WebIDLParser.js &quot;ifMember&quot; production.
-     * We just forward all properties to this object without modification,
-     * except for special extAttrs handling.
-     */
-    for (var k in obj)
-    {
-        this[k] = obj[k];
-    }
-    if (!(&quot;extAttrs&quot; in this))
-    {
-        this.extAttrs = [];
-    }
-
-    this.isUnforgeable = this.has_extended_attribute(&quot;Unforgeable&quot;);
-}
-
-//@}
-IdlInterfaceMember.prototype = Object.create(IdlObject.prototype);
-
-/// Internal helper functions ///
-function create_suitable_object(type)
-//@{
-{
-    /**
-     * type is an object produced by the WebIDLParser.js &quot;type&quot; production.  We
-     * return a JavaScript value that matches the type, if we can figure out
-     * how.
-     */
-    if (type.nullable)
-    {
-        return null;
-    }
-    switch (type.idlType)
-    {
-        case &quot;any&quot;:
-        case &quot;boolean&quot;:
-            return true;
-
-        case &quot;byte&quot;: case &quot;octet&quot;: case &quot;short&quot;: case &quot;unsigned short&quot;:
-        case &quot;long&quot;: case &quot;unsigned long&quot;: case &quot;long long&quot;:
-        case &quot;unsigned long long&quot;: case &quot;float&quot;: case &quot;double&quot;:
-        case &quot;unrestricted float&quot;: case &quot;unrestricted double&quot;:
-            return 7;
-
-        case &quot;DOMString&quot;:
-        case &quot;ByteString&quot;:
-        case &quot;USVString&quot;:
-            return &quot;foo&quot;;
-
-        case &quot;object&quot;:
-            return {a: &quot;b&quot;};
-
-        case &quot;Node&quot;:
-            return document.createTextNode(&quot;abc&quot;);
-    }
-    return null;
-}
-//@}
-
-/// IdlEnum ///
-// Used for IdlArray.prototype.assert_type_is
-function IdlEnum(obj)
-//@{
-{
-    /**
-     * obj is an object produced by the WebIDLParser.js &quot;dictionary&quot;
-     * production.
-     */
-
-    /** Self-explanatory. */
-    this.name = obj.name;
-
-    /** An array of values produced by the &quot;enum&quot; production. */
-    this.values = obj.values;
-
-}
-//@}
-
-IdlEnum.prototype = Object.create(IdlObject.prototype);
-
-/// IdlTypedef ///
-// Used for IdlArray.prototype.assert_type_is
-function IdlTypedef(obj)
-//@{
-{
-    /**
-     * obj is an object produced by the WebIDLParser.js &quot;typedef&quot;
-     * production.
-     */
-
-    /** Self-explanatory. */
-    this.name = obj.name;
-
-    /** An array of values produced by the &quot;typedef&quot; production. */
-    this.values = obj.values;
-
-}
-//@}
-
-IdlTypedef.prototype = Object.create(IdlObject.prototype);
-
-}());
-// vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:
</del></span></pre></div>
<a id="trunkLayoutTestsplatformmacjsdomglobalconstructorsattributesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/js/dom/global-constructors-attributes-expected.txt (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/js/dom/global-constructors-attributes-expected.txt        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/LayoutTests/platform/mac/js/dom/global-constructors-attributes-expected.txt        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -303,6 +303,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'Credential').value is Credential
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').value is Crypto
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').hasOwnProperty('set') is false
</span><span class="lines">@@ -1168,6 +1173,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').value is PasswordCredential
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').value is Path2D
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').hasOwnProperty('set') is false
</span><span class="lines">@@ -2098,6 +2108,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').value is SiteBoundCredential
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').value is SourceBuffer
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').hasOwnProperty('set') is false
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacelcapitanjsdomglobalconstructorsattributesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac-elcapitan/js/dom/global-constructors-attributes-expected.txt (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac-elcapitan/js/dom/global-constructors-attributes-expected.txt        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/LayoutTests/platform/mac-elcapitan/js/dom/global-constructors-attributes-expected.txt        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -298,6 +298,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'Credential').value is Credential
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').value is Crypto
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').hasOwnProperty('set') is false
</span><span class="lines">@@ -1163,6 +1168,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').value is PasswordCredential
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').value is Path2D
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').hasOwnProperty('set') is false
</span><span class="lines">@@ -2093,6 +2103,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').value is SiteBoundCredential
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').value is SourceBuffer
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').hasOwnProperty('set') is false
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacwk1jsdomglobalconstructorsattributesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac-wk1/js/dom/global-constructors-attributes-expected.txt (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac-wk1/js/dom/global-constructors-attributes-expected.txt        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/LayoutTests/platform/mac-wk1/js/dom/global-constructors-attributes-expected.txt        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -298,6 +298,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'Credential').value is Credential
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').value is Crypto
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').hasOwnProperty('set') is false
</span><span class="lines">@@ -1163,6 +1168,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').value is PasswordCredential
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').value is Path2D
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').hasOwnProperty('set') is false
</span><span class="lines">@@ -2093,6 +2103,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').value is SiteBoundCredential
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').value is SourceBuffer
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').hasOwnProperty('set') is false
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacyosemitejsdomglobalconstructorsattributesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac-yosemite/js/dom/global-constructors-attributes-expected.txt (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac-yosemite/js/dom/global-constructors-attributes-expected.txt        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/LayoutTests/platform/mac-yosemite/js/dom/global-constructors-attributes-expected.txt        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -298,6 +298,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Counter').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'Credential').value is Credential
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'Credential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').value is Crypto
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Crypto').hasOwnProperty('set') is false
</span><span class="lines">@@ -1158,6 +1163,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'PageTransitionEvent').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').value is PasswordCredential
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'PasswordCredential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').value is Path2D
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'Path2D').hasOwnProperty('set') is false
</span><span class="lines">@@ -2088,6 +2098,11 @@
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').hasOwnProperty('set') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').enumerable is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SharedArrayBuffer').configurable is true
</span><ins>+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').value is SiteBoundCredential
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').hasOwnProperty('get') is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').hasOwnProperty('set') is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').enumerable is false
+PASS Object.getOwnPropertyDescriptor(global, 'SiteBoundCredential').configurable is true
</ins><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').value is SourceBuffer
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').hasOwnProperty('get') is false
</span><span class="cx"> PASS Object.getOwnPropertyDescriptor(global, 'SourceBuffer').hasOwnProperty('set') is false
</span></span></pre></div>
<a id="trunkLayoutTestsresourcesWebIDLParserjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/resources/WebIDLParser.js (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/resources/WebIDLParser.js                                (rev 0)
+++ trunk/LayoutTests/resources/WebIDLParser.js        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,1012 @@
</span><ins>+
+
+(function () {
+    var tokenise = function (str) {
+        var tokens = []
+        ,   re = {
+                &quot;float&quot;:        /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/
+            ,   &quot;integer&quot;:      /^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/
+            ,   &quot;identifier&quot;:   /^[A-Z_a-z][0-9A-Z_a-z]*/
+            ,   &quot;string&quot;:       /^&quot;[^&quot;]*&quot;/
+            ,   &quot;whitespace&quot;:   /^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/
+            ,   &quot;other&quot;:        /^[^\t\n\r 0-9A-Z_a-z]/
+            }
+        ,   types = []
+        ;
+        for (var k in re) types.push(k);
+        while (str.length &gt; 0) {
+            var matched = false;
+            for (var i = 0, n = types.length; i &lt; n; i++) {
+                var type = types[i];
+                str = str.replace(re[type], function (tok) {
+                    tokens.push({ type: type, value: tok });
+                    matched = true;
+                    return &quot;&quot;;
+                });
+                if (matched) break;
+            }
+            if (matched) continue;
+            throw new Error(&quot;Token stream not progressing&quot;);
+        }
+        return tokens;
+    };
+    
+    var parse = function (tokens, opt) {
+        var line = 1;
+        tokens = tokens.slice();
+        
+        var FLOAT = &quot;float&quot;
+        ,   INT = &quot;integer&quot;
+        ,   ID = &quot;identifier&quot;
+        ,   STR = &quot;string&quot;
+        ,   OTHER = &quot;other&quot;
+        ;
+        
+        var WebIDLParseError = function (str, line, input, tokens) {
+            this.message = str;
+            this.line = line;
+            this.input = input;
+            this.tokens = tokens;
+        };
+        WebIDLParseError.prototype.toString = function () {
+            return this.message + &quot;, line &quot; + this.line + &quot; (tokens: '&quot; + this.input + &quot;')\n&quot; +
+                   JSON.stringify(this.tokens, null, 4);
+        };
+        
+        var error = function (str) {
+            var tok = &quot;&quot;, numTokens = 0, maxTokens = 5;
+            while (numTokens &lt; maxTokens &amp;&amp; tokens.length &gt; numTokens) {
+                tok += tokens[numTokens].value;
+                numTokens++;
+            }
+            throw new WebIDLParseError(str, line, tok, tokens.slice(0, 5));
+        };
+        
+        var last_token = null;
+        
+        var consume = function (type, value) {
+            if (!tokens.length || tokens[0].type !== type) return;
+            if (typeof value === &quot;undefined&quot; || tokens[0].value === value) {
+                 last_token = tokens.shift();
+                 if (type === ID) last_token.value = last_token.value.replace(/^_/, &quot;&quot;);
+                 return last_token;
+             }
+        };
+        
+        var ws = function () {
+            if (!tokens.length) return;
+            if (tokens[0].type === &quot;whitespace&quot;) {
+                var t = tokens.shift();
+                t.value.replace(/\n/g, function (m) { line++; return m; });
+                return t;
+            }
+        };
+        
+        var all_ws = function (store, pea) { // pea == post extended attribute, tpea = same for types
+            var t = { type: &quot;whitespace&quot;, value: &quot;&quot; };
+            while (true) {
+                var w = ws();
+                if (!w) break;
+                t.value += w.value;
+            }
+            if (t.value.length &gt; 0) {
+                if (store) {
+                    var w = t.value
+                    ,   re = {
+                            &quot;ws&quot;:                   /^([\t\n\r ]+)/
+                        ,   &quot;line-comment&quot;:         /^\/\/(.*)\n?/m
+                        ,   &quot;multiline-comment&quot;:    /^\/\*((?:.|\n|\r)*?)\*\//
+                        }
+                    ,   wsTypes = []
+                    ;
+                    for (var k in re) wsTypes.push(k);
+                    while (w.length) {
+                        var matched = false;
+                        for (var i = 0, n = wsTypes.length; i &lt; n; i++) {
+                            var type = wsTypes[i];
+                            w = w.replace(re[type], function (tok, m1) {
+                                store.push({ type: type + (pea ? (&quot;-&quot; + pea) : &quot;&quot;), value: m1 });
+                                matched = true;
+                                return &quot;&quot;;
+                            });
+                            if (matched) break;
+                        }
+                        if (matched) continue;
+                        throw new Error(&quot;Surprising white space construct.&quot;); // this shouldn't happen
+                    }
+                }
+                return t;
+            }
+        };
+        
+        var integer_type = function () {
+            var ret = &quot;&quot;;
+            all_ws();
+            if (consume(ID, &quot;unsigned&quot;)) ret = &quot;unsigned &quot;;
+            all_ws();
+            if (consume(ID, &quot;short&quot;)) return ret + &quot;short&quot;;
+            if (consume(ID, &quot;long&quot;)) {
+                ret += &quot;long&quot;;
+                all_ws();
+                if (consume(ID, &quot;long&quot;)) return ret + &quot; long&quot;;
+                return ret;
+            }
+            if (ret) error(&quot;Failed to parse integer type&quot;);
+        };
+        
+        var float_type = function () {
+            var ret = &quot;&quot;;
+            all_ws();
+            if (consume(ID, &quot;unrestricted&quot;)) ret = &quot;unrestricted &quot;;
+            all_ws();
+            if (consume(ID, &quot;float&quot;)) return ret + &quot;float&quot;;
+            if (consume(ID, &quot;double&quot;)) return ret + &quot;double&quot;;
+            if (ret) error(&quot;Failed to parse float type&quot;);
+        };
+        
+        var primitive_type = function () {
+            var num_type = integer_type() || float_type();
+            if (num_type) return num_type;
+            all_ws();
+            if (consume(ID, &quot;boolean&quot;)) return &quot;boolean&quot;;
+            if (consume(ID, &quot;byte&quot;)) return &quot;byte&quot;;
+            if (consume(ID, &quot;octet&quot;)) return &quot;octet&quot;;
+        };
+        
+        var const_value = function () {
+            if (consume(ID, &quot;true&quot;)) return { type: &quot;boolean&quot;, value: true };
+            if (consume(ID, &quot;false&quot;)) return { type: &quot;boolean&quot;, value: false };
+            if (consume(ID, &quot;null&quot;)) return { type: &quot;null&quot; };
+            if (consume(ID, &quot;Infinity&quot;)) return { type: &quot;Infinity&quot;, negative: false };
+            if (consume(ID, &quot;NaN&quot;)) return { type: &quot;NaN&quot; };
+            var ret = consume(FLOAT) || consume(INT);
+            if (ret) return { type: &quot;number&quot;, value: 1 * ret.value };
+            var tok = consume(OTHER, &quot;-&quot;);
+            if (tok) {
+                if (consume(ID, &quot;Infinity&quot;)) return { type: &quot;Infinity&quot;, negative: true };
+                else tokens.unshift(tok);
+            }
+        };
+        
+        var type_suffix = function (obj) {
+            while (true) {
+                all_ws();
+                if (consume(OTHER, &quot;?&quot;)) {
+                    if (obj.nullable) error(&quot;Can't nullable more than once&quot;);
+                    obj.nullable = true;
+                }
+                else if (consume(OTHER, &quot;[&quot;)) {
+                    all_ws();
+                    consume(OTHER, &quot;]&quot;) || error(&quot;Unterminated array type&quot;);
+                    if (!obj.array) {
+                        obj.array = 1;
+                        obj.nullableArray = [obj.nullable];
+                    }
+                    else {
+                        obj.array++;
+                        obj.nullableArray.push(obj.nullable);
+                    }
+                    obj.nullable = false;
+                }
+                else return;
+            }
+        };
+        
+        var single_type = function () {
+            var prim = primitive_type()
+            ,   ret = { sequence: false, generic: null, nullable: false, array: false, union: false }
+            ,   name
+            ,   value
+            ;
+            if (prim) {
+                ret.idlType = prim;
+            }
+            else if (name = consume(ID)) {
+                value = name.value;
+                all_ws();
+                // Generic types
+                if (consume(OTHER, &quot;&lt;&quot;)) {
+                    // backwards compat
+                    if (value === &quot;sequence&quot;) {
+                        ret.sequence = true;
+                    }
+                    ret.generic = value;
+                    ret.idlType = type() || error(&quot;Error parsing generic type &quot; + value);
+                    all_ws();
+                    if (!consume(OTHER, &quot;&gt;&quot;)) error(&quot;Unterminated generic type &quot; + value);
+                    type_suffix(ret);
+                    return ret;
+                }
+                else {
+                    ret.idlType = value;
+                }
+            }
+            else {
+                return;
+            }
+            type_suffix(ret);
+            if (ret.nullable &amp;&amp; !ret.array &amp;&amp; ret.idlType === &quot;any&quot;) error(&quot;Type any cannot be made nullable&quot;);
+            return ret;
+        };
+        
+        var union_type = function () {
+            all_ws();
+            if (!consume(OTHER, &quot;(&quot;)) return;
+            var ret = { sequence: false, generic: null, nullable: false, array: false, union: true, idlType: [] };
+            var fst = type() || error(&quot;Union type with no content&quot;);
+            ret.idlType.push(fst);
+            while (true) {
+                all_ws();
+                if (!consume(ID, &quot;or&quot;)) break;
+                var typ = type() || error(&quot;No type after 'or' in union type&quot;);
+                ret.idlType.push(typ);
+            }
+            if (!consume(OTHER, &quot;)&quot;)) error(&quot;Unterminated union type&quot;);
+            type_suffix(ret);
+            return ret;
+        };
+        
+        var type = function () {
+            return single_type() || union_type();
+        };
+        
+        var argument = function (store) {
+            var ret = { optional: false, variadic: false };
+            ret.extAttrs = extended_attrs(store);
+            all_ws(store, &quot;pea&quot;);
+            var opt_token = consume(ID, &quot;optional&quot;);
+            if (opt_token) {
+                ret.optional = true;
+                all_ws();
+            }
+            ret.idlType = type();
+            if (!ret.idlType) {
+                if (opt_token) tokens.unshift(opt_token);
+                return;
+            }
+            var type_token = last_token;
+            if (!ret.optional) {
+                all_ws();
+                if (tokens.length &gt;= 3 &amp;&amp;
+                    tokens[0].type === &quot;other&quot; &amp;&amp; tokens[0].value === &quot;.&quot; &amp;&amp;
+                    tokens[1].type === &quot;other&quot; &amp;&amp; tokens[1].value === &quot;.&quot; &amp;&amp;
+                    tokens[2].type === &quot;other&quot; &amp;&amp; tokens[2].value === &quot;.&quot;
+                    ) {
+                    tokens.shift();
+                    tokens.shift();
+                    tokens.shift();
+                    ret.variadic = true;
+                }
+            }
+            all_ws();
+            var name = consume(ID);
+            if (!name) {
+                if (opt_token) tokens.unshift(opt_token);
+                tokens.unshift(type_token);
+                return;
+            }
+            ret.name = name.value;
+            if (ret.optional) {
+                all_ws();
+                ret[&quot;default&quot;] = default_();
+            }
+            return ret;
+        };
+        
+        var argument_list = function (store) {
+            var ret = []
+            ,   arg = argument(store ? ret : null)
+            ;
+            if (!arg) return;
+            ret.push(arg);
+            while (true) {
+                all_ws(store ? ret : null);
+                if (!consume(OTHER, &quot;,&quot;)) return ret;
+                var nxt = argument(store ? ret : null) || error(&quot;Trailing comma in arguments list&quot;);
+                ret.push(nxt);
+            }
+        };
+        
+        var type_pair = function () {
+            all_ws();
+            var k = type();
+            if (!k) return;
+            all_ws()
+            if (!consume(OTHER, &quot;,&quot;)) return;
+            all_ws();
+            var v = type();
+            if (!v) return;
+            return [k, v];
+        };
+        
+        var simple_extended_attr = function (store) {
+            all_ws();
+            var name = consume(ID);
+            if (!name) return;
+            var ret = {
+                name: name.value
+            ,   &quot;arguments&quot;: null
+            };
+            all_ws();
+            var eq = consume(OTHER, &quot;=&quot;);
+            if (eq) {
+                var rhs;
+                all_ws();
+                if (rhs = consume(ID)) {
+                  ret.rhs = rhs
+                }
+                else if (consume(OTHER, &quot;(&quot;)) {
+                    // [Exposed=(Window,Worker)]
+                    rhs = [];
+                    var id = consume(ID);
+                    if (id) {
+                      rhs = [id.value];
+                    }
+                    identifiers(rhs);
+                    consume(OTHER, &quot;)&quot;) || error(&quot;Unexpected token in extended attribute argument list or type pair&quot;);
+                    ret.rhs = {
+                        type: &quot;identifier-list&quot;,
+                        value: rhs
+                    };
+                }
+                if (!ret.rhs) return error(&quot;No right hand side to extended attribute assignment&quot;);
+            }
+            all_ws();
+            if (consume(OTHER, &quot;(&quot;)) {
+                var args, pair;
+                // [Constructor(DOMString str)]
+                if (args = argument_list(store)) {
+                    ret[&quot;arguments&quot;] = args;
+                }
+                // [MapClass(DOMString, DOMString)]
+                else if (pair = type_pair()) {
+                    ret.typePair = pair;
+                }
+                // [Constructor()]
+                else {
+                    ret[&quot;arguments&quot;] = [];
+                }
+                all_ws();
+                consume(OTHER, &quot;)&quot;) || error(&quot;Unexpected token in extended attribute argument list or type pair&quot;);
+            }
+            return ret;
+        };
+        
+        // Note: we parse something simpler than the official syntax. It's all that ever
+        // seems to be used
+        var extended_attrs = function (store) {
+            var eas = [];
+            all_ws(store);
+            if (!consume(OTHER, &quot;[&quot;)) return eas;
+            eas[0] = simple_extended_attr(store) || error(&quot;Extended attribute with not content&quot;);
+            all_ws();
+            while (consume(OTHER, &quot;,&quot;)) {
+                eas.push(simple_extended_attr(store) || error(&quot;Trailing comma in extended attribute&quot;));
+                all_ws();
+            }
+            consume(OTHER, &quot;]&quot;) || error(&quot;No end of extended attribute&quot;);
+            return eas;
+        };
+        
+        var default_ = function () {
+            all_ws();
+            if (consume(OTHER, &quot;=&quot;)) {
+                all_ws();
+                var def = const_value();
+                if (def) {
+                    return def;
+                }
+                else if (consume(OTHER, &quot;[&quot;)) {
+                    if (!consume(OTHER, &quot;]&quot;)) error(&quot;Default sequence value must be empty&quot;);
+                    return { type: &quot;sequence&quot;, value: [] };
+                }
+                else {
+                    var str = consume(STR) || error(&quot;No value for default&quot;);
+                    str.value = str.value.replace(/^&quot;/, &quot;&quot;).replace(/&quot;$/, &quot;&quot;);
+                    return str;
+                }
+            }
+        };
+        
+        var const_ = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            if (!consume(ID, &quot;const&quot;)) return;
+            var ret = { type: &quot;const&quot;, nullable: false };
+            all_ws();
+            var typ = primitive_type();
+            if (!typ) {
+                typ = consume(ID) || error(&quot;No type for const&quot;);
+                typ = typ.value;
+            }
+            ret.idlType = typ;
+            all_ws();
+            if (consume(OTHER, &quot;?&quot;)) {
+                ret.nullable = true;
+                all_ws();
+            }
+            var name = consume(ID) || error(&quot;No name for const&quot;);
+            ret.name = name.value;
+            all_ws();
+            consume(OTHER, &quot;=&quot;) || error(&quot;No value assignment for const&quot;);
+            all_ws();
+            var cnt = const_value();
+            if (cnt) ret.value = cnt;
+            else error(&quot;No value for const&quot;);
+            all_ws();
+            consume(OTHER, &quot;;&quot;) || error(&quot;Unterminated const&quot;);
+            return ret;
+        };
+        
+        var inheritance = function () {
+            all_ws();
+            if (consume(OTHER, &quot;:&quot;)) {
+                all_ws();
+                var inh = consume(ID) || error (&quot;No type in inheritance&quot;);
+                return inh.value;
+            }
+        };
+        
+        var operation_rest = function (ret, store) {
+            all_ws();
+            if (!ret) ret = {};
+            var name = consume(ID);
+            ret.name = name ? name.value : null;
+            all_ws();
+            consume(OTHER, &quot;(&quot;) || error(&quot;Invalid operation&quot;);
+            ret[&quot;arguments&quot;] = argument_list(store) || [];
+            all_ws();
+            consume(OTHER, &quot;)&quot;) || error(&quot;Unterminated operation&quot;);
+            all_ws();
+            consume(OTHER, &quot;;&quot;) || error(&quot;Unterminated operation&quot;);
+            return ret;
+        };
+        
+        var callback = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            var ret;
+            if (!consume(ID, &quot;callback&quot;)) return;
+            all_ws();
+            var tok = consume(ID, &quot;interface&quot;);
+            if (tok) {
+                tokens.unshift(tok);
+                ret = interface_();
+                ret.type = &quot;callback interface&quot;;
+                return ret;
+            }
+            var name = consume(ID) || error(&quot;No name for callback&quot;);
+            ret = { type: &quot;callback&quot;, name: name.value };
+            all_ws();
+            consume(OTHER, &quot;=&quot;) || error(&quot;No assignment in callback&quot;);
+            all_ws();
+            ret.idlType = return_type();
+            all_ws();
+            consume(OTHER, &quot;(&quot;) || error(&quot;No arguments in callback&quot;);
+            ret[&quot;arguments&quot;] = argument_list(store) || [];
+            all_ws();
+            consume(OTHER, &quot;)&quot;) || error(&quot;Unterminated callback&quot;);
+            all_ws();
+            consume(OTHER, &quot;;&quot;) || error(&quot;Unterminated callback&quot;);
+            return ret;
+        };
+
+        var attribute = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            var grabbed = []
+            ,   ret = {
+                type:           &quot;attribute&quot;
+            ,   &quot;static&quot;:       false
+            ,   stringifier:    false
+            ,   inherit:        false
+            ,   readonly:       false
+            };
+            if (consume(ID, &quot;static&quot;)) {
+                ret[&quot;static&quot;] = true;
+                grabbed.push(last_token);
+            }
+            else if (consume(ID, &quot;stringifier&quot;)) {
+                ret.stringifier = true;
+                grabbed.push(last_token);
+            }
+            var w = all_ws();
+            if (w) grabbed.push(w);
+            if (consume(ID, &quot;inherit&quot;)) {
+                if (ret[&quot;static&quot;] || ret.stringifier) error(&quot;Cannot have a static or stringifier inherit&quot;);
+                ret.inherit = true;
+                grabbed.push(last_token);
+                var w = all_ws();
+                if (w) grabbed.push(w);
+            }
+            if (consume(ID, &quot;readonly&quot;)) {
+                ret.readonly = true;
+                grabbed.push(last_token);
+                var w = all_ws();
+                if (w) grabbed.push(w);
+            }
+            if (!consume(ID, &quot;attribute&quot;)) {
+                tokens = grabbed.concat(tokens);
+                return;
+            }
+            all_ws();
+            ret.idlType = type() || error(&quot;No type in attribute&quot;);
+            if (ret.idlType.sequence) error(&quot;Attributes cannot accept sequence types&quot;);
+            all_ws();
+            var name = consume(ID) || error(&quot;No name in attribute&quot;);
+            ret.name = name.value;
+            all_ws();
+            consume(OTHER, &quot;;&quot;) || error(&quot;Unterminated attribute&quot;);
+            return ret;
+        };
+        
+        var return_type = function () {
+            var typ = type();
+            if (!typ) {
+                if (consume(ID, &quot;void&quot;)) {
+                    return &quot;void&quot;;
+                }
+                else error(&quot;No return type&quot;);
+            }
+            return typ;
+        };
+        
+        var operation = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            var ret = {
+                type:           &quot;operation&quot;
+            ,   getter:         false
+            ,   setter:         false
+            ,   creator:        false
+            ,   deleter:        false
+            ,   legacycaller:   false
+            ,   &quot;static&quot;:       false
+            ,   stringifier:    false
+            };
+            while (true) {
+                all_ws();
+                if (consume(ID, &quot;getter&quot;)) ret.getter = true;
+                else if (consume(ID, &quot;setter&quot;)) ret.setter = true;
+                else if (consume(ID, &quot;creator&quot;)) ret.creator = true;
+                else if (consume(ID, &quot;deleter&quot;)) ret.deleter = true;
+                else if (consume(ID, &quot;legacycaller&quot;)) ret.legacycaller = true;
+                else break;
+            }
+            if (ret.getter || ret.setter || ret.creator || ret.deleter || ret.legacycaller) {
+                all_ws();
+                ret.idlType = return_type();
+                operation_rest(ret, store);
+                return ret;
+            }
+            if (consume(ID, &quot;static&quot;)) {
+                ret[&quot;static&quot;] = true;
+                ret.idlType = return_type();
+                operation_rest(ret, store);
+                return ret;
+            }
+            else if (consume(ID, &quot;stringifier&quot;)) {
+                ret.stringifier = true;-
+                all_ws();
+                if (consume(OTHER, &quot;;&quot;)) return ret;
+                ret.idlType = return_type();
+                operation_rest(ret, store);
+                return ret;
+            }
+            ret.idlType = return_type();
+            all_ws();
+            if (consume(ID, &quot;iterator&quot;)) {
+                all_ws();
+                ret.type = &quot;iterator&quot;;
+                if (consume(ID, &quot;object&quot;)) {
+                    ret.iteratorObject = &quot;object&quot;;
+                }
+                else if (consume(OTHER, &quot;=&quot;)) {
+                    all_ws();
+                    var name = consume(ID) || error(&quot;No right hand side in iterator&quot;);
+                    ret.iteratorObject = name.value;
+                }
+                all_ws();
+                consume(OTHER, &quot;;&quot;) || error(&quot;Unterminated iterator&quot;);
+                return ret;
+            }
+            else {
+                operation_rest(ret, store);
+                return ret;
+            }
+        };
+        
+        var identifiers = function (arr) {
+            while (true) {
+                all_ws();
+                if (consume(OTHER, &quot;,&quot;)) {
+                    all_ws();
+                    var name = consume(ID) || error(&quot;Trailing comma in identifiers list&quot;);
+                    arr.push(name.value);
+                }
+                else break;
+            }
+        };
+        
+        var serialiser = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            if (!consume(ID, &quot;serializer&quot;)) return;
+            var ret = { type: &quot;serializer&quot; };
+            all_ws();
+            if (consume(OTHER, &quot;=&quot;)) {
+                all_ws();
+                if (consume(OTHER, &quot;{&quot;)) {
+                    ret.patternMap = true;
+                    all_ws();
+                    var id = consume(ID);
+                    if (id &amp;&amp; id.value === &quot;getter&quot;) {
+                        ret.names = [&quot;getter&quot;];
+                    }
+                    else if (id &amp;&amp; id.value === &quot;inherit&quot;) {
+                        ret.names = [&quot;inherit&quot;];
+                        identifiers(ret.names);
+                    }
+                    else if (id) {
+                        ret.names = [id.value];
+                        identifiers(ret.names);
+                    }
+                    else {
+                        ret.names = [];
+                    }
+                    all_ws();
+                    consume(OTHER, &quot;}&quot;) || error(&quot;Unterminated serializer pattern map&quot;);
+                }
+                else if (consume(OTHER, &quot;[&quot;)) {
+                    ret.patternList = true;
+                    all_ws();
+                    var id = consume(ID);
+                    if (id &amp;&amp; id.value === &quot;getter&quot;) {
+                        ret.names = [&quot;getter&quot;];
+                    }
+                    else if (id) {
+                        ret.names = [id.value];
+                        identifiers(ret.names);
+                    }
+                    else {
+                        ret.names = [];
+                    }
+                    all_ws();
+                    consume(OTHER, &quot;]&quot;) || error(&quot;Unterminated serializer pattern list&quot;);
+                }
+                else {
+                    var name = consume(ID) || error(&quot;Invalid serializer&quot;);
+                    ret.name = name.value;
+                }
+                all_ws();
+                consume(OTHER, &quot;;&quot;) || error(&quot;Unterminated serializer&quot;);
+                return ret;
+            }
+            else if (consume(OTHER, &quot;;&quot;)) {
+                // noop, just parsing
+            }
+            else {
+                ret.idlType = return_type();
+                all_ws();
+                ret.operation = operation_rest(null, store);
+            }
+            return ret;
+        };
+
+        var iterable_type = function() {
+            if (consume(ID, &quot;iterable&quot;)) return &quot;iterable&quot;;
+            else if (consume(ID, &quot;legacyiterable&quot;)) return &quot;legacyiterable&quot;;
+            else if (consume(ID, &quot;maplike&quot;)) return &quot;maplike&quot;;
+            else if (consume(ID, &quot;setlike&quot;)) return &quot;setlike&quot;;
+            else return;
+        }
+
+        var readonly_iterable_type = function() {
+            if (consume(ID, &quot;maplike&quot;)) return &quot;maplike&quot;;
+            else if (consume(ID, &quot;setlike&quot;)) return &quot;setlike&quot;;
+            else return;
+        }
+
+        var iterable = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            var grabbed = [],
+                ret = {type: null, idlType: null, readonly: false};
+            if (consume(ID, &quot;readonly&quot;)) {
+                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 === &quot;maplike&quot;;
+            var secondTypeAllowed = secondTypeRequired || ittype === &quot;iterable&quot;;
+            ret.type = ittype;
+            if (ret.type !== 'maplike' &amp;&amp; ret.type !== 'setlike')
+                delete ret.readonly;
+            all_ws();
+            if (consume(OTHER, &quot;&lt;&quot;)) {
+                ret.idlType = type() || error(&quot;Error parsing &quot; + ittype + &quot; declaration&quot;);
+                all_ws();
+                if (secondTypeAllowed) {
+                    var type2 = null;
+                    if (consume(OTHER, &quot;,&quot;)) {
+                        all_ws();
+                        type2 = type();
+                        all_ws();                        
+                    }
+                    if (type2)
+                        ret.idlType = [ret.idlType, type2];
+                    else if (secondTypeRequired)
+                        error(&quot;Missing second type argument in &quot; + ittype + &quot; declaration&quot;);
+                }
+                if (!consume(OTHER, &quot;&gt;&quot;)) error(&quot;Unterminated &quot; + ittype + &quot; declaration&quot;);
+                all_ws();
+                if (!consume(OTHER, &quot;;&quot;)) error(&quot;Missing semicolon after &quot; + ittype + &quot; declaration&quot;);
+            }
+            else
+                error(&quot;Error parsing &quot; + ittype + &quot; declaration&quot;);
+
+            return ret;            
+        }        
+        
+        var interface_ = function (isPartial, store) {
+            all_ws(isPartial ? null : store, &quot;pea&quot;);
+            if (!consume(ID, &quot;interface&quot;)) return;
+            all_ws();
+            var name = consume(ID) || error(&quot;No name for interface&quot;);
+            var mems = []
+            ,   ret = {
+                type:   &quot;interface&quot;
+            ,   name:   name.value
+            ,   partial:    false
+            ,   members:    mems
+            };
+            if (!isPartial) ret.inheritance = inheritance() || null;
+            all_ws();
+            consume(OTHER, &quot;{&quot;) || error(&quot;Bodyless interface&quot;);
+            while (true) {
+                all_ws(store ? mems : null);
+                if (consume(OTHER, &quot;}&quot;)) {
+                    all_ws();
+                    consume(OTHER, &quot;;&quot;) || error(&quot;Missing semicolon after interface&quot;);
+                    return ret;
+                }
+                var ea = extended_attrs(store ? mems : null);
+                all_ws();
+                var cnt = const_(store ? mems : null);
+                if (cnt) {
+                    cnt.extAttrs = ea;
+                    ret.members.push(cnt);
+                    continue;
+                }
+                var mem = (opt.allowNestedTypedefs &amp;&amp; typedef(store ? mems : null)) ||
+                          iterable(store ? mems : null) ||
+                          serialiser(store ? mems : null) ||
+                          attribute(store ? mems : null) ||
+                          operation(store ? mems : null) ||
+                          error(&quot;Unknown member&quot;);
+                mem.extAttrs = ea;
+                ret.members.push(mem);
+            }
+        };
+        
+        var partial = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            if (!consume(ID, &quot;partial&quot;)) return;
+            var thing = dictionary(true, store) ||
+                        interface_(true, store) ||
+                        error(&quot;Partial doesn't apply to anything&quot;);
+            thing.partial = true;
+            return thing;
+        };
+        
+        var dictionary = function (isPartial, store) {
+            all_ws(isPartial ? null : store, &quot;pea&quot;);
+            if (!consume(ID, &quot;dictionary&quot;)) return;
+            all_ws();
+            var name = consume(ID) || error(&quot;No name for dictionary&quot;);
+            var mems = []
+            ,   ret = {
+                type:   &quot;dictionary&quot;
+            ,   name:   name.value
+            ,   partial:    false
+            ,   members:    mems
+            };
+            if (!isPartial) ret.inheritance = inheritance() || null;
+            all_ws();
+            consume(OTHER, &quot;{&quot;) || error(&quot;Bodyless dictionary&quot;);
+            while (true) {
+                all_ws(store ? mems : null);
+                if (consume(OTHER, &quot;}&quot;)) {
+                    all_ws();
+                    consume(OTHER, &quot;;&quot;) || error(&quot;Missing semicolon after dictionary&quot;);
+                    return ret;
+                }
+                var ea = extended_attrs(store ? mems : null);
+                all_ws(store ? mems : null, &quot;pea&quot;);
+                var required = consume(ID, &quot;required&quot;);
+                var typ = type() || error(&quot;No type for dictionary member&quot;);
+                all_ws();
+                var name = consume(ID) || error(&quot;No name for dictionary member&quot;);
+                var dflt = default_();
+                if (required &amp;&amp; dflt) error(&quot;Required member must not have a default&quot;);
+                ret.members.push({
+                    type:       &quot;field&quot;
+                ,   name:       name.value
+                ,   required:   !!required
+                ,   idlType:    typ
+                ,   extAttrs:   ea
+                ,   &quot;default&quot;:  dflt
+                });
+                all_ws();
+                consume(OTHER, &quot;;&quot;) || error(&quot;Unterminated dictionary member&quot;);
+            }
+        };
+        
+        var exception = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            if (!consume(ID, &quot;exception&quot;)) return;
+            all_ws();
+            var name = consume(ID) || error(&quot;No name for exception&quot;);
+            var mems = []
+            ,   ret = {
+                type:   &quot;exception&quot;
+            ,   name:   name.value
+            ,   members:    mems
+            };
+            ret.inheritance = inheritance() || null;
+            all_ws();
+            consume(OTHER, &quot;{&quot;) || error(&quot;Bodyless exception&quot;);
+            while (true) {
+                all_ws(store ? mems : null);
+                if (consume(OTHER, &quot;}&quot;)) {
+                    all_ws();
+                    consume(OTHER, &quot;;&quot;) || error(&quot;Missing semicolon after exception&quot;);
+                    return ret;
+                }
+                var ea = extended_attrs(store ? mems : null);
+                all_ws(store ? mems : null, &quot;pea&quot;);
+                var cnt = const_();
+                if (cnt) {
+                    cnt.extAttrs = ea;
+                    ret.members.push(cnt);
+                }
+                else {
+                    var typ = type();
+                    all_ws();
+                    var name = consume(ID);
+                    all_ws();
+                    if (!typ || !name || !consume(OTHER, &quot;;&quot;)) error(&quot;Unknown member in exception body&quot;);
+                    ret.members.push({
+                        type:       &quot;field&quot;
+                    ,   name:       name.value
+                    ,   idlType:    typ
+                    ,   extAttrs:   ea
+                    });
+                }
+            }
+        };
+        
+        var enum_ = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            if (!consume(ID, &quot;enum&quot;)) return;
+            all_ws();
+            var name = consume(ID) || error(&quot;No name for enum&quot;);
+            var vals = []
+            ,   ret = {
+                type:   &quot;enum&quot;
+            ,   name:   name.value
+            ,   values: vals
+            };
+            all_ws();
+            consume(OTHER, &quot;{&quot;) || error(&quot;No curly for enum&quot;);
+            var saw_comma = false;
+            while (true) {
+                all_ws(store ? vals : null);
+                if (consume(OTHER, &quot;}&quot;)) {
+                    all_ws();
+                    consume(OTHER, &quot;;&quot;) || error(&quot;No semicolon after enum&quot;);
+                    return ret;
+                }
+                var val = consume(STR) || error(&quot;Unexpected value in enum&quot;);
+                ret.values.push(val.value.replace(/&quot;/g, &quot;&quot;));
+                all_ws(store ? vals : null);
+                if (consume(OTHER, &quot;,&quot;)) {
+                    if (store) vals.push({ type: &quot;,&quot; });
+                    all_ws(store ? vals : null);
+                    saw_comma = true;
+                }
+                else {
+                    saw_comma = false;
+                }
+            }
+        };
+        
+        var typedef = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            if (!consume(ID, &quot;typedef&quot;)) return;
+            var ret = {
+                type:   &quot;typedef&quot;
+            };
+            all_ws();
+            ret.typeExtAttrs = extended_attrs();
+            all_ws(store, &quot;tpea&quot;);
+            ret.idlType = type() || error(&quot;No type in typedef&quot;);
+            all_ws();
+            var name = consume(ID) || error(&quot;No name in typedef&quot;);
+            ret.name = name.value;
+            all_ws();
+            consume(OTHER, &quot;;&quot;) || error(&quot;Unterminated typedef&quot;);
+            return ret;
+        };
+        
+        var implements_ = function (store) {
+            all_ws(store, &quot;pea&quot;);
+            var target = consume(ID);
+            if (!target) return;
+            var w = all_ws();
+            if (consume(ID, &quot;implements&quot;)) {
+                var ret = {
+                    type:   &quot;implements&quot;
+                ,   target: target.value
+                };
+                all_ws();
+                var imp = consume(ID) || error(&quot;Incomplete implements statement&quot;);
+                ret[&quot;implements&quot;] = imp.value;
+                all_ws();
+                consume(OTHER, &quot;;&quot;) || error(&quot;No terminating ; for implements statement&quot;);
+                return ret;
+            }
+            else {
+                // rollback
+                tokens.unshift(w);
+                tokens.unshift(target);
+            }
+        };
+        
+        var definition = function (store) {
+            return  callback(store)             ||
+                    interface_(false, store)    ||
+                    partial(store)              ||
+                    dictionary(false, store)    ||
+                    exception(store)            ||
+                    enum_(store)                ||
+                    typedef(store)              ||
+                    implements_(store)
+                    ;
+        };
+        
+        var definitions = function (store) {
+            if (!tokens.length) return [];
+            var defs = [];
+            while (true) {
+                var ea = extended_attrs(store ? defs : null)
+                ,   def = definition(store ? defs : null);
+                if (!def) {
+                    if (ea.length) error(&quot;Stray extended attributes&quot;);
+                    break;
+                }
+                def.extAttrs = ea;
+                defs.push(def);
+            }
+            return defs;
+        };
+        var res = definitions(opt.ws);
+        if (tokens.length) error(&quot;Unrecognised tokens&quot;);
+        return res;
+    };
+
+    var inNode = typeof module !== &quot;undefined&quot; &amp;&amp; module.exports
+    ,   obj = {
+            parse:  function (str, opt) {
+                if (!opt) opt = {};
+                var tokens = tokenise(str);
+                return parse(tokens, opt);
+            }
+    };
+
+    if (inNode) module.exports = obj;
+    else        self.WebIDL2 = obj;
+}());
</ins></span></pre></div>
<a id="trunkLayoutTestsresourcesidlharnessjsfromrev213080trunkLayoutTestsimportedw3cresourcesidlharnessjs"></a>
<div class="copfile"><h4>Copied: trunk/LayoutTests/resources/idlharness.js (from rev 213080, trunk/LayoutTests/imported/w3c/resources/idlharness.js) (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/resources/idlharness.js                                (rev 0)
+++ trunk/LayoutTests/resources/idlharness.js        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,1968 @@
</span><ins>+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+/* For user documentation see docs/idlharness.md */
+
+/**
+ * Notes for people who want to edit this file (not just use it as a library):
+ *
+ * Most of the interesting stuff happens in the derived classes of IdlObject,
+ * especially IdlInterface.  The entry point for all IdlObjects is .test(),
+ * which is called by IdlArray.test().  An IdlObject is conceptually just
+ * &quot;thing we want to run tests on&quot;, and an IdlArray is an array of IdlObjects
+ * with some additional data thrown in.
+ *
+ * The object model is based on what WebIDLParser.js produces, which is in turn
+ * based on its pegjs grammar.  If you want to figure out what properties an
+ * object will have from WebIDLParser.js, the best way is to look at the
+ * grammar:
+ *
+ *   https://github.com/darobin/webidl.js/blob/master/lib/grammar.peg
+ *
+ * So for instance:
+ *
+ *   // interface definition
+ *   interface
+ *       =   extAttrs:extendedAttributeList? S? &quot;interface&quot; S name:identifier w herit:ifInheritance? w &quot;{&quot; w mem:ifMember* w &quot;}&quot; w &quot;;&quot; w
+ *           { return { type: &quot;interface&quot;, name: name, inheritance: herit, members: mem, extAttrs: extAttrs }; }
+ *
+ * This means that an &quot;interface&quot; object will have a .type property equal to
+ * the string &quot;interface&quot;, a .name property equal to the identifier that the
+ * parser found, an .inheritance property equal to either null or the result of
+ * the &quot;ifInheritance&quot; production found elsewhere in the grammar, and so on.
+ * After each grammatical production is a JavaScript function in curly braces
+ * that gets called with suitable arguments and returns some JavaScript value.
+ *
+ * (Note that the version of WebIDLParser.js we use might sometimes be
+ * out-of-date or forked.)
+ *
+ * The members and methods of the classes defined by this file are all at least
+ * briefly documented, hopefully.
+ */
+(function(){
+&quot;use strict&quot;;
+/// Helpers ///
+function constValue (cnt)
+//@{
+{
+    if (cnt.type === &quot;null&quot;) return null;
+    if (cnt.type === &quot;NaN&quot;) return NaN;
+    if (cnt.type === &quot;Infinity&quot;) return cnt.negative ? -Infinity : Infinity;
+    return cnt.value;
+}
+
+//@}
+function minOverloadLength(overloads)
+//@{
+{
+    if (!overloads.length) {
+        return 0;
+    }
+
+    return overloads.map(function(attr) {
+        return attr.arguments ? attr.arguments.filter(function(arg) {
+            return !arg.optional &amp;&amp; !arg.variadic;
+        }).length : 0;
+    })
+    .reduce(function(m, n) { return Math.min(m, n); });
+}
+
+//@}
+function throwOrReject(a_test, operation, fn, obj, args,  message, cb)
+//@{
+{
+    if (operation.idlType.generic !== &quot;Promise&quot;) {
+        assert_throws(new TypeError(), function() {
+            fn.apply(obj, args);
+        }, message);
+        cb();
+    } else {
+        try {
+            promise_rejects(a_test, new TypeError(), fn.apply(obj, args)).then(cb, cb);
+        } catch (e){
+            a_test.step(function() {
+                assert_unreached(&quot;Throws \&quot;&quot; + e + &quot;\&quot; instead of rejecting promise&quot;);
+                cb();
+            });
+        }
+    }
+}
+
+//@}
+function awaitNCallbacks(n, cb, ctx)
+//@{
+{
+    var counter = 0;
+    return function() {
+        counter++;
+        if (counter &gt;= n) {
+            cb();
+        }
+    };
+}
+
+//@}
+var fround =
+//@{
+(function(){
+    if (Math.fround) return Math.fround;
+
+    var arr = new Float32Array(1);
+    return function fround(n) {
+        arr[0] = n;
+        return arr[0];
+    };
+})();
+//@}
+
+/// IdlArray ///
+// Entry point
+self.IdlArray = function()
+//@{
+{
+    /**
+     * A map from strings to the corresponding named IdlObject, such as
+     * IdlInterface or IdlException.  These are the things that test() will run
+     * tests on.
+     */
+    this.members = {};
+
+    /**
+     * A map from strings to arrays of strings.  The keys are interface or
+     * exception names, and are expected to also exist as keys in this.members
+     * (otherwise they'll be ignored).  This is populated by add_objects() --
+     * see documentation at the start of the file.  The actual tests will be
+     * run by calling this.members[name].test_object(obj) for each obj in
+     * this.objects[name].  obj is a string that will be eval'd to produce a
+     * JavaScript value, which is supposed to be an object implementing the
+     * given IdlObject (interface, exception, etc.).
+     */
+    this.objects = {};
+
+    /**
+     * When adding multiple collections of IDLs one at a time, an earlier one
+     * might contain a partial interface or implements statement that depends
+     * on a later one.  Save these up and handle them right before we run
+     * tests.
+     *
+     * .partials is simply an array of objects from WebIDLParser.js'
+     * &quot;partialinterface&quot; production.  .implements maps strings to arrays of
+     * strings, such that
+     *
+     *   A implements B;
+     *   A implements C;
+     *   D implements E;
+     *
+     * results in { A: [&quot;B&quot;, &quot;C&quot;], D: [&quot;E&quot;] }.
+     */
+    this.partials = [];
+    this[&quot;implements&quot;] = {};
+};
+
+//@}
+IdlArray.prototype.add_idls = function(raw_idls)
+//@{
+{
+    /** Entry point.  See documentation at beginning of file. */
+    this.internal_add_idls(WebIDL2.parse(raw_idls));
+};
+
+//@}
+IdlArray.prototype.add_untested_idls = function(raw_idls)
+//@{
+{
+    /** Entry point.  See documentation at beginning of file. */
+    var parsed_idls = WebIDL2.parse(raw_idls);
+    for (var i = 0; i &lt; parsed_idls.length; i++)
+    {
+        parsed_idls[i].untested = true;
+        if (&quot;members&quot; in parsed_idls[i])
+        {
+            for (var j = 0; j &lt; parsed_idls[i].members.length; j++)
+            {
+                parsed_idls[i].members[j].untested = true;
+            }
+        }
+    }
+    this.internal_add_idls(parsed_idls);
+};
+
+//@}
+IdlArray.prototype.internal_add_idls = function(parsed_idls)
+//@{
+{
+    /**
+     * Internal helper called by add_idls() and add_untested_idls().
+     * parsed_idls is an array of objects that come from WebIDLParser.js's
+     * &quot;definitions&quot; production.  The add_untested_idls() entry point
+     * additionally sets an .untested property on each object (and its
+     * .members) so that they'll be skipped by test() -- they'll only be
+     * used for base interfaces of tested interfaces, return types, etc.
+     */
+    parsed_idls.forEach(function(parsed_idl)
+    {
+        if (parsed_idl.type == &quot;interface&quot; &amp;&amp; parsed_idl.partial)
+        {
+            this.partials.push(parsed_idl);
+            return;
+        }
+
+        if (parsed_idl.type == &quot;implements&quot;)
+        {
+            if (!(parsed_idl.target in this[&quot;implements&quot;]))
+            {
+                this[&quot;implements&quot;][parsed_idl.target] = [];
+            }
+            this[&quot;implements&quot;][parsed_idl.target].push(parsed_idl[&quot;implements&quot;]);
+            return;
+        }
+
+        parsed_idl.array = this;
+        if (parsed_idl.name in this.members)
+        {
+            throw &quot;Duplicate identifier &quot; + parsed_idl.name;
+        }
+        switch(parsed_idl.type)
+        {
+        case &quot;interface&quot;:
+            this.members[parsed_idl.name] =
+                new IdlInterface(parsed_idl, /* is_callback = */ false);
+            break;
+
+        case &quot;dictionary&quot;:
+            // Nothing to test, but we need the dictionary info around for type
+            // checks
+            this.members[parsed_idl.name] = new IdlDictionary(parsed_idl);
+            break;
+
+        case &quot;typedef&quot;:
+            this.members[parsed_idl.name] = new IdlTypedef(parsed_idl);
+            break;
+
+        case &quot;callback&quot;:
+            // TODO
+            console.log(&quot;callback not yet supported&quot;);
+            break;
+
+        case &quot;enum&quot;:
+            this.members[parsed_idl.name] = new IdlEnum(parsed_idl);
+            break;
+
+        case &quot;callback interface&quot;:
+            this.members[parsed_idl.name] =
+                new IdlInterface(parsed_idl, /* is_callback = */ true);
+            break;
+
+        default:
+            throw parsed_idl.name + &quot;: &quot; + parsed_idl.type + &quot; not yet supported&quot;;
+        }
+    }.bind(this));
+};
+
+//@}
+IdlArray.prototype.add_objects = function(dict)
+//@{
+{
+    /** Entry point.  See documentation at beginning of file. */
+    for (var k in dict)
+    {
+        if (k in this.objects)
+        {
+            this.objects[k] = this.objects[k].concat(dict[k]);
+        }
+        else
+        {
+            this.objects[k] = dict[k];
+        }
+    }
+};
+
+//@}
+IdlArray.prototype.prevent_multiple_testing = function(name)
+//@{
+{
+    /** Entry point.  See documentation at beginning of file. */
+    this.members[name].prevent_multiple_testing = true;
+};
+
+//@}
+IdlArray.prototype.recursively_get_implements = function(interface_name)
+//@{
+{
+    /**
+     * Helper function for test().  Returns an array of things that implement
+     * interface_name, so if the IDL contains
+     *
+     *   A implements B;
+     *   B implements C;
+     *   B implements D;
+     *
+     * then recursively_get_implements(&quot;A&quot;) should return [&quot;B&quot;, &quot;C&quot;, &quot;D&quot;].
+     */
+    var ret = this[&quot;implements&quot;][interface_name];
+    if (ret === undefined)
+    {
+        return [];
+    }
+    for (var i = 0; i &lt; this[&quot;implements&quot;][interface_name].length; i++)
+    {
+        ret = ret.concat(this.recursively_get_implements(ret[i]));
+        if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
+        {
+            throw &quot;Circular implements statements involving &quot; + ret[i];
+        }
+    }
+    return ret;
+};
+
+function exposed_in(globals) {
+    if ('document' in self) {
+        return globals.indexOf(&quot;Window&quot;) &gt;= 0;
+    }
+    if ('DedicatedWorkerGlobalScope' in self &amp;&amp;
+        self instanceof DedicatedWorkerGlobalScope) {
+        return globals.indexOf(&quot;Worker&quot;) &gt;= 0 ||
+               globals.indexOf(&quot;DedicatedWorker&quot;) &gt;= 0;
+    }
+    if ('SharedWorkerGlobalScope' in self &amp;&amp;
+        self instanceof SharedWorkerGlobalScope) {
+        return globals.indexOf(&quot;Worker&quot;) &gt;= 0 ||
+               globals.indexOf(&quot;SharedWorker&quot;) &gt;= 0;
+    }
+    if ('ServiceWorkerGlobalScope' in self &amp;&amp;
+        self instanceof ServiceWorkerGlobalScope) {
+        return globals.indexOf(&quot;Worker&quot;) &gt;= 0 ||
+               globals.indexOf(&quot;ServiceWorker&quot;) &gt;= 0;
+    }
+    throw &quot;Unexpected global object&quot;;
+}
+
+//@}
+IdlArray.prototype.test = function()
+//@{
+{
+    /** Entry point.  See documentation at beginning of file. */
+
+    // First merge in all the partial interfaces and implements statements we
+    // encountered.
+    this.partials.forEach(function(parsed_idl)
+    {
+        if (!(parsed_idl.name in this.members)
+        || !(this.members[parsed_idl.name] instanceof IdlInterface))
+        {
+            throw &quot;Partial interface &quot; + parsed_idl.name + &quot; with no original interface&quot;;
+        }
+        if (parsed_idl.extAttrs)
+        {
+            parsed_idl.extAttrs.forEach(function(extAttr)
+            {
+                this.members[parsed_idl.name].extAttrs.push(extAttr);
+            }.bind(this));
+        }
+        parsed_idl.members.forEach(function(member)
+        {
+            this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member));
+        }.bind(this));
+    }.bind(this));
+    this.partials = [];
+
+    for (var lhs in this[&quot;implements&quot;])
+    {
+        this.recursively_get_implements(lhs).forEach(function(rhs)
+        {
+            var errStr = lhs + &quot; implements &quot; + rhs + &quot;, but &quot;;
+            if (!(lhs in this.members)) throw errStr + lhs + &quot; is undefined.&quot;;
+            if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + &quot; is not an interface.&quot;;
+            if (!(rhs in this.members)) throw errStr + rhs + &quot; is undefined.&quot;;
+            if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + &quot; is not an interface.&quot;;
+            this.members[rhs].members.forEach(function(member)
+            {
+                this.members[lhs].members.push(new IdlInterfaceMember(member));
+            }.bind(this));
+        }.bind(this));
+    }
+    this[&quot;implements&quot;] = {};
+
+    Object.getOwnPropertyNames(this.members).forEach(function(memberName) {
+        var member = this.members[memberName];
+        if (!(member instanceof IdlInterface)) {
+            return;
+        }
+
+        var exposed = member.extAttrs.filter(function(a) { return a.name == &quot;Exposed&quot; });
+        if (exposed.length &gt; 1) {
+            throw &quot;Unexpected Exposed extended attributes on &quot; + memberName + &quot;: &quot; + exposed;
+        }
+
+        var globals = exposed.length === 1
+                    ? exposed[0].rhs.value
+                    : [&quot;Window&quot;];
+        member.exposed = exposed_in(globals);
+    }.bind(this));
+
+    // Now run test() on every member, and test_object() for every object.
+    for (var name in this.members)
+    {
+        this.members[name].test();
+        if (name in this.objects)
+        {
+            this.objects[name].forEach(function(str)
+            {
+                this.members[name].test_object(str);
+            }.bind(this));
+        }
+    }
+};
+
+//@}
+IdlArray.prototype.assert_type_is = function(value, type)
+//@{
+{
+    /**
+     * Helper function that tests that value is an instance of type according
+     * to the rules of WebIDL.  value is any JavaScript value, and type is an
+     * object produced by WebIDLParser.js' &quot;type&quot; production.  That production
+     * is fairly elaborate due to the complexity of WebIDL's types, so it's
+     * best to look at the grammar to figure out what properties it might have.
+     */
+    if (type.idlType == &quot;any&quot;)
+    {
+        // No assertions to make
+        return;
+    }
+
+    if (type.nullable &amp;&amp; value === null)
+    {
+        // This is fine
+        return;
+    }
+
+    if (type.array)
+    {
+        // TODO: not supported yet
+        return;
+    }
+
+    if (type.sequence)
+    {
+        assert_true(Array.isArray(value), &quot;is not array&quot;);
+        if (!value.length)
+        {
+            // Nothing we can do.
+            return;
+        }
+        this.assert_type_is(value[0], type.idlType.idlType);
+        return;
+    }
+
+    if (type.generic === &quot;Promise&quot;) {
+        assert_true(&quot;then&quot; in value, &quot;Attribute with a Promise type has a then property&quot;);
+        // TODO: Ideally, we would check on project fulfillment
+        // that we get the right type
+        // but that would require making the type check async
+        return;
+    }
+
+    type = type.idlType;
+
+    switch(type)
+    {
+        case &quot;void&quot;:
+            assert_equals(value, undefined);
+            return;
+
+        case &quot;boolean&quot;:
+            assert_equals(typeof value, &quot;boolean&quot;);
+            return;
+
+        case &quot;byte&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
+            assert_true(-128 &lt;= value &amp;&amp; value &lt;= 127, &quot;byte &quot; + value + &quot; not in range [-128, 127]&quot;);
+            return;
+
+        case &quot;octet&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
+            assert_true(0 &lt;= value &amp;&amp; value &lt;= 255, &quot;octet &quot; + value + &quot; not in range [0, 255]&quot;);
+            return;
+
+        case &quot;short&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
+            assert_true(-32768 &lt;= value &amp;&amp; value &lt;= 32767, &quot;short &quot; + value + &quot; not in range [-32768, 32767]&quot;);
+            return;
+
+        case &quot;unsigned short&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
+            assert_true(0 &lt;= value &amp;&amp; value &lt;= 65535, &quot;unsigned short &quot; + value + &quot; not in range [0, 65535]&quot;);
+            return;
+
+        case &quot;long&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
+            assert_true(-2147483648 &lt;= value &amp;&amp; value &lt;= 2147483647, &quot;long &quot; + value + &quot; not in range [-2147483648, 2147483647]&quot;);
+            return;
+
+        case &quot;unsigned long&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_equals(value, Math.floor(value), &quot;not an integer&quot;);
+            assert_true(0 &lt;= value &amp;&amp; value &lt;= 4294967295, &quot;unsigned long &quot; + value + &quot; not in range [0, 4294967295]&quot;);
+            return;
+
+        case &quot;long long&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            return;
+
+        case &quot;unsigned long long&quot;:
+        case &quot;DOMTimeStamp&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_true(0 &lt;= value, &quot;unsigned long long is negative&quot;);
+            return;
+
+        case &quot;float&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_equals(value, fround(value), &quot;float rounded to 32-bit float should be itself&quot;);
+            assert_not_equals(value, Infinity);
+            assert_not_equals(value, -Infinity);
+            assert_not_equals(value, NaN);
+            return;
+
+        case &quot;DOMHighResTimeStamp&quot;:
+        case &quot;double&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_not_equals(value, Infinity);
+            assert_not_equals(value, -Infinity);
+            assert_not_equals(value, NaN);
+            return;
+
+        case &quot;unrestricted float&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            assert_equals(value, fround(value), &quot;unrestricted float rounded to 32-bit float should be itself&quot;);
+            return;
+
+        case &quot;unrestricted double&quot;:
+            assert_equals(typeof value, &quot;number&quot;);
+            return;
+
+        case &quot;DOMString&quot;:
+            assert_equals(typeof value, &quot;string&quot;);
+            return;
+
+        case &quot;ByteString&quot;:
+            assert_equals(typeof value, &quot;string&quot;);
+            assert_regexp_match(value, /^[\x00-\x7F]*$/);
+            return;
+
+        case &quot;USVString&quot;:
+            assert_equals(typeof value, &quot;string&quot;);
+            assert_regexp_match(value, /^([\x00-\ud7ff\ue000-\uffff]|[\ud800-\udbff][\udc00-\udfff])*$/);
+            return;
+
+        case &quot;object&quot;:
+            assert_true(typeof value == &quot;object&quot; || typeof value == &quot;function&quot;, &quot;wrong type: not object or function&quot;);
+            return;
+    }
+
+    if (!(type in this.members))
+    {
+        throw &quot;Unrecognized type &quot; + type;
+    }
+
+    if (this.members[type] instanceof IdlInterface)
+    {
+        // We don't want to run the full
+        // IdlInterface.prototype.test_instance_of, because that could result
+        // in an infinite loop.  TODO: This means we don't have tests for
+        // NoInterfaceObject interfaces, and we also can't test objects that
+        // come from another self.
+        assert_true(typeof value == &quot;object&quot; || typeof value == &quot;function&quot;, &quot;wrong type: not object or function&quot;);
+        if (value instanceof Object
+        &amp;&amp; !this.members[type].has_extended_attribute(&quot;NoInterfaceObject&quot;)
+        &amp;&amp; type in self)
+        {
+            assert_true(value instanceof self[type], &quot;not instanceof &quot; + type);
+        }
+    }
+    else if (this.members[type] instanceof IdlEnum)
+    {
+        assert_equals(typeof value, &quot;string&quot;);
+    }
+    else if (this.members[type] instanceof IdlDictionary)
+    {
+        // TODO: Test when we actually have something to test this on
+    }
+    else if (this.members[type] instanceof IdlTypedef)
+    {
+        // TODO: Test when we actually have something to test this on
+    }
+    else
+    {
+        throw &quot;Type &quot; + type + &quot; isn't an interface or dictionary&quot;;
+    }
+};
+//@}
+
+/// IdlObject ///
+function IdlObject() {}
+IdlObject.prototype.test = function()
+//@{
+{
+    /**
+     * By default, this does nothing, so no actual tests are run for IdlObjects
+     * that don't define any (e.g., IdlDictionary at the time of this writing).
+     */
+};
+
+//@}
+IdlObject.prototype.has_extended_attribute = function(name)
+//@{
+{
+    /**
+     * This is only meaningful for things that support extended attributes,
+     * such as interfaces, exceptions, and members.
+     */
+    return this.extAttrs.some(function(o)
+    {
+        return o.name == name;
+    });
+};
+
+//@}
+
+/// IdlDictionary ///
+// Used for IdlArray.prototype.assert_type_is
+function IdlDictionary(obj)
+//@{
+{
+    /**
+     * obj is an object produced by the WebIDLParser.js &quot;dictionary&quot;
+     * production.
+     */
+
+    /** Self-explanatory. */
+    this.name = obj.name;
+
+    /** An array of objects produced by the &quot;dictionaryMember&quot; production. */
+    this.members = obj.members;
+
+    /**
+     * The name (as a string) of the dictionary type we inherit from, or null
+     * if there is none.
+     */
+    this.base = obj.inheritance;
+}
+
+//@}
+IdlDictionary.prototype = Object.create(IdlObject.prototype);
+
+/// IdlInterface ///
+function IdlInterface(obj, is_callback)
+//@{
+{
+    /**
+     * obj is an object produced by the WebIDLParser.js &quot;interface&quot; production.
+     */
+
+    /** Self-explanatory. */
+    this.name = obj.name;
+
+    /** A back-reference to our IdlArray. */
+    this.array = obj.array;
+
+    /**
+     * An indicator of whether we should run tests on the interface object and
+     * interface prototype object. Tests on members are controlled by .untested
+     * on each member, not this.
+     */
+    this.untested = obj.untested;
+
+    /** An array of objects produced by the &quot;ExtAttr&quot; production. */
+    this.extAttrs = obj.extAttrs;
+
+    /** An array of IdlInterfaceMembers. */
+    this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); });
+    if (this.has_extended_attribute(&quot;Unforgeable&quot;)) {
+        this.members
+            .filter(function(m) { return !m[&quot;static&quot;] &amp;&amp; (m.type == &quot;attribute&quot; || m.type == &quot;operation&quot;); })
+            .forEach(function(m) { return m.isUnforgeable = true; });
+    }
+
+    /**
+     * The name (as a string) of the type we inherit from, or null if there is
+     * none.
+     */
+    this.base = obj.inheritance;
+
+    this._is_callback = is_callback;
+}
+//@}
+IdlInterface.prototype = Object.create(IdlObject.prototype);
+IdlInterface.prototype.is_callback = function()
+//@{
+{
+    return this._is_callback;
+};
+//@}
+
+IdlInterface.prototype.has_constants = function()
+//@{
+{
+    return this.members.some(function(member) {
+        return member.type === &quot;const&quot;;
+    });
+};
+//@}
+
+IdlInterface.prototype.is_global = function()
+//@{
+{
+    return this.extAttrs.some(function(attribute) {
+        return attribute.name === &quot;Global&quot; ||
+               attribute.name === &quot;PrimaryGlobal&quot;;
+    });
+};
+//@}
+
+IdlInterface.prototype.test = function()
+//@{
+{
+    if (this.has_extended_attribute(&quot;NoInterfaceObject&quot;))
+    {
+        // No tests to do without an instance.  TODO: We should still be able
+        // to run tests on the prototype object, if we obtain one through some
+        // other means.
+        return;
+    }
+
+    if (!this.exposed) {
+        test(function() {
+            assert_false(this.name in self);
+        }.bind(this), this.name + &quot; interface: existence and properties of interface object&quot;);
+        return;
+    }
+
+    if (!this.untested)
+    {
+        // First test things to do with the exception/interface object and
+        // exception/interface prototype object.
+        this.test_self();
+    }
+    // Then test things to do with its members (constants, fields, attributes,
+    // operations, . . .).  These are run even if .untested is true, because
+    // members might themselves be marked as .untested.  This might happen to
+    // interfaces if the interface itself is untested but a partial interface
+    // that extends it is tested -- then the interface itself and its initial
+    // members will be marked as untested, but the members added by the partial
+    // interface are still tested.
+    this.test_members();
+};
+//@}
+
+IdlInterface.prototype.test_self = function()
+//@{
+{
+    test(function()
+    {
+        // This function tests WebIDL as of 2015-01-13.
+
+        // &quot;For every interface that is exposed in a given ECMAScript global
+        // environment and:
+        // * is a callback interface that has constants declared on it, or
+        // * is a non-callback interface that is not declared with the
+        //   [NoInterfaceObject] extended attribute,
+        // a corresponding property MUST exist on the ECMAScript global object.
+        // The name of the property is the identifier of the interface, and its
+        // value is an object called the interface object.
+        // The property has the attributes { [[Writable]]: true,
+        // [[Enumerable]]: false, [[Configurable]]: true }.&quot;
+        if (this.is_callback() &amp;&amp; !this.has_constants()) {
+            return;
+        }
+
+        // TODO: Should we test here that the property is actually writable
+        // etc., or trust getOwnPropertyDescriptor?
+        assert_own_property(self, this.name,
+                            &quot;self does not have own property &quot; + format_value(this.name));
+        var desc = Object.getOwnPropertyDescriptor(self, this.name);
+        assert_false(&quot;get&quot; in desc, &quot;self's property &quot; + format_value(this.name) + &quot; has getter&quot;);
+        assert_false(&quot;set&quot; in desc, &quot;self's property &quot; + format_value(this.name) + &quot; has setter&quot;);
+        assert_true(desc.writable, &quot;self's property &quot; + format_value(this.name) + &quot; is not writable&quot;);
+        assert_false(desc.enumerable, &quot;self's property &quot; + format_value(this.name) + &quot; is enumerable&quot;);
+        assert_true(desc.configurable, &quot;self's property &quot; + format_value(this.name) + &quot; is not configurable&quot;);
+
+        if (this.is_callback()) {
+            // &quot;The internal [[Prototype]] property of an interface object for
+            // a callback interface must be the Function.prototype object.&quot;
+            assert_equals(Object.getPrototypeOf(self[this.name]), Function.prototype,
+                          &quot;prototype of self's property &quot; + format_value(this.name) + &quot; is not Object.prototype&quot;);
+
+            return;
+        }
+
+        // &quot;The interface object for a given non-callback interface is a
+        // function object.&quot;
+        // &quot;If an object is defined to be a function object, then it has
+        // characteristics as follows:&quot;
+
+        // Its [[Prototype]] internal property is otherwise specified (see
+        // below).
+
+        // &quot;* Its [[Get]] internal property is set as described in ECMA-262
+        //    section 9.1.8.&quot;
+        // Not much to test for this.
+
+        // &quot;* Its [[Construct]] internal property is set as described in
+        //    ECMA-262 section 19.2.2.3.&quot;
+        // Tested below if no constructor is defined.  TODO: test constructors
+        // if defined.
+
+        // &quot;* Its @@hasInstance property is set as described in ECMA-262
+        //    section 19.2.3.8, unless otherwise specified.&quot;
+        // TODO
+
+        // ES6 (rev 30) 19.1.3.6:
+        // &quot;Else, if O has a [[Call]] internal method, then let builtinTag be
+        // &quot;Function&quot;.&quot;
+        assert_class_string(self[this.name], &quot;Function&quot;, &quot;class string of &quot; + this.name);
+
+        // &quot;The [[Prototype]] internal property of an interface object for a
+        // non-callback interface is determined as follows:&quot;
+        var prototype = Object.getPrototypeOf(self[this.name]);
+        if (this.base) {
+            // &quot;* If the interface inherits from some other interface, the
+            //    value of [[Prototype]] is the interface object for that other
+            //    interface.&quot;
+            var has_interface_object =
+                !this.array
+                     .members[this.base]
+                     .has_extended_attribute(&quot;NoInterfaceObject&quot;);
+            if (has_interface_object) {
+                assert_own_property(self, this.base,
+                                    'should inherit from ' + this.base +
+                                    ', but self has no such property');
+                assert_equals(prototype, self[this.base],
+                              'prototype of ' + this.name + ' is not ' +
+                              this.base);
+            }
+        } else {
+            // &quot;If the interface doesn't inherit from any other interface, the
+            // value of [[Prototype]] is %FunctionPrototype% ([ECMA-262],
+            // section 6.1.7.4).&quot;
+            assert_equals(prototype, Function.prototype,
+                          &quot;prototype of self's property &quot; + format_value(this.name) + &quot; is not Function.prototype&quot;);
+        }
+
+        if (!this.has_extended_attribute(&quot;Constructor&quot;)) {
+            // &quot;The internal [[Call]] method of the interface object behaves as
+            // follows . . .
+            //
+            // &quot;If I was not declared with a [Constructor] extended attribute,
+            // then throw a TypeError.&quot;
+            assert_throws(new TypeError(), function() {
+                self[this.name]();
+            }.bind(this), &quot;interface object didn't throw TypeError when called as a function&quot;);
+            assert_throws(new TypeError(), function() {
+                new self[this.name]();
+            }.bind(this), &quot;interface object didn't throw TypeError when called as a constructor&quot;);
+        }
+    }.bind(this), this.name + &quot; interface: existence and properties of interface object&quot;);
+
+    if (!this.is_callback()) {
+        test(function() {
+            // This function tests WebIDL as of 2014-10-25.
+            // https://heycam.github.io/webidl/#es-interface-call
+
+            assert_own_property(self, this.name,
+                                &quot;self does not have own property &quot; + format_value(this.name));
+
+            // &quot;Interface objects for non-callback interfaces MUST have a
+            // property named “length” with attributes { [[Writable]]: false,
+            // [[Enumerable]]: false, [[Configurable]]: true } whose value is
+            // a Number.&quot;
+            assert_own_property(self[this.name], &quot;length&quot;);
+            var desc = Object.getOwnPropertyDescriptor(self[this.name], &quot;length&quot;);
+            assert_false(&quot;get&quot; in desc, this.name + &quot;.length has getter&quot;);
+            assert_false(&quot;set&quot; in desc, this.name + &quot;.length has setter&quot;);
+            assert_false(desc.writable, this.name + &quot;.length is writable&quot;);
+            assert_false(desc.enumerable, this.name + &quot;.length is enumerable&quot;);
+            assert_true(desc.configurable, this.name + &quot;.length is not configurable&quot;);
+
+            var constructors = this.extAttrs
+                .filter(function(attr) { return attr.name == &quot;Constructor&quot;; });
+            var expected_length = minOverloadLength(constructors);
+            assert_equals(self[this.name].length, expected_length, &quot;wrong value for &quot; + this.name + &quot;.length&quot;);
+        }.bind(this), this.name + &quot; interface object length&quot;);
+    }
+
+    if (!this.is_callback() || this.has_constants()) {
+        test(function() {
+            // This function tests WebIDL as of 2015-11-17.
+            // https://heycam.github.io/webidl/#interface-object
+
+            assert_own_property(self, this.name,
+                                &quot;self does not have own property &quot; + format_value(this.name));
+
+            // &quot;All interface objects must have a property named “name” with
+            // attributes { [[Writable]]: false, [[Enumerable]]: false,
+            // [[Configurable]]: true } whose value is the identifier of the
+            // corresponding interface.&quot;
+
+            assert_own_property(self[this.name], &quot;name&quot;);
+            var desc = Object.getOwnPropertyDescriptor(self[this.name], &quot;name&quot;);
+            assert_false(&quot;get&quot; in desc, this.name + &quot;.name has getter&quot;);
+            assert_false(&quot;set&quot; in desc, this.name + &quot;.name has setter&quot;);
+            assert_false(desc.writable, this.name + &quot;.name is writable&quot;);
+            assert_false(desc.enumerable, this.name + &quot;.name is enumerable&quot;);
+            assert_true(desc.configurable, this.name + &quot;.name is not configurable&quot;);
+            assert_equals(self[this.name].name, this.name, &quot;wrong value for &quot; + this.name + &quot;.name&quot;);
+        }.bind(this), this.name + &quot; interface object name&quot;);
+    }
+
+    // TODO: Test named constructors if I find any interfaces that have them.
+
+    test(function()
+    {
+        // This function tests WebIDL as of 2015-01-21.
+        // https://heycam.github.io/webidl/#interface-object
+
+        if (this.is_callback() &amp;&amp; !this.has_constants()) {
+            return;
+        }
+
+        assert_own_property(self, this.name,
+                            &quot;self does not have own property &quot; + format_value(this.name));
+
+        if (this.is_callback()) {
+            assert_false(&quot;prototype&quot; in self[this.name],
+                         this.name + ' should not have a &quot;prototype&quot; property');
+            return;
+        }
+
+        // &quot;An interface object for a non-callback interface must have a
+        // property named “prototype” with attributes { [[Writable]]: false,
+        // [[Enumerable]]: false, [[Configurable]]: false } whose value is an
+        // object called the interface prototype object. This object has
+        // properties that correspond to the regular attributes and regular
+        // operations defined on the interface, and is described in more detail
+        // in section 4.5.4 below.&quot;
+        assert_own_property(self[this.name], &quot;prototype&quot;,
+                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
+        var desc = Object.getOwnPropertyDescriptor(self[this.name], &quot;prototype&quot;);
+        assert_false(&quot;get&quot; in desc, this.name + &quot;.prototype has getter&quot;);
+        assert_false(&quot;set&quot; in desc, this.name + &quot;.prototype has setter&quot;);
+        assert_false(desc.writable, this.name + &quot;.prototype is writable&quot;);
+        assert_false(desc.enumerable, this.name + &quot;.prototype is enumerable&quot;);
+        assert_false(desc.configurable, this.name + &quot;.prototype is configurable&quot;);
+
+        // Next, test that the [[Prototype]] of the interface prototype object
+        // is correct. (This is made somewhat difficult by the existence of
+        // [NoInterfaceObject].)
+        // TODO: Aryeh thinks there's at least other place in this file where
+        //       we try to figure out if an interface prototype object is
+        //       correct. Consolidate that code.
+
+        // &quot;The interface prototype object for a given interface A must have an
+        // internal [[Prototype]] property whose value is returned from the
+        // following steps:
+        // &quot;If A is declared with the [Global] or [PrimaryGlobal] extended
+        // attribute, and A supports named properties, then return the named
+        // properties object for A, as defined in section 4.5.5 below.
+        // &quot;Otherwise, if A is declared to inherit from another interface, then
+        // return the interface prototype object for the inherited interface.
+        // &quot;Otherwise, if A is declared with the [ArrayClass] extended
+        // attribute, then return %ArrayPrototype% ([ECMA-262], section
+        // 6.1.7.4).
+        // &quot;Otherwise, return %ObjectPrototype% ([ECMA-262], section 6.1.7.4).
+        // ([ECMA-262], section 15.2.4).
+        if (this.name === &quot;Window&quot;) {
+            assert_class_string(Object.getPrototypeOf(self[this.name].prototype),
+                                'WindowProperties',
+                                'Class name for prototype of Window' +
+                                '.prototype is not &quot;WindowProperties&quot;');
+        } else {
+            var inherit_interface, inherit_interface_has_interface_object;
+            if (this.base) {
+                inherit_interface = this.base;
+                inherit_interface_has_interface_object =
+                    !this.array
+                         .members[inherit_interface]
+                         .has_extended_attribute(&quot;NoInterfaceObject&quot;);
+            } else if (this.has_extended_attribute('ArrayClass')) {
+                inherit_interface = 'Array';
+                inherit_interface_has_interface_object = true;
+            } else {
+                inherit_interface = 'Object';
+                inherit_interface_has_interface_object = true;
+            }
+            if (inherit_interface_has_interface_object) {
+                assert_own_property(self, inherit_interface,
+                                    'should inherit from ' + inherit_interface + ', but self has no such property');
+                assert_own_property(self[inherit_interface], 'prototype',
+                                    'should inherit from ' + inherit_interface + ', but that object has no &quot;prototype&quot; property');
+                assert_equals(Object.getPrototypeOf(self[this.name].prototype),
+                              self[inherit_interface].prototype,
+                              'prototype of ' + this.name + '.prototype is not ' + inherit_interface + '.prototype');
+            } else {
+                // We can't test that we get the correct object, because this is the
+                // only way to get our hands on it. We only test that its class
+                // string, at least, is correct.
+                assert_class_string(Object.getPrototypeOf(self[this.name].prototype),
+                                    inherit_interface + 'Prototype',
+                                    'Class name for prototype of ' + this.name +
+                                    '.prototype is not &quot;' + inherit_interface + 'Prototype&quot;');
+            }
+        }
+
+        // &quot;The class string of an interface prototype object is the
+        // concatenation of the interface’s identifier and the string
+        // “Prototype”.&quot;
+        assert_class_string(self[this.name].prototype, this.name + &quot;Prototype&quot;,
+                            &quot;class string of &quot; + this.name + &quot;.prototype&quot;);
+        // String() should end up calling {}.toString if nothing defines a
+        // stringifier.
+        if (!this.has_stringifier()) {
+            assert_equals(String(self[this.name].prototype), &quot;[object &quot; + this.name + &quot;Prototype]&quot;,
+                    &quot;String(&quot; + this.name + &quot;.prototype)&quot;);
+        }
+    }.bind(this), this.name + &quot; interface: existence and properties of interface prototype object&quot;);
+
+    test(function()
+    {
+        if (this.is_callback() &amp;&amp; !this.has_constants()) {
+            return;
+        }
+
+        assert_own_property(self, this.name,
+                            &quot;self does not have own property &quot; + format_value(this.name));
+
+        if (this.is_callback()) {
+            assert_false(&quot;prototype&quot; in self[this.name],
+                         this.name + ' should not have a &quot;prototype&quot; property');
+            return;
+        }
+
+        assert_own_property(self[this.name], &quot;prototype&quot;,
+                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
+
+        // &quot;If the [NoInterfaceObject] extended attribute was not specified on
+        // the interface, then the interface prototype object must also have a
+        // property named “constructor” with attributes { [[Writable]]: true,
+        // [[Enumerable]]: false, [[Configurable]]: true } whose value is a
+        // reference to the interface object for the interface.&quot;
+        assert_own_property(self[this.name].prototype, &quot;constructor&quot;,
+                            this.name + '.prototype does not have own property &quot;constructor&quot;');
+        var desc = Object.getOwnPropertyDescriptor(self[this.name].prototype, &quot;constructor&quot;);
+        assert_false(&quot;get&quot; in desc, this.name + &quot;.prototype.constructor has getter&quot;);
+        assert_false(&quot;set&quot; in desc, this.name + &quot;.prototype.constructor has setter&quot;);
+        assert_true(desc.writable, this.name + &quot;.prototype.constructor is not writable&quot;);
+        assert_false(desc.enumerable, this.name + &quot;.prototype.constructor is enumerable&quot;);
+        assert_true(desc.configurable, this.name + &quot;.prototype.constructor in not configurable&quot;);
+        assert_equals(self[this.name].prototype.constructor, self[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 &quot;constructor&quot; property');
+};
+
+//@}
+IdlInterface.prototype.test_member_const = function(member)
+//@{
+{
+    if (!this.has_constants()) {
+        throw &quot;Internal error: test_member_const called without any constants&quot;;
+    }
+
+    test(function()
+    {
+        assert_own_property(self, this.name,
+                            &quot;self does not have own property &quot; + format_value(this.name));
+
+        // &quot;For each constant defined on an interface A, there must be
+        // a corresponding property on the interface object, if it
+        // exists.&quot;
+        assert_own_property(self[this.name], member.name);
+        // &quot;The value of the property is that which is obtained by
+        // converting the constant’s IDL value to an ECMAScript
+        // value.&quot;
+        assert_equals(self[this.name][member.name], constValue(member.value),
+                      &quot;property has wrong value&quot;);
+        // &quot;The property has attributes { [[Writable]]: false,
+        // [[Enumerable]]: true, [[Configurable]]: false }.&quot;
+        var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);
+        assert_false(&quot;get&quot; in desc, &quot;property has getter&quot;);
+        assert_false(&quot;set&quot; in desc, &quot;property has setter&quot;);
+        assert_false(desc.writable, &quot;property is writable&quot;);
+        assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
+        assert_false(desc.configurable, &quot;property is configurable&quot;);
+    }.bind(this), this.name + &quot; interface: constant &quot; + member.name + &quot; on interface object&quot;);
+
+    // &quot;In addition, a property with the same characteristics must
+    // exist on the interface prototype object.&quot;
+    test(function()
+    {
+        assert_own_property(self, this.name,
+                            &quot;self does not have own property &quot; + format_value(this.name));
+
+        if (this.is_callback()) {
+            assert_false(&quot;prototype&quot; in self[this.name],
+                         this.name + ' should not have a &quot;prototype&quot; property');
+            return;
+        }
+
+        assert_own_property(self[this.name], &quot;prototype&quot;,
+                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
+
+        assert_own_property(self[this.name].prototype, member.name);
+        assert_equals(self[this.name].prototype[member.name], constValue(member.value),
+                      &quot;property has wrong value&quot;);
+        var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);
+        assert_false(&quot;get&quot; in desc, &quot;property has getter&quot;);
+        assert_false(&quot;set&quot; in desc, &quot;property has setter&quot;);
+        assert_false(desc.writable, &quot;property is writable&quot;);
+        assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
+        assert_false(desc.configurable, &quot;property is configurable&quot;);
+    }.bind(this), this.name + &quot; interface: constant &quot; + member.name + &quot; on interface prototype object&quot;);
+};
+
+
+//@}
+IdlInterface.prototype.test_member_attribute = function(member)
+//@{
+  {
+    var a_test = async_test(this.name + &quot; interface: attribute &quot; + member.name);
+    a_test.step(function()
+    {
+        if (this.is_callback() &amp;&amp; !this.has_constants()) {
+            a_test.done()
+            return;
+        }
+
+        assert_own_property(self, this.name,
+                            &quot;self does not have own property &quot; + format_value(this.name));
+        assert_own_property(self[this.name], &quot;prototype&quot;,
+                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
+
+        if (member[&quot;static&quot;]) {
+            assert_own_property(self[this.name], member.name,
+                &quot;The interface object must have a property &quot; +
+                format_value(member.name));
+            a_test.done();
+        } else if (this.is_global()) {
+            assert_own_property(self, member.name,
+                &quot;The global object must have a property &quot; +
+                format_value(member.name));
+            assert_false(member.name in self[this.name].prototype,
+                &quot;The prototype object must not have a property &quot; +
+                format_value(member.name));
+
+            var getter = Object.getOwnPropertyDescriptor(self, member.name).get;
+            assert_equals(typeof(getter), &quot;function&quot;,
+                          format_value(member.name) + &quot; must have a getter&quot;);
+
+            // Try/catch around the get here, since it can legitimately throw.
+            // If it does, we obviously can't check for equality with direct
+            // invocation of the getter.
+            var gotValue;
+            var propVal;
+            try {
+                propVal = self[member.name];
+                gotValue = true;
+            } catch (e) {
+                gotValue = false;
+            }
+            if (gotValue) {
+                assert_equals(propVal, getter.call(undefined),
+                              &quot;Gets on a global should not require an explicit this&quot;);
+            }
+
+            // do_interface_attribute_asserts must be the last thing we do,
+            // since it will call done() on a_test.
+            this.do_interface_attribute_asserts(self, member, a_test);
+        } else {
+            assert_true(member.name in self[this.name].prototype,
+                &quot;The prototype object must have a property &quot; +
+                format_value(member.name));
+
+            if (!member.has_extended_attribute(&quot;LenientThis&quot;)) {
+                if (member.idlType.generic !== &quot;Promise&quot;) {
+                    assert_throws(new TypeError(), function() {
+                        self[this.name].prototype[member.name];
+                    }.bind(this), &quot;getting property on prototype object must throw TypeError&quot;);
+                    // do_interface_attribute_asserts must be the last thing we
+                    // do, since it will call done() on a_test.
+                    this.do_interface_attribute_asserts(self[this.name].prototype, member, a_test);
+                } else {
+                    promise_rejects(a_test, new TypeError(),
+                                    self[this.name].prototype[member.name])
+                        .then(function() {
+                            // do_interface_attribute_asserts must be the last
+                            // thing we do, since it will call done() on a_test.
+                            this.do_interface_attribute_asserts(self[this.name].prototype,
+                                                                member, a_test);
+                        }.bind(this));
+                }
+            } else {
+                assert_equals(self[this.name].prototype[member.name], undefined,
+                              &quot;getting property on prototype object must return undefined&quot;);
+              // do_interface_attribute_asserts must be the last thing we do,
+              // since it will call done() on a_test.
+              this.do_interface_attribute_asserts(self[this.name].prototype, member, a_test);
+            }
+
+        }
+    }.bind(this));
+};
+
+//@}
+IdlInterface.prototype.test_member_operation = function(member)
+//@{
+{
+    var a_test = async_test(this.name + &quot; interface: operation &quot; + member.name +
+                            &quot;(&quot; + member.arguments.map(
+                                function(m) {return m.idlType.idlType; } )
+                            +&quot;)&quot;);
+    a_test.step(function()
+    {
+        // This function tests WebIDL as of 2015-12-29.
+        // https://heycam.github.io/webidl/#es-operations
+
+        if (this.is_callback() &amp;&amp; !this.has_constants()) {
+            a_test.done();
+            return;
+        }
+
+        assert_own_property(self, this.name,
+                            &quot;self does not have own property &quot; + format_value(this.name));
+
+        if (this.is_callback()) {
+            assert_false(&quot;prototype&quot; in self[this.name],
+                         this.name + ' should not have a &quot;prototype&quot; property');
+            a_test.done();
+            return;
+        }
+
+        assert_own_property(self[this.name], &quot;prototype&quot;,
+                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
+
+        // &quot;For each unique identifier of an exposed operation defined on the
+        // interface, there must exist a corresponding property, unless the
+        // effective overload set for that identifier and operation and with an
+        // argument count of 0 has no entries.&quot;
+
+        // TODO: Consider [Exposed].
+
+        // &quot;The location of the property is determined as follows:&quot;
+        var memberHolderObject;
+        // &quot;* If the operation is static, then the property exists on the
+        //    interface object.&quot;
+        if (member[&quot;static&quot;]) {
+            assert_own_property(self[this.name], member.name,
+                    &quot;interface object missing static operation&quot;);
+            memberHolderObject = self[this.name];
+        // &quot;* Otherwise, [...] if the interface was declared with the [Global]
+        //    or [PrimaryGlobal] extended attribute, then the property exists
+        //    on every object that implements the interface.&quot;
+        } else if (this.is_global()) {
+            assert_own_property(self, member.name,
+                    &quot;global object missing non-static operation&quot;);
+            memberHolderObject = self;
+        // &quot;* Otherwise, the property exists solely on the interface’s
+        //    interface prototype object.&quot;
+        } else {
+            assert_own_property(self[this.name].prototype, member.name,
+                    &quot;interface prototype object missing non-static operation&quot;);
+            memberHolderObject = self[this.name].prototype;
+        }
+        this.do_member_operation_asserts(memberHolderObject, member, a_test);
+    }.bind(this));
+};
+
+//@}
+IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject, member, a_test)
+//@{
+{
+    var done = a_test.done.bind(a_test);
+    var operationUnforgeable = member.isUnforgeable;
+    var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);
+    // &quot;The property has attributes { [[Writable]]: B,
+    // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
+    // operation is unforgeable on the interface, and true otherwise&quot;.
+    assert_false(&quot;get&quot; in desc, &quot;property has getter&quot;);
+    assert_false(&quot;set&quot; in desc, &quot;property has setter&quot;);
+    assert_equals(desc.writable, !operationUnforgeable,
+                  &quot;property should be writable if and only if not unforgeable&quot;);
+    assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
+    assert_equals(desc.configurable, !operationUnforgeable,
+                  &quot;property should be configurable if and only if not unforgeable&quot;);
+    // &quot;The value of the property is a Function object whose
+    // behavior is as follows . . .&quot;
+    assert_equals(typeof memberHolderObject[member.name], &quot;function&quot;,
+                  &quot;property must be a function&quot;);
+    // &quot;The value of the Function object’s “length” property is
+    // a Number determined as follows:
+    // &quot;. . .
+    // &quot;Return the length of the shortest argument list of the
+    // entries in S.&quot;
+    assert_equals(memberHolderObject[member.name].length,
+        minOverloadLength(this.members.filter(function(m) {
+            return m.type == &quot;operation&quot; &amp;&amp; m.name == member.name;
+        })),
+        &quot;property has wrong .length&quot;);
+
+    // Make some suitable arguments
+    var args = member.arguments.map(function(arg) {
+        return create_suitable_object(arg.idlType);
+    });
+
+    // &quot;Let O be a value determined as follows:
+    // &quot;. . .
+    // &quot;Otherwise, throw a TypeError.&quot;
+    // This should be hit if the operation is not static, there is
+    // no [ImplicitThis] attribute, and the this value is null.
+    //
+    // TODO: We currently ignore the [ImplicitThis] case.  Except we manually
+    // check for globals, since otherwise we'll invoke window.close().  And we
+    // have to skip this test for anything that on the proto chain of &quot;self&quot;,
+    // since that does in fact have implicit-this behavior.
+    if (!member[&quot;static&quot;]) {
+        var cb;
+        if (!this.is_global() &amp;&amp;
+            memberHolderObject[member.name] != self[member.name])
+        {
+            cb = awaitNCallbacks(2, done);
+            throwOrReject(a_test, member, memberHolderObject[member.name], null, args,
+                          &quot;calling operation with this = null didn't throw TypeError&quot;, cb);
+        } else {
+            cb = awaitNCallbacks(1, done);
+        }
+
+        // &quot;. . . If O is not null and is also not a platform object
+        // that implements interface I, throw a TypeError.&quot;
+        //
+        // TODO: Test a platform object that implements some other
+        // interface.  (Have to be sure to get inheritance right.)
+        throwOrReject(a_test, member, memberHolderObject[member.name], {}, args,
+                      &quot;calling operation with this = {} didn't throw TypeError&quot;, cb);
+    } else {
+        done();
+    }
+}
+
+//@}
+IdlInterface.prototype.add_iterable_members = function(member)
+//@{
+{
+    this.members.push({type: &quot;operation&quot;, name: &quot;entries&quot;, idlType: &quot;iterator&quot;, arguments: []});
+    this.members.push({type: &quot;operation&quot;, name: &quot;keys&quot;, idlType: &quot;iterator&quot;, arguments: []});
+    this.members.push({type: &quot;operation&quot;, name: &quot;values&quot;, idlType: &quot;iterator&quot;, arguments: []});
+    this.members.push({type: &quot;operation&quot;, name: &quot;forEach&quot;, idlType: &quot;void&quot;, arguments:
+        [{ name: &quot;callback&quot;, idlType: {idlType: &quot;function&quot;}},
+        { name: &quot;thisValue&quot;, idlType: {idlType: &quot;any&quot;}, optional: true}]});
+};
+
+//@}
+IdlInterface.prototype.test_member_iterable = function(member)
+//@{
+{
+    var interfaceName = this.name;
+    var isPairIterator = member.idlType instanceof Array;
+    test(function()
+    {
+        var descriptor = Object.getOwnPropertyDescriptor(self[interfaceName].prototype, Symbol.iterator);
+        assert_true(descriptor.writable, &quot;property is not writable&quot;);
+        assert_true(descriptor.configurable, &quot;property is not configurable&quot;);
+        assert_false(descriptor.enumerable, &quot;property is enumerable&quot;);
+        assert_equals(self[interfaceName].prototype[Symbol.iterator].name, isPairIterator ? &quot;entries&quot; : &quot;values&quot;, &quot;@@iterator function does not have the right name&quot;);
+    }, &quot;Testing Symbol.iterator property of iterable interface &quot; + interfaceName);
+
+    if (isPairIterator) {
+        test(function() {
+            assert_equals(self[interfaceName].prototype[Symbol.iterator], self[interfaceName].prototype[&quot;entries&quot;], &quot;entries method is not the same as @@iterator&quot;);
+        }, &quot;Testing pair iterable interface &quot; + interfaceName);
+    } else {
+        test(function() {
+            [&quot;entries&quot;, &quot;keys&quot;, &quot;values&quot;, &quot;forEach&quot;, Symbol.Iterator].forEach(function(property) {
+                assert_equals(self[interfaceName].prototype[property], Array.prototype[property], property + &quot; function is not the same as Array one&quot;);
+            });
+        }, &quot;Testing value iterable interface &quot; + interfaceName);
+    }
+};
+
+//@}
+IdlInterface.prototype.test_member_stringifier = function(member)
+//@{
+{
+    test(function()
+    {
+        if (this.is_callback() &amp;&amp; !this.has_constants()) {
+            return;
+        }
+
+        assert_own_property(self, this.name,
+                            &quot;self does not have own property &quot; + format_value(this.name));
+
+        if (this.is_callback()) {
+            assert_false(&quot;prototype&quot; in self[this.name],
+                         this.name + ' should not have a &quot;prototype&quot; property');
+            return;
+        }
+
+        assert_own_property(self[this.name], &quot;prototype&quot;,
+                            'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
+
+        // &quot;. . . the property exists on the interface prototype object.&quot;
+        var interfacePrototypeObject = self[this.name].prototype;
+        assert_own_property(self[this.name].prototype, &quot;toString&quot;,
+                &quot;interface prototype object missing non-static operation&quot;);
+
+        var stringifierUnforgeable = member.isUnforgeable;
+        var desc = Object.getOwnPropertyDescriptor(interfacePrototypeObject, &quot;toString&quot;);
+        // &quot;The property has attributes { [[Writable]]: B,
+        // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
+        // stringifier is unforgeable on the interface, and true otherwise.&quot;
+        assert_false(&quot;get&quot; in desc, &quot;property has getter&quot;);
+        assert_false(&quot;set&quot; in desc, &quot;property has setter&quot;);
+        assert_equals(desc.writable, !stringifierUnforgeable,
+                      &quot;property should be writable if and only if not unforgeable&quot;);
+        assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
+        assert_equals(desc.configurable, !stringifierUnforgeable,
+                      &quot;property should be configurable if and only if not unforgeable&quot;);
+        // &quot;The value of the property is a Function object, which behaves as
+        // follows . . .&quot;
+        assert_equals(typeof interfacePrototypeObject.toString, &quot;function&quot;,
+                      &quot;property must be a function&quot;);
+        // &quot;The value of the Function object’s “length” property is the Number
+        // value 0.&quot;
+        assert_equals(interfacePrototypeObject.toString.length, 0,
+            &quot;property has wrong .length&quot;);
+
+        // &quot;Let O be the result of calling ToObject on the this value.&quot;
+        assert_throws(new TypeError(), function() {
+            self[this.name].prototype.toString.apply(null, []);
+        }, &quot;calling stringifier with this = null didn't throw TypeError&quot;);
+
+        // &quot;If O is not an object that implements the interface on which the
+        // stringifier was declared, then throw a TypeError.&quot;
+        //
+        // TODO: Test a platform object that implements some other
+        // interface.  (Have to be sure to get inheritance right.)
+        assert_throws(new TypeError(), function() {
+            self[this.name].prototype.toString.apply({}, []);
+        }, &quot;calling stringifier with this = {} didn't throw TypeError&quot;);
+    }.bind(this), this.name + &quot; interface: stringifier&quot;);
+};
+
+//@}
+IdlInterface.prototype.test_members = function()
+//@{
+{
+    for (var i = 0; i &lt; this.members.length; i++)
+    {
+        var member = this.members[i];
+        switch (member.type) {
+        case &quot;iterable&quot;:
+            this.add_iterable_members(member);
+            break;
+        // TODO: add setlike and maplike handling.
+        default:
+            break;
+        }
+    }
+
+    for (var i = 0; i &lt; this.members.length; i++)
+    {
+        var member = this.members[i];
+        if (member.untested) {
+            continue;
+        }
+
+        switch (member.type) {
+        case &quot;const&quot;:
+            this.test_member_const(member);
+            break;
+
+        case &quot;attribute&quot;:
+            // For unforgeable attributes, we do the checks in
+            // test_interface_of instead.
+            if (!member.isUnforgeable)
+            {
+                this.test_member_attribute(member);
+            }
+            if (member.stringifier) {
+                this.test_member_stringifier(member);
+            }
+            break;
+
+        case &quot;operation&quot;:
+            // TODO: Need to correctly handle multiple operations with the same
+            // identifier.
+            // For unforgeable operations, we do the checks in
+            // test_interface_of instead.
+            if (member.name) {
+                if (!member.isUnforgeable)
+                {
+                    this.test_member_operation(member);
+                }
+            } else if (member.stringifier) {
+                this.test_member_stringifier(member);
+            }
+            break;
+
+        case &quot;iterable&quot;:
+            this.test_member_iterable(member);
+            break;
+        default:
+            // TODO: check more member types.
+            break;
+        }
+    }
+};
+
+//@}
+IdlInterface.prototype.test_object = function(desc)
+//@{
+{
+    var obj, exception = null;
+    try
+    {
+        obj = eval(desc);
+    }
+    catch(e)
+    {
+        exception = e;
+    }
+
+    var expected_typeof =
+        this.members.some(function(member) { return member.legacycaller; })
+        ? &quot;function&quot;
+        : &quot;object&quot;;
+
+    this.test_primary_interface_of(desc, obj, exception, expected_typeof);
+    var current_interface = this;
+    while (current_interface)
+    {
+        if (!(current_interface.name in this.array.members))
+        {
+            throw &quot;Interface &quot; + current_interface.name + &quot; not found (inherited by &quot; + this.name + &quot;)&quot;;
+        }
+        if (current_interface.prevent_multiple_testing &amp;&amp; current_interface.already_tested)
+        {
+            return;
+        }
+        current_interface.test_interface_of(desc, obj, exception, expected_typeof);
+        current_interface = this.array.members[current_interface.base];
+    }
+};
+
+//@}
+IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception, expected_typeof)
+//@{
+{
+    // We can't easily test that its prototype is correct if there's no
+    // interface object, or the object is from a different global environment
+    // (not instanceof Object).  TODO: test in this case that its prototype at
+    // least looks correct, even if we can't test that it's actually correct.
+    if (!this.has_extended_attribute(&quot;NoInterfaceObject&quot;)
+    &amp;&amp; (typeof obj != expected_typeof || obj instanceof Object))
+    {
+        test(function()
+        {
+            assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
+            assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
+            assert_own_property(self, this.name,
+                                &quot;self does not have own property &quot; + format_value(this.name));
+            assert_own_property(self[this.name], &quot;prototype&quot;,
+                                'interface &quot;' + this.name + '&quot; does not have own property &quot;prototype&quot;');
+
+            // &quot;The value of the internal [[Prototype]] property of the
+            // platform object is the interface prototype object of the primary
+            // interface from the platform object’s associated global
+            // environment.&quot;
+            assert_equals(Object.getPrototypeOf(obj),
+                          self[this.name].prototype,
+                          desc + &quot;'s prototype is not &quot; + this.name + &quot;.prototype&quot;);
+        }.bind(this), this.name + &quot; must be primary interface of &quot; + desc);
+    }
+
+    // &quot;The class string of a platform object that implements one or more
+    // interfaces must be the identifier of the primary interface of the
+    // platform object.&quot;
+    test(function()
+    {
+        assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
+        assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
+        assert_class_string(obj, this.name, &quot;class string of &quot; + desc);
+        if (!this.has_stringifier())
+        {
+            assert_equals(String(obj), &quot;[object &quot; + this.name + &quot;]&quot;, &quot;String(&quot; + desc + &quot;)&quot;);
+        }
+    }.bind(this), &quot;Stringification of &quot; + desc);
+};
+
+//@}
+IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof)
+//@{
+{
+    // TODO: Indexed and named properties, more checks on interface members
+    this.already_tested = true;
+
+    for (var i = 0; i &lt; this.members.length; i++)
+    {
+        var member = this.members[i];
+        if (member.type == &quot;attribute&quot; &amp;&amp; member.isUnforgeable)
+        {
+            var a_test = async_test(this.name + &quot; interface: &quot; + desc + ' must have own property &quot;' + member.name + '&quot;');
+            a_test.step(function() {
+                assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
+                assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
+                // Call do_interface_attribute_asserts last, since it will call a_test.done()
+                this.do_interface_attribute_asserts(obj, member, a_test);
+            }.bind(this));
+        }
+        else if (member.type == &quot;operation&quot; &amp;&amp;
+                 member.name &amp;&amp;
+                 member.isUnforgeable)
+        {
+            var a_test = async_test(this.name + &quot; interface: &quot; + desc + ' must have own property &quot;' + member.name + '&quot;');
+            a_test.step(function()
+            {
+                assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
+                assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
+                assert_own_property(obj, member.name,
+                                    &quot;Doesn't have the unforgeable operation property&quot;);
+                this.do_member_operation_asserts(obj, member, a_test);
+            }.bind(this));
+        }
+        else if ((member.type == &quot;const&quot;
+        || member.type == &quot;attribute&quot;
+        || member.type == &quot;operation&quot;)
+        &amp;&amp; member.name)
+        {
+            test(function()
+            {
+                assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
+                assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
+                if (!member[&quot;static&quot;]) {
+                    if (!this.is_global()) {
+                        assert_inherits(obj, member.name);
+                    } else {
+                        assert_own_property(obj, member.name);
+                    }
+
+                    if (member.type == &quot;const&quot;)
+                    {
+                        assert_equals(obj[member.name], constValue(member.value));
+                    }
+                    if (member.type == &quot;attribute&quot;)
+                    {
+                        // Attributes are accessor properties, so they might
+                        // legitimately throw an exception rather than returning
+                        // anything.
+                        var property, thrown = false;
+                        try
+                        {
+                            property = obj[member.name];
+                        }
+                        catch (e)
+                        {
+                            thrown = true;
+                        }
+                        if (!thrown)
+                        {
+                            this.array.assert_type_is(property, member.idlType);
+                        }
+                    }
+                    if (member.type == &quot;operation&quot;)
+                    {
+                        assert_equals(typeof obj[member.name], &quot;function&quot;);
+                    }
+                }
+            }.bind(this), this.name + &quot; interface: &quot; + desc + ' must inherit property &quot;' + member.name + '&quot; with the proper type (' + i + ')');
+        }
+        // TODO: This is wrong if there are multiple operations with the same
+        // identifier.
+        // TODO: Test passing arguments of the wrong type.
+        if (member.type == &quot;operation&quot; &amp;&amp; member.name &amp;&amp; member.arguments.length)
+        {
+            var a_test = async_test( this.name + &quot; interface: calling &quot; + member.name +
+            &quot;(&quot; + member.arguments.map(function(m) { return m.idlType.idlType; }) +
+            &quot;) on &quot; + desc + &quot; with too few arguments must throw TypeError&quot;);
+            a_test.step(function()
+            {
+                assert_equals(exception, null, &quot;Unexpected exception when evaluating object&quot;);
+                assert_equals(typeof obj, expected_typeof, &quot;wrong typeof object&quot;);
+                if (!member[&quot;static&quot;]) {
+                    if (!this.is_global() &amp;&amp; !member.isUnforgeable) {
+                        assert_inherits(obj, member.name);
+                    } else {
+                        assert_own_property(obj, member.name);
+                    }
+                }
+                else
+                {
+                    assert_false(member.name in obj);
+                }
+
+                var minLength = minOverloadLength(this.members.filter(function(m) {
+                    return m.type == &quot;operation&quot; &amp;&amp; m.name == member.name;
+                }));
+                var args = [];
+                var cb = awaitNCallbacks(minLength, a_test.done.bind(a_test));
+                for (var i = 0; i &lt; minLength; i++) {
+                    throwOrReject(a_test, member, obj[member.name], obj, args,  &quot;Called with &quot; + i + &quot; arguments&quot;, cb);
+
+                    args.push(create_suitable_object(member.arguments[i].idlType));
+                }
+                if (minLength === 0) {
+                    cb();
+                }
+            }.bind(this));
+        }
+    }
+};
+
+//@}
+IdlInterface.prototype.has_stringifier = function()
+//@{
+{
+    if (this.members.some(function(member) { return member.stringifier; })) {
+        return true;
+    }
+    if (this.base &amp;&amp;
+        this.array.members[this.base].has_stringifier()) {
+        return true;
+    }
+    return false;
+};
+
+//@}
+IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member, a_test)
+//@{
+{
+    // This function tests WebIDL as of 2015-01-27.
+    // TODO: Consider [Exposed].
+
+    // This is called by test_member_attribute() with the prototype as obj if
+    // it is not a global, and the global otherwise, and by test_interface_of()
+    // with the object as obj.
+
+    var pendingPromises = [];
+
+    // &quot;For each exposed attribute of the interface, whether it was declared on
+    // the interface itself or one of its consequential interfaces, there MUST
+    // exist a corresponding property. The characteristics of this property are
+    // as follows:&quot;
+
+    // &quot;The name of the property is the identifier of the attribute.&quot;
+    assert_own_property(obj, member.name);
+
+    // &quot;The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+    // true, [[Configurable]]: configurable }, where:
+    // &quot;configurable is false if the attribute was declared with the
+    // [Unforgeable] extended attribute and true otherwise;
+    // &quot;G is the attribute getter, defined below; and
+    // &quot;S is the attribute setter, also defined below.&quot;
+    var desc = Object.getOwnPropertyDescriptor(obj, member.name);
+    assert_false(&quot;value&quot; in desc, 'property descriptor has value but is supposed to be accessor');
+    assert_false(&quot;writable&quot; in desc, 'property descriptor has &quot;writable&quot; field but is supposed to be accessor');
+    assert_true(desc.enumerable, &quot;property is not enumerable&quot;);
+    if (member.isUnforgeable)
+    {
+        assert_false(desc.configurable, &quot;[Unforgeable] property must not be configurable&quot;);
+    }
+    else
+    {
+        assert_true(desc.configurable, &quot;property must be configurable&quot;);
+    }
+
+
+    // &quot;The attribute getter is a Function object whose behavior when invoked
+    // is as follows:&quot;
+    assert_equals(typeof desc.get, &quot;function&quot;, &quot;getter must be Function&quot;);
+
+    // &quot;If the attribute is a regular attribute, then:&quot;
+    if (!member[&quot;static&quot;]) {
+        // &quot;If O is not a platform object that implements I, then:
+        // &quot;If the attribute was specified with the [LenientThis] extended
+        // attribute, then return undefined.
+        // &quot;Otherwise, throw a TypeError.&quot;
+        if (!member.has_extended_attribute(&quot;LenientThis&quot;)) {
+            if (member.idlType.generic !== &quot;Promise&quot;) {
+                assert_throws(new TypeError(), function() {
+                    desc.get.call({});
+                }.bind(this), &quot;calling getter on wrong object type must throw TypeError&quot;);
+            } else {
+                pendingPromises.push(
+                    promise_rejects(a_test, new TypeError(), desc.get.call({}),
+                                    &quot;calling getter on wrong object type must reject the return promise with TypeError&quot;));
+            }
+        } else {
+            assert_equals(desc.get.call({}), undefined,
+                          &quot;calling getter on wrong object type must return undefined&quot;);
+        }
+    }
+
+    // &quot;The value of the Function object’s “length” property is the Number
+    // value 0.&quot;
+    assert_equals(desc.get.length, 0, &quot;getter length must be 0&quot;);
+
+
+    // TODO: Test calling setter on the interface prototype (should throw
+    // TypeError in most cases).
+    if (member.readonly
+    &amp;&amp; !member.has_extended_attribute(&quot;PutForwards&quot;)
+    &amp;&amp; !member.has_extended_attribute(&quot;Replaceable&quot;))
+    {
+        // &quot;The attribute setter is undefined if the attribute is declared
+        // readonly and has neither a [PutForwards] nor a [Replaceable]
+        // extended attribute declared on it.&quot;
+        assert_equals(desc.set, undefined, &quot;setter must be undefined for readonly attributes&quot;);
+    }
+    else
+    {
+        // &quot;Otherwise, it is a Function object whose behavior when
+        // invoked is as follows:&quot;
+        assert_equals(typeof desc.set, &quot;function&quot;, &quot;setter must be function for PutForwards, Replaceable, or non-readonly attributes&quot;);
+
+        // &quot;If the attribute is a regular attribute, then:&quot;
+        if (!member[&quot;static&quot;]) {
+            // &quot;If /validThis/ is false and the attribute was not specified
+            // with the [LenientThis] extended attribute, then throw a
+            // TypeError.&quot;
+            // &quot;If the attribute is declared with a [Replaceable] extended
+            // attribute, then: ...&quot;
+            // &quot;If validThis is false, then return.&quot;
+            if (!member.has_extended_attribute(&quot;LenientThis&quot;)) {
+                assert_throws(new TypeError(), function() {
+                    desc.set.call({});
+                }.bind(this), &quot;calling setter on wrong object type must throw TypeError&quot;);
+            } else {
+                assert_equals(desc.set.call({}), undefined,
+                              &quot;calling setter on wrong object type must return undefined&quot;);
+            }
+        }
+
+        // &quot;The value of the Function object’s “length” property is the Number
+        // value 1.&quot;
+        assert_equals(desc.set.length, 1, &quot;setter length must be 1&quot;);
+    }
+
+    Promise.all(pendingPromises).then(a_test.done.bind(a_test));
+}
+//@}
+
+/// IdlInterfaceMember ///
+function IdlInterfaceMember(obj)
+//@{
+{
+    /**
+     * obj is an object produced by the WebIDLParser.js &quot;ifMember&quot; production.
+     * We just forward all properties to this object without modification,
+     * except for special extAttrs handling.
+     */
+    for (var k in obj)
+    {
+        this[k] = obj[k];
+    }
+    if (!(&quot;extAttrs&quot; in this))
+    {
+        this.extAttrs = [];
+    }
+
+    this.isUnforgeable = this.has_extended_attribute(&quot;Unforgeable&quot;);
+}
+
+//@}
+IdlInterfaceMember.prototype = Object.create(IdlObject.prototype);
+
+/// Internal helper functions ///
+function create_suitable_object(type)
+//@{
+{
+    /**
+     * type is an object produced by the WebIDLParser.js &quot;type&quot; production.  We
+     * return a JavaScript value that matches the type, if we can figure out
+     * how.
+     */
+    if (type.nullable)
+    {
+        return null;
+    }
+    switch (type.idlType)
+    {
+        case &quot;any&quot;:
+        case &quot;boolean&quot;:
+            return true;
+
+        case &quot;byte&quot;: case &quot;octet&quot;: case &quot;short&quot;: case &quot;unsigned short&quot;:
+        case &quot;long&quot;: case &quot;unsigned long&quot;: case &quot;long long&quot;:
+        case &quot;unsigned long long&quot;: case &quot;float&quot;: case &quot;double&quot;:
+        case &quot;unrestricted float&quot;: case &quot;unrestricted double&quot;:
+            return 7;
+
+        case &quot;DOMString&quot;:
+        case &quot;ByteString&quot;:
+        case &quot;USVString&quot;:
+            return &quot;foo&quot;;
+
+        case &quot;object&quot;:
+            return {a: &quot;b&quot;};
+
+        case &quot;Node&quot;:
+            return document.createTextNode(&quot;abc&quot;);
+    }
+    return null;
+}
+//@}
+
+/// IdlEnum ///
+// Used for IdlArray.prototype.assert_type_is
+function IdlEnum(obj)
+//@{
+{
+    /**
+     * obj is an object produced by the WebIDLParser.js &quot;dictionary&quot;
+     * production.
+     */
+
+    /** Self-explanatory. */
+    this.name = obj.name;
+
+    /** An array of values produced by the &quot;enum&quot; production. */
+    this.values = obj.values;
+
+}
+//@}
+
+IdlEnum.prototype = Object.create(IdlObject.prototype);
+
+/// IdlTypedef ///
+// Used for IdlArray.prototype.assert_type_is
+function IdlTypedef(obj)
+//@{
+{
+    /**
+     * obj is an object produced by the WebIDLParser.js &quot;typedef&quot;
+     * production.
+     */
+
+    /** Self-explanatory. */
+    this.name = obj.name;
+
+    /** An array of values produced by the &quot;typedef&quot; production. */
+    this.values = obj.values;
+
+}
+//@}
+
+IdlTypedef.prototype = Object.create(IdlObject.prototype);
+
+}());
+// vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:
</ins></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/Source/WebCore/CMakeLists.txt        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -8,6 +8,7 @@
</span><span class="cx">     &quot;${WEBCORE_DIR}&quot;
</span><span class="cx">     &quot;${WEBCORE_DIR}/Modules/airplay&quot;
</span><span class="cx">     &quot;${WEBCORE_DIR}/Modules/applepay&quot;
</span><ins>+    &quot;${WEBCORE_DIR}/Modules/credentials&quot;
</ins><span class="cx">     &quot;${WEBCORE_DIR}/Modules/encryptedmedia&quot;
</span><span class="cx">     &quot;${WEBCORE_DIR}/Modules/encryptedmedia/legacy&quot;
</span><span class="cx">     &quot;${WEBCORE_DIR}/Modules/fetch&quot;
</span><span class="lines">@@ -137,6 +138,7 @@
</span><span class="cx">     xml
</span><span class="cx"> 
</span><span class="cx">     Modules/airplay
</span><ins>+    Modules/credentials
</ins><span class="cx">     Modules/encryptedmedia/legacy
</span><span class="cx">     Modules/fetch
</span><span class="cx">     Modules/geolocation
</span><span class="lines">@@ -165,6 +167,12 @@
</span><span class="cx"> set(WebCore_NON_SVG_IDL_FILES
</span><span class="cx">     Modules/airplay/WebKitPlaybackTargetAvailabilityEvent.idl
</span><span class="cx"> 
</span><ins>+    Modules/credentials/BasicCredential.idl
+    Modules/credentials/CredentialData.idl
+    Modules/credentials/PasswordCredential.idl
+    Modules/credentials/SiteBoundCredential.idl
+    Modules/credentials/SiteBoundCredentialData.idl
+
</ins><span class="cx">     Modules/fetch/DOMWindowFetch.idl
</span><span class="cx">     Modules/fetch/FetchBody.idl
</span><span class="cx">     Modules/fetch/FetchHeaders.idl
</span><span class="lines">@@ -800,6 +808,10 @@
</span><span class="cx"> set(WebCore_SOURCES
</span><span class="cx">     Modules/airplay/WebKitPlaybackTargetAvailabilityEvent.cpp
</span><span class="cx"> 
</span><ins>+    Modules/credentials/BasicCredential.cpp
+    Modules/credentials/PasswordCredential.cpp
+    Modules/credentials/SiteBoundCredential.cpp
+
</ins><span class="cx">     Modules/fetch/DOMWindowFetch.cpp
</span><span class="cx">     Modules/fetch/FetchBody.cpp
</span><span class="cx">     Modules/fetch/FetchBodyConsumer.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/Source/WebCore/ChangeLog        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -1,3 +1,56 @@
</span><ins>+2017-02-27  Jiewen Tan  &lt;jiewen_tan@apple.com&gt;
+
+        [CredentialManagement] Add IDL definitions for Credential, SiteBoundCredential, and PasswordCredential
+        https://bugs.webkit.org/show_bug.cgi?id=168616
+        &lt;rdar://problem/30167149&gt;
+
+        Reviewed by Daniel Bates.
+
+        This patch adds IDL definitions for:
+        1. Credential(https://w3c.github.io/webappsec-credential-management/#interfaces-credential-types-credential),
+        2. SiteBoundCredential(https://w3c.github.io/webappsec-credential-management/#interfaces-credential-types-siteboundcredential), and
+        3. PasswordCredential(https://w3c.github.io/webappsec-credential-management/#interfaces-credential-types-passwordcredential).
+
+        Test: credentials/idlharness.html
+
+        * CMakeLists.txt:
+        * DerivedSources.make:
+        * Modules/credentials/BasicCredential.cpp: Added.
+        (WebCore::BasicCredential::BasicCredential):
+        (WebCore::BasicCredential::~BasicCredential):
+        (WebCore::BasicCredential::type):
+        * Modules/credentials/BasicCredential.h: Added.
+        (WebCore::BasicCredential::id):
+        * Modules/credentials/BasicCredential.idl: Added.
+        * Modules/credentials/CredentialData.h: Added.
+        * Modules/credentials/CredentialData.idl: Added.
+        * Modules/credentials/PasswordCredential.cpp: Added.
+        (WebCore::PasswordCredential::PasswordCredential):
+        (WebCore::PasswordCredential::PasswordCredential):
+        Dummy constructors for now.
+        * Modules/credentials/PasswordCredential.h: Added.
+        (WebCore::PasswordCredential::create):
+        (WebCore::PasswordCredential::create):
+        (WebCore::PasswordCredential::setIdName):
+        (WebCore::PasswordCredential::idName):
+        (WebCore::PasswordCredential::setPasswordName):
+        (WebCore::PasswordCredential::passwordName):
+        (WebCore::PasswordCredential::setAdditionalData):
+        (WebCore::PasswordCredential::additionalData):
+        * Modules/credentials/PasswordCredential.idl: Added.
+        * Modules/credentials/SiteBoundCredential.cpp: Added.
+        (WebCore::SiteBoundCredential::SiteBoundCredential):
+        (WebCore::SiteBoundCredential::~SiteBoundCredential):
+        * Modules/credentials/SiteBoundCredential.h: Added.
+        (WebCore::SiteBoundCredential::name):
+        (WebCore::SiteBoundCredential::iconURL):
+        (WebCore::SiteBoundCredential::setOrigin):
+        (WebCore::SiteBoundCredential::origin):
+        * Modules/credentials/SiteBoundCredential.idl: Added.
+        * Modules/credentials/SiteBoundCredentialData.h: Added.
+        * Modules/credentials/SiteBoundCredentialData.idl: Added.
+        * WebCore.xcodeproj/project.pbxproj:
+
</ins><span class="cx"> 2017-02-27  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebRTC] Fix remote audio rendering
</span></span></pre></div>
<a id="trunkSourceWebCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/DerivedSources.make (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/DerivedSources.make        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/Source/WebCore/DerivedSources.make        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx">     $(WebCore) \
</span><span class="cx">     $(WebCore)/Modules/airplay \
</span><span class="cx">     $(WebCore)/Modules/applepay \
</span><ins>+    $(WebCore)/Modules/credentials \
</ins><span class="cx">     $(WebCore)/Modules/encryptedmedia \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/legacy \
</span><span class="cx">     $(WebCore)/Modules/fetch \
</span><span class="lines">@@ -91,6 +92,11 @@
</span><span class="cx">     $(WebCore)/Modules/applepay/ApplePayShippingMethod.idl \
</span><span class="cx">     $(WebCore)/Modules/applepay/ApplePayShippingMethodSelectedEvent.idl \
</span><span class="cx">     $(WebCore)/Modules/applepay/ApplePayValidateMerchantEvent.idl \
</span><ins>+    $(WebCore)/Modules/credentials/BasicCredential.idl \
+    $(WebCore)/Modules/credentials/CredentialData.idl \
+    $(WebCore)/Modules/credentials/PasswordCredential.idl \
+    $(WebCore)/Modules/credentials/SiteBoundCredential.idl \
+    $(WebCore)/Modules/credentials/SiteBoundCredentialData.idl \
</ins><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeyMessageEvent.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeySession.idl \
</span><span class="cx">     $(WebCore)/Modules/encryptedmedia/MediaKeySessionType.idl \
</span></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsBasicCredentialcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/BasicCredential.cpp (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/BasicCredential.cpp                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/BasicCredential.cpp        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;BasicCredential.h&quot;
+
+namespace WebCore {
+
+BasicCredential::BasicCredential(const CredentialData&amp; data, Type type)
+    : m_id(data.id)
+    , m_type(type)
+{
+}
+
+BasicCredential::~BasicCredential()
+{
+}
+
+String BasicCredential::type() const
+{
+    switch (m_type) {
+    case Type::Password:
+        return ASCIILiteral(&quot;password&quot;);
+    case Type::Federated:
+        return ASCIILiteral(&quot;federated&quot;);
+    }
+
+    ASSERT_NOT_REACHED();
+    return emptyString();
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsBasicCredentialh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/BasicCredential.h (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/BasicCredential.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/BasicCredential.h        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;CredentialData.h&quot;
+#include &lt;wtf/RefCounted.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebCore {
+
+class BasicCredential : public RefCounted&lt;BasicCredential&gt; {
+public:
+    enum class Type {
+        Password,
+        Federated,
+    };
+
+    virtual ~BasicCredential();
+
+    const String&amp; id() const { return m_id; }
+    String type() const;
+
+protected:
+    BasicCredential(const CredentialData&amp;, Type);
+
+private:
+    String m_id;
+    Type m_type;
+};
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsBasicCredentialidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/BasicCredential.idl (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/BasicCredential.idl                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/BasicCredential.idl        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    InterfaceName=Credential,
+] interface BasicCredential {
+    readonly attribute USVString id;
+    readonly attribute DOMString type;
+};
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsCredentialDatah"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/CredentialData.h (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/CredentialData.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/CredentialData.h        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebCore {
+
+struct CredentialData {
+    String id;
+};
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsCredentialDataidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/CredentialData.idl (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/CredentialData.idl                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/CredentialData.idl        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+dictionary CredentialData {
+    required USVString id;
+};
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsPasswordCredentialcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/PasswordCredential.cpp (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/PasswordCredential.cpp                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/PasswordCredential.cpp        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;PasswordCredential.h&quot;
+
+namespace WebCore {
+
+PasswordCredential::PasswordCredential(const Data&amp; data)
+    : SiteBoundCredential(data, Type::Password)
+{
+}
+
+PasswordCredential::PasswordCredential(const HTMLFormElement&amp;)
+    : SiteBoundCredential(Data(), Type::Password)
+{
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsPasswordCredentialh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/PasswordCredential.h (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/PasswordCredential.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/PasswordCredential.h        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,65 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;DOMFormData.h&quot;
+#include &quot;SiteBoundCredential.h&quot;
+#include &quot;URLSearchParams.h&quot;
+#include &lt;wtf/Variant.h&gt;
+
+namespace WebCore {
+
+class HTMLFormElement;
+
+class PasswordCredential : public SiteBoundCredential {
+public:
+    struct Data : public SiteBoundCredentialData {
+        String password;
+    };
+
+    static Ref&lt;PasswordCredential&gt; create(const Data&amp; data) { return adoptRef(*new PasswordCredential(data)); }
+    static Ref&lt;PasswordCredential&gt; create(const HTMLFormElement&amp; form) { return adoptRef(*new PasswordCredential(form)); }
+
+    void setIdName(String&amp;&amp; idName) { m_idName = WTFMove(idName); }
+    const String&amp; idName() const { return m_idName; }
+
+    void setPasswordName(String&amp;&amp; passwordName) { m_passwordName = WTFMove(passwordName); }
+    const String&amp; passwordName() const { return m_passwordName; }
+
+    using CredentialBodyType = std::optional&lt;Variant&lt;RefPtr&lt;DOMFormData&gt;, RefPtr&lt;URLSearchParams&gt;&gt;&gt;;
+    void setAdditionalData(CredentialBodyType&amp;&amp; additionalData) { m_additionalData = WTFMove(additionalData); }
+    const CredentialBodyType&amp; additionalData() const { return m_additionalData; }
+
+private:
+    PasswordCredential(const Data&amp;);
+    PasswordCredential(const HTMLFormElement&amp;);
+
+    String m_idName;
+    String m_passwordName;
+    CredentialBodyType m_additionalData;
+};
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsPasswordCredentialidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/PasswordCredential.idl (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/PasswordCredential.idl                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/PasswordCredential.idl        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+typedef (DOMFormData or URLSearchParams) CredentialBodyType;
+
+[
+    Constructor(PasswordCredentialData data),
+    Constructor(HTMLFormElement form),
+    Exposed=Window,
+] interface PasswordCredential : SiteBoundCredential {
+    attribute USVString idName;
+    attribute USVString passwordName;
+
+    attribute CredentialBodyType? additionalData;
+};
+
+dictionary PasswordCredentialData : SiteBoundCredentialData {
+    required USVString password;
+};
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsSiteBoundCredentialcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.cpp (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.cpp                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.cpp        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;SiteBoundCredential.h&quot;
+
+namespace WebCore {
+
+SiteBoundCredential::SiteBoundCredential(const SiteBoundCredentialData&amp; data, Type type)
+    : BasicCredential(data, type)
+    , m_name(data.name)
+    , m_iconURL(URL(URL(), data.iconURL))
+    , m_origin(SecurityOrigin::create(URL()))
+{
+}
+
+SiteBoundCredential::~SiteBoundCredential()
+{
+}
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsSiteBoundCredentialh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.h (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.h        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;BasicCredential.h&quot;
+#include &quot;SecurityOrigin.h&quot;
+#include &quot;SiteBoundCredentialData.h&quot;
+#include &quot;URL.h&quot;
+
+namespace WebCore {
+
+class SiteBoundCredential : public BasicCredential {
+public:
+    virtual ~SiteBoundCredential();
+
+    const String&amp; name() const { return m_name; }
+    const URL&amp; iconURL() const { return m_iconURL; }
+
+    void setOrigin(const URL&amp; origin) { m_origin = SecurityOrigin::create(origin); }
+    const SecurityOrigin&amp; origin() const { return m_origin.get(); }
+
+protected:
+    SiteBoundCredential(const SiteBoundCredentialData&amp;, Type);
+
+private:
+    String m_name;
+    URL m_iconURL;
+    Ref&lt;SecurityOrigin&gt; m_origin;
+};
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsSiteBoundCredentialidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.idl (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.idl                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/SiteBoundCredential.idl        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+interface SiteBoundCredential : BasicCredential {
+    readonly attribute USVString name;
+    readonly attribute USVString iconURL;
+};
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsSiteBoundCredentialDatah"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/SiteBoundCredentialData.h (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/SiteBoundCredentialData.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/SiteBoundCredentialData.h        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;CredentialData.h&quot;
+
+namespace WebCore {
+
+struct SiteBoundCredentialData : public CredentialData {
+    String name;
+    String iconURL;
+};
+
+} // namespace WebCore
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulescredentialsSiteBoundCredentialDataidl"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/credentials/SiteBoundCredentialData.idl (0 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/credentials/SiteBoundCredentialData.idl                                (rev 0)
+++ trunk/Source/WebCore/Modules/credentials/SiteBoundCredentialData.idl        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+dictionary SiteBoundCredentialData : CredentialData {
+    USVString name;
+    USVString iconURL;
+};
</ins></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (213080 => 213081)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-02-27 18:22:49 UTC (rev 213080)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2017-02-27 19:01:13 UTC (rev 213081)
</span><span class="lines">@@ -2365,6 +2365,24 @@
</span><span class="cx">                 5778BD821DA4806C009E3009 /* SubtleCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 5778BD811DA4802C009E3009 /* SubtleCrypto.h */; };
</span><span class="cx">                 5778BD841DA4817B009E3009 /* SubtleCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5778BD831DA4817B009E3009 /* SubtleCrypto.cpp */; };
</span><span class="cx">                 57A9C88E1DA70BF800BC7305 /* JSSubtleCryptoCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57A9C88D1DA70BF800BC7305 /* JSSubtleCryptoCustom.cpp */; };
</span><ins>+                57B5F7D41E57CF6800F34F90 /* SiteBoundCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57B5F7D21E57CF6800F34F90 /* SiteBoundCredential.cpp */; };
+                57B5F7D51E57CF6800F34F90 /* SiteBoundCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B5F7D31E57CF6800F34F90 /* SiteBoundCredential.h */; };
+                57B5F7D81E57D3C900F34F90 /* CredentialData.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B5F7D71E57D3C900F34F90 /* CredentialData.h */; };
+                57B5F7DB1E57D4CC00F34F90 /* SiteBoundCredentialData.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B5F7DA1E57D4CC00F34F90 /* SiteBoundCredentialData.h */; };
+                57B5F7E01E57DBC800F34F90 /* JSSiteBoundCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57B5F7DC1E57DBC800F34F90 /* JSSiteBoundCredential.cpp */; };
+                57B5F7E11E57DBC800F34F90 /* JSSiteBoundCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B5F7DD1E57DBC800F34F90 /* JSSiteBoundCredential.h */; };
+                57B5F7E21E57DBC800F34F90 /* JSSiteBoundCredentialData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57B5F7DE1E57DBC800F34F90 /* JSSiteBoundCredentialData.cpp */; };
+                57B5F7E31E57DBC800F34F90 /* JSSiteBoundCredentialData.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B5F7DF1E57DBC800F34F90 /* JSSiteBoundCredentialData.h */; };
+                57B5F7E61E57DBE000F34F90 /* JSCredentialData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57B5F7E41E57DBE000F34F90 /* JSCredentialData.cpp */; };
+                57B5F7E71E57DBE000F34F90 /* JSCredentialData.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B5F7E51E57DBE000F34F90 /* JSCredentialData.h */; };
+                57B5F7EC1E57F1E300F34F90 /* PasswordCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57B5F7EA1E57F1E300F34F90 /* PasswordCredential.cpp */; };
+                57B5F7ED1E57F1E300F34F90 /* PasswordCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B5F7EB1E57F1E300F34F90 /* PasswordCredential.h */; };
+                57B5F7F01E5B8C5A00F34F90 /* JSPasswordCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57B5F7EE1E5B8C5A00F34F90 /* JSPasswordCredential.cpp */; };
+                57B5F7F11E5B8C5A00F34F90 /* JSPasswordCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57B5F7EF1E5B8C5A00F34F90 /* JSPasswordCredential.h */; };
+                57C7A68C1E56967500C67D71 /* BasicCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57C7A68B1E56967500C67D71 /* BasicCredential.h */; };
+                57C7A6941E578ACA00C67D71 /* BasicCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57C7A6931E578ACA00C67D71 /* BasicCredential.cpp */; };
+                57C7A69F1E57917800C67D71 /* JSBasicCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57C7A69D1E57910D00C67D71 /* JSBasicCredential.h */; };
+                57C7A6A01E57919B00C67D71 /* JSBasicCredential.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57C7A69C1E57910D00C67D71 /* JSBasicCredential.cpp */; };
</ins><span class="cx">                 57D0018D1DD5413200ED19D9 /* JSCryptoKeyUsage.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D0018C1DD5413200ED19D9 /* JSCryptoKeyUsage.h */; };
</span><span class="cx">                 57D0018F1DD5415300ED19D9 /* JSCryptoKeyUsage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57D0018E1DD5415300ED19D9 /* JSCryptoKeyUsage.cpp */; };
</span><span class="cx">                 57E2335B1DC7D5E500F28D01 /* JSJsonWebKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E2335A1DC7D5E500F28D01 /* JSJsonWebKey.h */; };
</span><span class="lines">@@ -9744,6 +9762,29 @@
</span><span class="cx">                 5778BD811DA4802C009E3009 /* SubtleCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubtleCrypto.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5778BD831DA4817B009E3009 /* SubtleCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SubtleCrypto.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 57A9C88D1DA70BF800BC7305 /* JSSubtleCryptoCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSubtleCryptoCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                57B5F7D11E57CF0E00F34F90 /* SiteBoundCredential.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = SiteBoundCredential.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7D21E57CF6800F34F90 /* SiteBoundCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SiteBoundCredential.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7D31E57CF6800F34F90 /* SiteBoundCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SiteBoundCredential.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7D61E57D36A00F34F90 /* CredentialData.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = CredentialData.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7D71E57D3C900F34F90 /* CredentialData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CredentialData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7D91E57D44E00F34F90 /* SiteBoundCredentialData.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = SiteBoundCredentialData.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7DA1E57D4CC00F34F90 /* SiteBoundCredentialData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SiteBoundCredentialData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7DC1E57DBC800F34F90 /* JSSiteBoundCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSiteBoundCredential.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7DD1E57DBC800F34F90 /* JSSiteBoundCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSiteBoundCredential.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7DE1E57DBC800F34F90 /* JSSiteBoundCredentialData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSiteBoundCredentialData.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7DF1E57DBC800F34F90 /* JSSiteBoundCredentialData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSiteBoundCredentialData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7E41E57DBE000F34F90 /* JSCredentialData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCredentialData.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7E51E57DBE000F34F90 /* JSCredentialData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCredentialData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7E91E57E00000F34F90 /* PasswordCredential.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = PasswordCredential.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7EA1E57F1E300F34F90 /* PasswordCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PasswordCredential.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7EB1E57F1E300F34F90 /* PasswordCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasswordCredential.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7EE1E5B8C5A00F34F90 /* JSPasswordCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPasswordCredential.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57B5F7EF1E5B8C5A00F34F90 /* JSPasswordCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPasswordCredential.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57C7A6891E56946D00C67D71 /* BasicCredential.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BasicCredential.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57C7A68B1E56967500C67D71 /* BasicCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BasicCredential.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57C7A6931E578ACA00C67D71 /* BasicCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BasicCredential.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57C7A69C1E57910D00C67D71 /* JSBasicCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBasicCredential.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                57C7A69D1E57910D00C67D71 /* JSBasicCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBasicCredential.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 57D0018B1DD3DBA400ED19D9 /* CryptoKeyUsage.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = CryptoKeyUsage.idl; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 57D0018C1DD5413200ED19D9 /* JSCryptoKeyUsage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCryptoKeyUsage.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 57D0018E1DD5415300ED19D9 /* JSCryptoKeyUsage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCryptoKeyUsage.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -15962,6 +16003,7 @@
</span><span class="cx">                                 1221E0581C02B409006A1A00 /* Animation */,
</span><span class="cx">                                 1AE96A791D1A0A5C00B86768 /* ApplePay */,
</span><span class="cx">                                 A83B79100CCB001B000B0825 /* Core */,
</span><ins>+                                57C7A68D1E569A8400C67D71 /* Credentials */,
</ins><span class="cx">                                 E1FF8F61180745C600132674 /* Crypto */,
</span><span class="cx">                                 A83B790E0CCAFF97000B0825 /* CSS */,
</span><span class="cx">                                 5CE5D9A61DB899A800CE7A8D /* Encoding */,
</span><span class="lines">@@ -17691,6 +17733,43 @@
</span><span class="cx">                         path = mac;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="cx">                 };
</span><ins>+                57C7A6881E56946D00C67D71 /* credentials */ = {
+                        isa = PBXGroup;
+                        children = (
+                                57C7A6931E578ACA00C67D71 /* BasicCredential.cpp */,
+                                57C7A68B1E56967500C67D71 /* BasicCredential.h */,
+                                57C7A6891E56946D00C67D71 /* BasicCredential.idl */,
+                                57B5F7D71E57D3C900F34F90 /* CredentialData.h */,
+                                57B5F7D61E57D36A00F34F90 /* CredentialData.idl */,
+                                57B5F7EA1E57F1E300F34F90 /* PasswordCredential.cpp */,
+                                57B5F7EB1E57F1E300F34F90 /* PasswordCredential.h */,
+                                57B5F7E91E57E00000F34F90 /* PasswordCredential.idl */,
+                                57B5F7D21E57CF6800F34F90 /* SiteBoundCredential.cpp */,
+                                57B5F7D31E57CF6800F34F90 /* SiteBoundCredential.h */,
+                                57B5F7D11E57CF0E00F34F90 /* SiteBoundCredential.idl */,
+                                57B5F7DA1E57D4CC00F34F90 /* SiteBoundCredentialData.h */,
+                                57B5F7D91E57D44E00F34F90 /* SiteBoundCredentialData.idl */,
+                        );
+                        path = credentials;
+                        sourceTree = &quot;&lt;group&gt;&quot;;
+                };
+                57C7A68D1E569A8400C67D71 /* Credentials */ = {
+                        isa = PBXGroup;
+                        children = (
+                                57C7A69C1E57910D00C67D71 /* JSBasicCredential.cpp */,
+                                57C7A69D1E57910D00C67D71 /* JSBasicCredential.h */,
+                                57B5F7E41E57DBE000F34F90 /* JSCredentialData.cpp */,
+                                57B5F7E51E57DBE000F34F90 /* JSCredentialData.h */,
+                                57B5F7EE1E5B8C5A00F34F90 /* JSPasswordCredential.cpp */,
+                                57B5F7EF1E5B8C5A00F34F90 /* JSPasswordCredential.h */,
+                                57B5F7DC1E57DBC800F34F90 /* JSSiteBoundCredential.cpp */,
+                                57B5F7DD1E57DBC800F34F90 /* JSSiteBoundCredential.h */,
+                                57B5F7DE1E57DBC800F34F90 /* JSSiteBoundCredentialData.cpp */,
+                                57B5F7DF1E57DBC800F34F90 /* JSSiteBoundCredentialData.h */,
+                        );
+                        name = Credentials;
+                        sourceTree = &quot;&lt;group&gt;&quot;;
+                };
</ins><span class="cx">                 59B5977111086556007159E8 /* jsc */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><span class="lines">@@ -19633,6 +19712,7 @@
</span><span class="cx">                         children = (
</span><span class="cx">                                 CE26169D187E6554007955F3 /* airplay */,
</span><span class="cx">                                 1A58E8611D19D37300C0EA73 /* applepay */,
</span><ins>+                                57C7A6881E56946D00C67D71 /* credentials */,
</ins><span class="cx">                                 CDA98DBD16014E0800FEA3B1 /* encryptedmedia */,
</span><span class="cx">                                 41F54F7C1C50C4F600338488 /* fetch */,
</span><span class="cx">                                 518F4FE9194CA4B60081BAAE /* gamepad */,
</span><span class="lines">@@ -25332,11 +25412,13 @@
</span><span class="cx">                                 49E912AB0EFAC906009D0CAF /* Animation.h in Headers */,
</span><span class="cx">                                 316FE1120E6E1DA700BF6088 /* AnimationBase.h in Headers */,
</span><span class="cx">                                 319848011A1D817B00A13318 /* AnimationEvent.h in Headers */,
</span><ins>+                                57B5F7D81E57D3C900F34F90 /* CredentialData.h in Headers */,
</ins><span class="cx">                                 49E912AD0EFAC906009D0CAF /* AnimationList.h in Headers */,
</span><span class="cx">                                 31DCD29D1AB4FBDE0072E817 /* AnimationTrigger.h in Headers */,
</span><span class="cx">                                 0F580FAF149800D400FB5BD8 /* AnimationUtilities.h in Headers */,
</span><span class="cx">                                 93309DD7099E64920056E581 /* AppendNodeCommand.h in Headers */,
</span><span class="cx">                                 7C6579E31E00827000E3A27A /* ApplePayLineItem.h in Headers */,
</span><ins>+                                57C7A68C1E56967500C67D71 /* BasicCredential.h in Headers */,
</ins><span class="cx">                                 7C6523011E00D03400677F22 /* ApplePayPayment.h in Headers */,
</span><span class="cx">                                 1A8A64521D19FCFB00D0E00F /* ApplePayPaymentAuthorizedEvent.h in Headers */,
</span><span class="cx">                                 7C6522FB1E00C90900677F22 /* ApplePayPaymentContact.h in Headers */,
</span><span class="lines">@@ -25689,6 +25771,7 @@
</span><span class="cx">                                 E1BD331C182D8EE900C05D9F /* CryptoAlgorithmRsaSsaParamsDeprecated.h in Headers */,
</span><span class="cx">                                 E125F82C1822CFEC00D84CD9 /* CryptoAlgorithmSHA1.h in Headers */,
</span><span class="cx">                                 E19AC3EF1824DC7900349426 /* CryptoAlgorithmSHA224.h in Headers */,
</span><ins>+                                57B5F7F11E5B8C5A00F34F90 /* JSPasswordCredential.h in Headers */,
</ins><span class="cx">                                 E19AC3F11824DC7900349426 /* CryptoAlgorithmSHA256.h in Headers */,
</span><span class="cx">                                 E19AC3F31824DC7900349426 /* CryptoAlgorithmSHA384.h in Headers */,
</span><span class="cx">                                 E19AC3F51824DC7900349426 /* CryptoAlgorithmSHA512.h in Headers */,
</span><span class="lines">@@ -25977,6 +26060,7 @@
</span><span class="cx">                                 A7CA59630B27C1F200FA021D /* DragClient.h in Headers */,
</span><span class="cx">                                 A7CA595D0B27BD9E00FA021D /* DragController.h in Headers */,
</span><span class="cx">                                 A7B6E69F0B291A9600D0529F /* DragData.h in Headers */,
</span><ins>+                                57B5F7D51E57CF6800F34F90 /* SiteBoundCredential.h in Headers */,
</ins><span class="cx">                                 A7CFB3D20B7ED10A0070C32D /* DragImage.h in Headers */,
</span><span class="cx">                                 81F65FF613788FAA00FF6F2D /* DragState.h in Headers */,
</span><span class="cx">                                 E1BA66F11742BD8600C20251 /* DynamicLinkerInterposing.h in Headers */,
</span><span class="lines">@@ -26461,6 +26545,7 @@
</span><span class="cx">                                 AA4C3A770B2B1679002334A2 /* InlineStyleSheetOwner.h in Headers */,
</span><span class="cx">                                 BCEA485A097D93020094C9E4 /* InlineTextBox.h in Headers */,
</span><span class="cx">                                 1C010701192594DF008A4201 /* InlineTextBoxStyle.h in Headers */,
</span><ins>+                                57B5F7E31E57DBC800F34F90 /* JSSiteBoundCredentialData.h in Headers */,
</ins><span class="cx">                                 510A58E51BAA40B100C19282 /* InProcessIDBServer.h in Headers */,
</span><span class="cx">                                 2EB767571DA19BDF003E23B5 /* InputEvent.h in Headers */,
</span><span class="cx">                                 37E3524D12450C6600BAF5D9 /* InputType.h in Headers */,
</span><span class="lines">@@ -26666,6 +26751,7 @@
</span><span class="cx">                                 65DF31F809D1CC60000BE325 /* JSDOMImplementation.h in Headers */,
</span><span class="cx">                                 4138F8581D253F0E001CB61E /* JSDOMIterator.h in Headers */,
</span><span class="cx">                                 A9D248070D757E7D00FDF959 /* JSDOMMimeType.h in Headers */,
</span><ins>+                                57B5F7E11E57DBC800F34F90 /* JSSiteBoundCredential.h in Headers */,
</ins><span class="cx">                                 A9D248090D757E7D00FDF959 /* JSDOMMimeTypeArray.h in Headers */,
</span><span class="cx">                                 52CCA9E315E3F62C0053C77F /* JSDOMNamedFlowCollection.h in Headers */,
</span><span class="cx">                                 1ACE53E00A8D18810022947D /* JSDOMParser.h in Headers */,
</span><span class="lines">@@ -26773,6 +26859,7 @@
</span><span class="cx">                                 A80E7B0D0A19D606007FB8C5 /* JSHTMLLinkElement.h in Headers */,
</span><span class="cx">                                 1AE2AB280A1CE63B00B42B25 /* JSHTMLMapElement.h in Headers */,
</span><span class="cx">                                 BC491B790C023EFD009D6316 /* JSHTMLMarqueeElement.h in Headers */,
</span><ins>+                                57C7A69F1E57917800C67D71 /* JSBasicCredential.h in Headers */,
</ins><span class="cx">                                 E446143A0CD689C800FADA75 /* JSHTMLMediaElement.h in Headers */,
</span><span class="cx">                                 1AE2AE5C0A1D26F200B42B25 /* JSHTMLMenuElement.h in Headers */,
</span><span class="cx">                                 A80E7A180A19C3D6007FB8C5 /* JSHTMLMetaElement.h in Headers */,
</span><span class="lines">@@ -27471,6 +27558,7 @@
</span><span class="cx">                                 979F43D41075E44A0000F83B /* NavigationScheduler.h in Headers */,
</span><span class="cx">                                 A9C6E5A60D746458006442E9 /* Navigator.h in Headers */,
</span><span class="cx">                                 E12719C70EEEC16800F61213 /* NavigatorBase.h in Headers */,
</span><ins>+                                57B5F7ED1E57F1E300F34F90 /* PasswordCredential.h in Headers */,
</ins><span class="cx">                                 9711460414EF009A00674FD9 /* NavigatorGeolocation.h in Headers */,
</span><span class="cx">                                 5EA725D61ACABD5700EAD17B /* NavigatorMediaDevices.h in Headers */,
</span><span class="cx">                                 996E59DF1DF0128D006612B9 /* NavigatorWebDriver.h in Headers */,
</span><span class="lines">@@ -27778,6 +27866,7 @@
</span><span class="cx">                                 836DAA061CEAB80D00A2B707 /* RenderDescendantIterator.h in Headers */,
</span><span class="cx">                                 D302754A12A5FE84004BD828 /* RenderDetailsMarker.h in Headers */,
</span><span class="cx">                                 A76E5F7F135E0DCF00A69837 /* RenderedDocumentMarker.h in Headers */,
</span><ins>+                                57B5F7E71E57DBE000F34F90 /* JSCredentialData.h in Headers */,
</ins><span class="cx">                                 9B32CDA913DF7FA900F34D13 /* RenderedPosition.h in Headers */,
</span><span class="cx">                                 E43A023B17EB370A004CDD25 /* RenderElement.h in Headers */,
</span><span class="cx">                                 0F5B7A5510F65D7A00376302 /* RenderEmbeddedObject.h in Headers */,
</span><span class="lines">@@ -27983,6 +28072,7 @@
</span><span class="cx">                                 078E094317D16E1C00420AA1 /* RTCSessionDescriptionDescriptor.h in Headers */,
</span><span class="cx">                                 078E094417D16E1C00420AA1 /* RTCSessionDescriptionRequest.h in Headers */,
</span><span class="cx">                                 078E092A17D14D1C00420AA1 /* RTCStatsReport.h in Headers */,
</span><ins>+                                57B5F7DB1E57D4CC00F34F90 /* SiteBoundCredentialData.h in Headers */,
</ins><span class="cx">                                 5E2C43681BCEE3770001E2BC /* RTCTrackEvent.h in Headers */,
</span><span class="cx">                                 078E094717D16E1C00420AA1 /* RTCVoidRequest.h in Headers */,
</span><span class="cx">                                 5824ABA31AE81116009074B7 /* RubyElement.h in Headers */,
</span><span class="lines">@@ -29283,6 +29373,7 @@
</span><span class="cx">                         buildActionMask = 2147483647;
</span><span class="cx">                         files = (
</span><span class="cx">                                 570440531E5278B200356601 /* CryptoAlgorithmAES_CFB.cpp in Sources */,
</span><ins>+                                57C7A6A01E57919B00C67D71 /* JSBasicCredential.cpp in Sources */,
</ins><span class="cx">                                 41E1B1D00FF5986900576B3B /* AbstractWorker.cpp in Sources */,
</span><span class="cx">                                 37F57AB91A50726900876F98 /* AccessibilityARIAGrid.cpp in Sources */,
</span><span class="cx">                                 37F57ABA1A50726F00876F98 /* AccessibilityARIAGridCell.cpp in Sources */,
</span><span class="lines">@@ -29357,6 +29448,7 @@
</span><span class="cx">                                 A8C4A80E09D563270003AC8D /* Attr.cpp in Sources */,
</span><span class="cx">                                 E4A814D81C70E10500BF85AC /* AttributeChangeInvalidation.cpp in Sources */,
</span><span class="cx">                                 FD629EA4154B47160006D026 /* AudioBasicInspectorNode.cpp in Sources */,
</span><ins>+                                57B5F7E61E57DBE000F34F90 /* JSCredentialData.cpp in Sources */,
</ins><span class="cx">                                 FD315FF612B0267600C1A359 /* AudioBasicProcessorNode.cpp in Sources */,
</span><span class="cx">                                 FD315FF812B0267600C1A359 /* AudioBuffer.cpp in Sources */,
</span><span class="cx">                                 FD315FFB12B0267600C1A359 /* AudioBufferSourceNode.cpp in Sources */,
</span><span class="lines">@@ -30329,6 +30421,7 @@
</span><span class="cx">                                 120DE3FE1C87E18800B6D4DD /* JSAnimationEffect.cpp in Sources */,
</span><span class="cx">                                 3198480B1A1E6CE400A13318 /* JSAnimationEvent.cpp in Sources */,
</span><span class="cx">                                 1221E06C1C03D224006A1A00 /* JSAnimationTimeline.cpp in Sources */,
</span><ins>+                                57B5F7E21E57DBC800F34F90 /* JSSiteBoundCredentialData.cpp in Sources */,
</ins><span class="cx">                                 1221E0731C03E4C2006A1A00 /* JSAnimationTimelineCustom.cpp in Sources */,
</span><span class="cx">                                 7C6579EF1E00856600E3A27A /* JSApplePayLineItem.cpp in Sources */,
</span><span class="cx">                                 7C65231E1E018B5A00677F22 /* JSApplePayPayment.cpp in Sources */,
</span><span class="lines">@@ -30369,6 +30462,7 @@
</span><span class="cx">                                 7C77C3D41DEF178E00A50BFA /* JSBlobPropertyBag.cpp in Sources */,
</span><span class="cx">                                 14DCF3B21B6BE2080062D4C3 /* JSByteLengthQueuingStrategy.cpp in Sources */,
</span><span class="cx">                                 1449E287107D4DB400B5793F /* JSCallbackData.cpp in Sources */,
</span><ins>+                                57B5F7D41E57CF6800F34F90 /* SiteBoundCredential.cpp in Sources */,
</ins><span class="cx">                                 65DF323909D1DE65000BE325 /* JSCanvasGradient.cpp in Sources */,
</span><span class="cx">                                 65DF323B09D1DE65000BE325 /* JSCanvasPattern.cpp in Sources */,
</span><span class="cx">                                 49EED1441051969400099FAB /* JSCanvasRenderingContext2D.cpp in Sources */,
</span><span class="lines">@@ -31298,6 +31392,7 @@
</span><span class="cx">                                 D6E276AF14637455001D280A /* MutationObserverRegistration.cpp in Sources */,
</span><span class="cx">                                 C6F08FBC1430FE8F00685849 /* MutationRecord.cpp in Sources */,
</span><span class="cx">                                 52B6C9C515E3F4DF00690B05 /* NamedFlowCollection.cpp in Sources */,
</span><ins>+                                57B5F7EC1E57F1E300F34F90 /* PasswordCredential.cpp in Sources */,
</ins><span class="cx">                                 314BE3A61B3103FB00141982 /* NamedImageGeneratedImage.cpp in Sources */,
</span><span class="cx">                                 BCF34A3711A231CD00C71804 /* NamedNodeMap.cpp in Sources */,
</span><span class="cx">                                 A81872240977D3C0005826D9 /* NameNodeList.cpp in Sources */,
</span><span class="lines">@@ -31687,6 +31782,7 @@
</span><span class="cx">                                 5824ABA21AE81116009074B7 /* RubyElement.cpp in Sources */,
</span><span class="cx">                                 5824ABA61AE81384009074B7 /* RubyTextElement.cpp in Sources */,
</span><span class="cx">                                 A79BADA1161E7F3F00C2E652 /* RuleFeature.cpp in Sources */,
</span><ins>+                                57B5F7E01E57DBC800F34F90 /* JSSiteBoundCredential.cpp in Sources */,
</ins><span class="cx">                                 A79BADA3161E7F3F00C2E652 /* RuleSet.cpp in Sources */,
</span><span class="cx">                                 2D76BB8419456F8100CFD29A /* RunLoopObserver.cpp in Sources */,
</span><span class="cx">                                 1A569D1E0D7E2B82007C3983 /* runtime_array.cpp in Sources */,
</span><span class="lines">@@ -31822,6 +31918,7 @@
</span><span class="cx">                                 5C688AA31D3814BF000B54FA /* SocketProvider.cpp in Sources */,
</span><span class="cx">                                 510D4A36103165EE0049EA54 /* SocketStreamHandle.cpp in Sources */,
</span><span class="cx">                                 51ABAE1F103C1913008C5260 /* SocketStreamHandleImplCFNet.cpp in Sources */,
</span><ins>+                                57C7A6941E578ACA00C67D71 /* BasicCredential.cpp in Sources */,
</ins><span class="cx">                                 E45390470EAFD637003695C8 /* SoundIOS.mm in Sources */,
</span><span class="cx">                                 4B3043C90AE0371D00A82647 /* SoundMac.mm in Sources */,
</span><span class="cx">                                 84A81F3D0FC7DFF000955300 /* SourceAlpha.cpp in Sources */,
</span><span class="lines">@@ -32191,6 +32288,7 @@
</span><span class="cx">                                 E17B491516A9B094001C8839 /* TransitionEvent.cpp in Sources */,
</span><span class="cx">                                 49E911D10EF86D47009D0CAF /* TranslateTransformOperation.cpp in Sources */,
</span><span class="cx">                                 854FE7360A2297BE0058D7AD /* Traversal.cpp in Sources */,
</span><ins>+                                57B5F7F01E5B8C5A00F34F90 /* JSPasswordCredential.cpp in Sources */,
</ins><span class="cx">                                 14D64B5C134A5B6B00E58FDA /* TreeScope.cpp in Sources */,
</span><span class="cx">                                 A77E1FEF14AACB6E005B7CB6 /* TreeScopeAdopter.cpp in Sources */,
</span><span class="cx">                                 854FE7380A2297BE0058D7AD /* TreeWalker.cpp in Sources */,
</span></span></pre>
</div>
</div>

</body>
</html>