Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: LayoutTests/http/tests/w3c/resources/idlharness.js

Issue 1061543006: Pull in the latest upstream testharness.js changes. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase/tweaks for affected tests Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 Distributed under both the W3C Test Suite License [1] and the W3C 2 Distributed under both the W3C Test Suite License [1] and the W3C
3 3-clause BSD License [2]. To contribute to a W3C Test Suite, see the 3 3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
4 policies and contribution forms [3]. 4 policies and contribution forms [3].
5 5
6 [1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license 6 [1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
7 [2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license 7 [2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
8 [3] http://www.w3.org/2004/10/27-testcases 8 [3] http://www.w3.org/2004/10/27-testcases
9 */ 9 */
10 10
11 /* 11 /* For user documentation see docs/idlharness.md */
12 * This file automatically generates browser tests for WebIDL interfaces, using
13 * the testharness.js framework. To use, first include the following:
14 *
15 * <script src=/resources/testharness.js></script>
16 * <script src=/resources/testharnessreport.js></script>
17 * <script src=/resources/WebIDLParser.js></script>
18 * <script src=/resources/idlharness.js></script>
19 *
20 * Then you'll need some type of IDLs. Here's some script that can be run on a
21 * spec written in HTML, which will grab all the elements with class="idl",
22 * concatenate them, and replace the body so you can copy-paste:
23 *
24 var s = "";
25 [].forEach.call(document.getElementsByClassName("idl"), function(idl) {
26 //https://www.w3.org/Bugs/Public/show_bug.cgi?id=14914
27 if (!idl.classList.contains("extract"))
28 {
29 s += idl.textContent + "\n\n";
30 }
31 });
32 document.body.innerHTML = '<pre></pre>';
33 document.body.firstChild.textContent = s;
34 *
35 * (TODO: write this in Python or something so that it can be done from the
36 * command line instead.)
37 *
38 * Once you have that, put it in your script somehow. The easiest way is to
39 * embed it literally in an HTML file with <script type=text/plain> or similar,
40 * so that you don't have to do any escaping. Another possibility is to put it
41 * in a separate .idl file that's fetched via XHR or similar. Sample usage:
42 *
43 * var idl_array = new IdlArray();
44 * idl_array.add_untested_idls("interface Node { readonly attribute DOMString nodeName; };");
45 * idl_array.add_idls("interface Document : Node { readonly attribute DOMStrin g URL; };");
46 * idl_array.add_objects({Document: ["document"]});
47 * idl_array.test();
48 *
49 * This tests that window.Document exists and meets all the requirements of
50 * WebIDL. It also tests that window.document (the result of evaluating the
51 * string "document") has URL and nodeName properties that behave as they
52 * should, and otherwise meets WebIDL's requirements for an object whose
53 * primary interface is Document. It does not test that window.Node exists,
54 * which is what you want if the Node interface is already tested in some other
55 * specification's suite and your specification only extends or refers to it.
56 * Of course, each IDL string can define many different things, and calls to
57 * add_objects() can register many different objects for different interfaces:
58 * this is a very simple example.
59 *
60 * TODO: Write assert_writable, assert_enumerable, assert_configurable and
61 * their inverses, and use those instead of just checking
62 * getOwnPropertyDescriptor.
63 *
64 * == Public methods of IdlArray ==
65 *
66 * IdlArray objects can be obtained with new IdlArray(). Anything not
67 * documented in this section should be considered an implementation detail,
68 * and outside callers should not use it.
69 *
70 * add_idls(idl_string):
71 * Parses idl_string (throwing on parse error) and adds the results to the
72 * IdlArray. All the definitions will be tested when you run test(). If
73 * some of the definitions refer to other definitions, those must be present
74 * too. For instance, if idl_string says that Document inherits from Node,
75 * the Node interface must also have been provided in some call to add_idls()
76 * or add_untested_idls().
77 *
78 * add_untested_idls(idl_string):
79 * Like add_idls(), but the definitions will not be tested. If an untested
80 * interface is added and then extended with a tested partial interface, the
81 * members of the partial interface will still be tested. Also, all the
82 * members will still be tested for objects added with add_objects(), because
83 * you probably want to test that (for instance) window.document has all the
84 * properties from Node, not just Document, even if the Node interface itself
85 * is tested in a different test suite.
86 *
87 * add_objects(dict):
88 * dict should be an object whose keys are the names of interfaces or
89 * exceptions, and whose values are arrays of strings. When an interface or
90 * exception is tested, every string registered for it with add_objects()
91 * will be evaluated, and tests will be run on the result to verify that it
92 * correctly implements that interface or exception. This is the only way to
93 * test anything about [NoInterfaceObject] interfaces, and there are many
94 * tests that can't be run on any interface without an object to fiddle with.
95 *
96 * The interface has to be the *primary* interface of all the objects
97 * provided. For example, don't pass {Node: ["document"]}, but rather
98 * {Document: ["document"]}. Assuming the Document interface was declared to
99 * inherit from Node, this will automatically test that document implements
100 * the Node interface too.
101 *
102 * Warning: methods will be called on any provided objects, in a manner that
103 * WebIDL requires be safe. For instance, if a method has mandatory
104 * arguments, the test suite will try calling it with too few arguments to
105 * see if it throws an exception. If an implementation incorrectly runs the
106 * function instead of throwing, this might have side effects, possibly even
107 * preventing the test suite from running correctly.
108 *
109 * prevent_multiple_testing(name):
110 * This is a niche method for use in case you're testing many objects that
111 * implement the same interfaces, and don't want to retest the same
112 * interfaces every single time. For instance, HTML defines many interfaces
113 * that all inherit from HTMLElement, so the HTML test suite has something
114 * like
115 * .add_objects({
116 * HTMLHtmlElement: ['document.documentElement'],
117 * HTMLHeadElement: ['document.head'],
118 * HTMLBodyElement: ['document.body'],
119 * ...
120 * })
121 * and so on for dozens of element types. This would mean that it would
122 * retest that each and every one of those elements implements HTMLElement,
123 * Element, and Node, which would be thousands of basically redundant tests.
124 * The test suite therefore calls prevent_multiple_testing("HTMLElement").
125 * This means that once one object has been tested to implement HTMLElement
126 * and its ancestors, no other object will be. Thus in the example code
127 * above, the harness would test that document.documentElement correctly
128 * implements HTMLHtmlElement, HTMLElement, Element, and Node; but
129 * document.head would only be tested for HTMLHeadElement, and so on for
130 * further objects.
131 *
132 * test():
133 * Run all tests. This should be called after you've called all other
134 * methods to add IDLs and objects.
135 */
136 12
137 /** 13 /**
138 * Notes for people who want to edit this file (not just use it as a library): 14 * Notes for people who want to edit this file (not just use it as a library):
139 * 15 *
140 * Most of the interesting stuff happens in the derived classes of IdlObject, 16 * Most of the interesting stuff happens in the derived classes of IdlObject,
141 * especially IdlInterface. The entry point for all IdlObjects is .test(), 17 * especially IdlInterface. The entry point for all IdlObjects is .test(),
142 * which is called by IdlArray.test(). An IdlObject is conceptually just 18 * which is called by IdlArray.test(). An IdlObject is conceptually just
143 * "thing we want to run tests on", and an IdlArray is an array of IdlObjects 19 * "thing we want to run tests on", and an IdlArray is an array of IdlObjects
144 * with some additional data thrown in. 20 * with some additional data thrown in.
145 * 21 *
(...skipping 29 matching lines...) Expand all
175 /// Helpers /// 51 /// Helpers ///
176 function constValue (cnt) { 52 function constValue (cnt) {
177 if (cnt.type === "null") return null; 53 if (cnt.type === "null") return null;
178 if (cnt.type === "NaN") return NaN; 54 if (cnt.type === "NaN") return NaN;
179 if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity; 55 if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity;
180 return cnt.value; 56 return cnt.value;
181 } 57 }
182 58
183 /// IdlArray /// 59 /// IdlArray ///
184 // Entry point 60 // Entry point
185 window.IdlArray = function() 61 self.IdlArray = function()
186 //@{ 62 //@{
187 { 63 {
188 /** 64 /**
189 * A map from strings to the corresponding named IdlObject, such as 65 * A map from strings to the corresponding named IdlObject, such as
190 * IdlInterface or IdlException. These are the things that test() will run 66 * IdlInterface or IdlException. These are the things that test() will run
191 * tests on. 67 * tests on.
192 */ 68 */
193 this.members = {}; 69 this.members = {};
194 70
195 /** 71 /**
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 } 159 }
284 160
285 parsed_idl.array = this; 161 parsed_idl.array = this;
286 if (parsed_idl.name in this.members) 162 if (parsed_idl.name in this.members)
287 { 163 {
288 throw "Duplicate identifier " + parsed_idl.name; 164 throw "Duplicate identifier " + parsed_idl.name;
289 } 165 }
290 switch(parsed_idl.type) 166 switch(parsed_idl.type)
291 { 167 {
292 case "interface": 168 case "interface":
293 this.members[parsed_idl.name] = new IdlInterface(parsed_idl); 169 this.members[parsed_idl.name] =
294 break; 170 new IdlInterface(parsed_idl, /* is_callback = */ false);
295
296 case "exception":
297 this.members[parsed_idl.name] = new IdlException(parsed_idl);
298 break; 171 break;
299 172
300 case "dictionary": 173 case "dictionary":
301 // Nothing to test, but we need the dictionary info around for type 174 // Nothing to test, but we need the dictionary info around for type
302 // checks 175 // checks
303 this.members[parsed_idl.name] = new IdlDictionary(parsed_idl); 176 this.members[parsed_idl.name] = new IdlDictionary(parsed_idl);
304 break; 177 break;
305 178
306 case "typedef": 179 case "typedef":
307 this.members[parsed_idl.name] = new IdlTypedef(parsed_idl); 180 this.members[parsed_idl.name] = new IdlTypedef(parsed_idl);
308 break; 181 break;
309 182
310 case "callback": 183 case "callback":
311 // TODO 184 // TODO
312 console.log("callback not yet supported"); 185 console.log("callback not yet supported");
313 break; 186 break;
314 187
315 case "enum": 188 case "enum":
316 this.members[parsed_idl.name] = new IdlEnum(parsed_idl); 189 this.members[parsed_idl.name] = new IdlEnum(parsed_idl);
317 break; 190 break;
318 191
319 case "callback interface": 192 case "callback interface":
320 // TODO 193 this.members[parsed_idl.name] =
321 console.log("callback interface not yet supported"); 194 new IdlInterface(parsed_idl, /* is_callback = */ true);
322 break; 195 break;
323 196
324 default: 197 default:
325 throw parsed_idl.name + ": " + parsed_idl.type + " not yet supported "; 198 throw parsed_idl.name + ": " + parsed_idl.type + " not yet supported ";
326 } 199 }
327 }.bind(this)); 200 }.bind(this));
328 }; 201 };
329 202
330 //@} 203 //@}
331 IdlArray.prototype.add_objects = function(dict) 204 IdlArray.prototype.add_objects = function(dict)
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 assert_equals(typeof value, "number"); 403 assert_equals(typeof value, "number");
531 assert_equals(value, Math.floor(value), "not an integer"); 404 assert_equals(value, Math.floor(value), "not an integer");
532 assert_true(0 <= value && value <= 4294967295, "unsigned long " + va lue + " not in range [0, 4294967295]"); 405 assert_true(0 <= value && value <= 4294967295, "unsigned long " + va lue + " not in range [0, 4294967295]");
533 return; 406 return;
534 407
535 case "long long": 408 case "long long":
536 assert_equals(typeof value, "number"); 409 assert_equals(typeof value, "number");
537 return; 410 return;
538 411
539 case "unsigned long long": 412 case "unsigned long long":
413 case "DOMTimeStamp":
540 assert_equals(typeof value, "number"); 414 assert_equals(typeof value, "number");
541 assert_true(0 <= value, "unsigned long long is negative"); 415 assert_true(0 <= value, "unsigned long long is negative");
542 return; 416 return;
543 417
544 case "float": 418 case "float":
545 case "double": 419 case "double":
420 case "DOMHighResTimeStamp":
546 case "unrestricted float": 421 case "unrestricted float":
547 case "unrestricted double": 422 case "unrestricted double":
548 // TODO: distinguish these cases 423 // TODO: distinguish these cases
549 assert_equals(typeof value, "number"); 424 assert_equals(typeof value, "number");
550 return; 425 return;
551 426
552 case "DOMString": 427 case "DOMString":
428 case "ByteString":
429 case "USVString":
430 // TODO: https://github.com/w3c/testharness.js/issues/92
553 assert_equals(typeof value, "string"); 431 assert_equals(typeof value, "string");
554 return; 432 return;
555 433
556 case "object": 434 case "object":
557 assert_true(typeof value == "object" || typeof value == "function", "wrong type: not object or function"); 435 assert_true(typeof value == "object" || typeof value == "function", "wrong type: not object or function");
558 return; 436 return;
559 } 437 }
560 438
561 if (!(type in this.members)) 439 if (!(type in this.members))
562 { 440 {
563 throw "Unrecognized type " + type; 441 throw "Unrecognized type " + type;
564 } 442 }
565 443
566 if (this.members[type] instanceof IdlInterface) 444 if (this.members[type] instanceof IdlInterface)
567 { 445 {
568 // We don't want to run the full 446 // We don't want to run the full
569 // IdlInterface.prototype.test_instance_of, because that could result 447 // IdlInterface.prototype.test_instance_of, because that could result
570 // in an infinite loop. TODO: This means we don't have tests for 448 // in an infinite loop. TODO: This means we don't have tests for
571 // NoInterfaceObject interfaces, and we also can't test objects that 449 // NoInterfaceObject interfaces, and we also can't test objects that
572 // come from another window. 450 // come from another self.
573 assert_true(typeof value == "object" || typeof value == "function", "wro ng type: not object or function"); 451 assert_true(typeof value == "object" || typeof value == "function", "wro ng type: not object or function");
574 if (value instanceof Object 452 if (value instanceof Object
575 && !this.members[type].has_extended_attribute("NoInterfaceObject") 453 && !this.members[type].has_extended_attribute("NoInterfaceObject")
576 && type in window) 454 && type in self)
577 { 455 {
578 assert_true(value instanceof window[type], "not instanceof " + type) ; 456 assert_true(value instanceof self[type], "not instanceof " + type);
579 } 457 }
580 } 458 }
581 else if (this.members[type] instanceof IdlEnum) 459 else if (this.members[type] instanceof IdlEnum)
582 { 460 {
583 assert_equals(typeof value, "string"); 461 assert_equals(typeof value, "string");
584 } 462 }
585 else if (this.members[type] instanceof IdlDictionary) 463 else if (this.members[type] instanceof IdlDictionary)
586 { 464 {
587 // TODO: Test when we actually have something to test this on 465 // TODO: Test when we actually have something to test this on
588 } 466 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 /** 521 /**
644 * The name (as a string) of the dictionary type we inherit from, or null 522 * The name (as a string) of the dictionary type we inherit from, or null
645 * if there is none. 523 * if there is none.
646 */ 524 */
647 this.base = obj.inheritance; 525 this.base = obj.inheritance;
648 } 526 }
649 527
650 //@} 528 //@}
651 IdlDictionary.prototype = Object.create(IdlObject.prototype); 529 IdlDictionary.prototype = Object.create(IdlObject.prototype);
652 530
653 /// IdlExceptionOrInterface /// 531 /// IdlInterface ///
654 // Code sharing! 532 function IdlInterface(obj, is_callback) {
655 function IdlExceptionOrInterface(obj)
656 //@{
657 {
658 /** 533 /**
659 * obj is an object produced by the WebIDLParser.js "exception" or 534 * obj is an object produced by the WebIDLParser.js "exception" or
660 * "interface" production, as appropriate. 535 * "interface" production, as appropriate.
661 */ 536 */
662 537
663 /** Self-explanatory. */ 538 /** Self-explanatory. */
664 this.name = obj.name; 539 this.name = obj.name;
665 540
666 /** A back-reference to our IdlArray. */ 541 /** A back-reference to our IdlArray. */
667 this.array = obj.array; 542 this.array = obj.array;
668 543
669 /** 544 /**
670 * An indicator of whether we should run tests on the (exception) interface 545 * An indicator of whether we should run tests on the (exception) interface
671 * object and (exception) interface prototype object. Tests on members are 546 * object and (exception) interface prototype object. Tests on members are
672 * controlled by .untested on each member, not this. 547 * controlled by .untested on each member, not this.
673 */ 548 */
674 this.untested = obj.untested; 549 this.untested = obj.untested;
675 550
676 /** An array of objects produced by the "ExtAttr" production. */ 551 /** An array of objects produced by the "ExtAttr" production. */
677 this.extAttrs = obj.extAttrs; 552 this.extAttrs = obj.extAttrs;
678 553
679 /** An array of IdlInterfaceMembers. */ 554 /** An array of IdlInterfaceMembers. */
680 this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); }); 555 this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); });
556 if (this.has_extended_attribute("Unforgeable")) {
557 this.members
558 .filter(function(m) { return !m["static"] && (m.type == "attribute" || m.type == "operation"); })
559 .forEach(function(m) { return m.isUnforgeable = true; });
560 }
681 561
682 /** 562 /**
683 * The name (as a string) of the type we inherit from, or null if there is 563 * The name (as a string) of the type we inherit from, or null if there is
684 * none. 564 * none.
685 */ 565 */
686 this.base = obj.inheritance; 566 this.base = obj.inheritance;
567
568 this._is_callback = is_callback;
687 } 569 }
570 IdlInterface.prototype = Object.create(IdlObject.prototype);
571 IdlInterface.prototype.is_callback = function()
572 //@{
573 {
574 return this._is_callback;
575 };
576 //@}
688 577
578 IdlInterface.prototype.has_constants = function()
579 //@{
580 {
581 return this.members.some(function(member) {
582 return member.type === "const";
583 });
584 };
689 //@} 585 //@}
690 IdlExceptionOrInterface.prototype = Object.create(IdlObject.prototype); 586
691 IdlExceptionOrInterface.prototype.test = function() 587 IdlInterface.prototype.is_global = function()
588 //@{
589 {
590 return this.extAttrs.some(function(attribute) {
591 return attribute.name === "Global" ||
592 attribute.name === "PrimaryGlobal";
593 });
594 };
595 //@}
596
597 IdlInterface.prototype.test = function()
692 //@{ 598 //@{
693 { 599 {
694 if (this.has_extended_attribute("NoInterfaceObject")) 600 if (this.has_extended_attribute("NoInterfaceObject"))
695 { 601 {
696 // No tests to do without an instance. TODO: We should still be able 602 // No tests to do without an instance. TODO: We should still be able
697 // to run tests on the prototype object, if we obtain one through some 603 // to run tests on the prototype object, if we obtain one through some
698 // other means. 604 // other means.
699 return; 605 return;
700 } 606 }
701 607
702 if (!this.untested) 608 if (!this.untested)
703 { 609 {
704 // First test things to do with the exception/interface object and 610 // First test things to do with the exception/interface object and
705 // exception/interface prototype object. 611 // exception/interface prototype object.
706 this.test_self(); 612 this.test_self();
707 } 613 }
708 // Then test things to do with its members (constants, fields, attributes, 614 // Then test things to do with its members (constants, fields, attributes,
709 // operations, . . .). These are run even if .untested is true, because 615 // operations, . . .). These are run even if .untested is true, because
710 // members might themselves be marked as .untested. This might happen to 616 // members might themselves be marked as .untested. This might happen to
711 // interfaces if the interface itself is untested but a partial interface 617 // interfaces if the interface itself is untested but a partial interface
712 // that extends it is tested -- then the interface itself and its initial 618 // that extends it is tested -- then the interface itself and its initial
713 // members will be marked as untested, but the members added by the partial 619 // members will be marked as untested, but the members added by the partial
714 // interface are still tested. 620 // interface are still tested.
715 this.test_members(); 621 this.test_members();
716 }; 622 };
717
718 //@}
719
720 /// IdlException ///
721 function IdlException(obj) { IdlExceptionOrInterface.call(this, obj); }
722 IdlException.prototype = Object.create(IdlExceptionOrInterface.prototype);
723 IdlException.prototype.test_self = function()
724 //@{
725 {
726 test(function()
727 {
728 // "For every exception that is not declared with the
729 // [NoInterfaceObject] extended attribute, a corresponding property
730 // must exist on the exception’s relevant namespace object. The name of
731 // the property is the identifier of the exception, and its value is an
732 // object called the exception interface object, which provides access
733 // to any constants that have been associated with the exception. The
734 // property has the attributes { [[Writable]]: true, [[Enumerable]]:
735 // false, [[Configurable]]: true }."
736 assert_own_property(window, this.name,
737 "window does not have own property " + format_value( this.name));
738 var desc = Object.getOwnPropertyDescriptor(window, this.name);
739 assert_false("get" in desc, "window's property " + format_value(this.nam e) + " has getter");
740 assert_false("set" in desc, "window's property " + format_value(this.nam e) + " has setter");
741 assert_true(desc.writable, "window's property " + format_value(this.name ) + " is not writable");
742 assert_false(desc.enumerable, "window's property " + format_value(this.n ame) + " is enumerable");
743 assert_true(desc.configurable, "window's property " + format_value(this. name) + " is not configurable");
744
745 // "The exception interface object for a given exception must be a
746 // function object."
747 // "If an object is defined to be a function object, then it has
748 // characteristics as follows:"
749 // "Its [[Prototype]] internal property is the Function prototype
750 // object."
751 // Note: This doesn't match browsers as of December 2011, see
752 // http://www.w3.org/Bugs/Public/show_bug.cgi?id=14813
753 assert_equals(Object.getPrototypeOf(window[this.name]), Function.prototy pe,
754 "prototype of window's property " + format_value(this.name ) + " is not Function.prototype");
755 // "Its [[Get]] internal property is set as described in ECMA-262
756 // section 15.3.5.4."
757 // Not much to test for this.
758 // "Its [[Construct]] internal property is set as described in ECMA-262
759 // section 13.2.2."
760 // Tested below.
761 // "Its [[HasInstance]] internal property is set as described in
762 // ECMA-262 section 15.3.5.3, unless otherwise specified."
763 // TODO
764 // "Its [[Class]] internal property is “Function”."
765 // String() returns something implementation-dependent, because it
766 // calls Function#toString.
767 assert_class_string(window[this.name], "Function",
768 "class string of " + this.name);
769
770 // TODO: Test 4.9.1.1. Exception interface object [[Call]] method
771 // (which does not match browsers:
772 // http://www.w3.org/Bugs/Public/show_bug.cgi?id=14885)
773 }.bind(this), this.name + " exception: existence and properties of exception interface object");
774
775 test(function()
776 {
777 assert_own_property(window, this.name,
778 "window does not have own property " + format_value( this.name));
779
780 // "The exception interface object must also have a property named
781 // “prototype” with attributes { [[Writable]]: false, [[Enumerable]]:
782 // false, [[Configurable]]: false } whose value is an object called the
783 // exception interface prototype object. This object also provides
784 // access to the constants that are declared on the exception."
785 assert_own_property(window[this.name], "prototype",
786 'exception "' + this.name + '" does not have own pro perty "prototype"');
787 var desc = Object.getOwnPropertyDescriptor(window[this.name], "prototype ");
788 assert_false("get" in desc, this.name + ".prototype has getter");
789 assert_false("set" in desc, this.name + ".prototype has setter");
790 assert_false(desc.writable, this.name + ".prototype is writable");
791 assert_false(desc.enumerable, this.name + ".prototype is enumerable");
792 assert_false(desc.configurable, this.name + ".prototype is configurable" );
793
794 // "The exception interface prototype object for a given exception must
795 // have an internal [[Prototype]] property whose value is as follows:
796 //
797 // "If the exception is declared to inherit from another exception,
798 // then the value of the internal [[Prototype]] property is the
799 // exception interface prototype object for the inherited exception.
800 // "Otherwise, the exception is not declared to inherit from another
801 // exception. The value of the internal [[Prototype]] property is the
802 // Error prototype object ([ECMA-262], section 15.11.3.1)."
803 //
804 // Note: This doesn't match browsers as of December 2011, see
805 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=14887.
806 var inherit_exception = this.base ? this.base : "Error";
807 assert_own_property(window, inherit_exception,
808 'should inherit from ' + inherit_exception + ', but window has no such property');
809 assert_own_property(window[inherit_exception], "prototype",
810 'should inherit from ' + inherit_exception + ', but that object has no "prototype" property');
811 assert_equals(Object.getPrototypeOf(window[this.name].prototype),
812 window[inherit_exception].prototype,
813 'prototype of ' + this.name + '.prototype is not ' + inher it_exception + '.prototype');
814
815 // "The class string of an exception interface prototype object is the
816 // concatenation of the exception’s identifier and the string
817 // “Prototype”."
818 assert_class_string(window[this.name].prototype, this.name + "Prototype" ,
819 "class string of " + this.name + ".prototype");
820 // TODO: Test String(), based on ES definition of
821 // Error.prototype.toString?
822 }.bind(this), this.name + " exception: existence and properties of exception interface prototype object");
823
824 test(function()
825 {
826 assert_own_property(window, this.name,
827 "window does not have own property " + format_value( this.name));
828 assert_own_property(window[this.name], "prototype",
829 'interface "' + this.name + '" does not have own pro perty "prototype"');
830
831 // "There must be a property named “name” on the exception interface
832 // prototype object with attributes { [[Writable]]: true,
833 // [[Enumerable]]: false, [[Configurable]]: true } and whose value is
834 // the identifier of the exception."
835 assert_own_property(window[this.name].prototype, "name",
836 'prototype object does not have own property "name"');
837 var desc = Object.getOwnPropertyDescriptor(window[this.name].prototype, "name");
838 assert_false("get" in desc, this.name + ".prototype.name has getter");
839 assert_false("set" in desc, this.name + ".prototype.name has setter");
840 assert_true(desc.writable, this.name + ".prototype.name is not writable" );
841 assert_false(desc.enumerable, this.name + ".prototype.name is enumerable ");
842 assert_true(desc.configurable, this.name + ".prototype.name is not confi gurable");
843 assert_equals(desc.value, this.name, this.name + ".prototype.name has in correct value");
844 }.bind(this), this.name + " exception: existence and properties of exception interface prototype object's \"name\" property");
845
846 test(function()
847 {
848 assert_own_property(window, this.name,
849 "window does not have own property " + format_value( this.name));
850 assert_own_property(window[this.name], "prototype",
851 'interface "' + this.name + '" does not have own pro perty "prototype"');
852
853 // "If the [NoInterfaceObject] extended attribute was not specified on
854 // the exception, then there must also be a property named
855 // “constructor” on the exception interface prototype object with
856 // attributes { [[Writable]]: true, [[Enumerable]]: false,
857 // [[Configurable]]: true } and whose value is a reference to the
858 // exception interface object for the exception."
859 assert_own_property(window[this.name].prototype, "constructor",
860 this.name + '.prototype does not have own property " constructor"');
861 var desc = Object.getOwnPropertyDescriptor(window[this.name].prototype, "constructor");
862 assert_false("get" in desc, this.name + ".prototype.constructor has gett er");
863 assert_false("set" in desc, this.name + ".prototype.constructor has sett er");
864 assert_true(desc.writable, this.name + ".prototype.constructor is not wr itable");
865 assert_false(desc.enumerable, this.name + ".prototype.constructor is enu merable");
866 assert_true(desc.configurable, this.name + ".prototype.constructor in no t configurable");
867 assert_equals(window[this.name].prototype.constructor, window[this.name] ,
868 this.name + '.prototype.constructor is not the same object as ' + this.name);
869 }.bind(this), this.name + " exception: existence and properties of exception interface prototype object's \"constructor\" property");
870 };
871
872 //@}
873 IdlException.prototype.test_members = function()
874 //@{
875 {
876 for (var i = 0; i < this.members.length; i++)
877 {
878 var member = this.members[i];
879 if (member.untested)
880 {
881 continue;
882 }
883 if (member.type == "const" && member.name != "prototype")
884 {
885 test(function()
886 {
887 assert_own_property(window, this.name,
888 "window does not have own property " + forma t_value(this.name));
889
890 // "For each constant defined on the exception, there must be a
891 // corresponding property on the exception interface object, if
892 // it exists, if the identifier of the constant is not
893 // “prototype”."
894 assert_own_property(window[this.name], member.name);
895 // "The value of the property is the ECMAScript value that is
896 // equivalent to the constant’s IDL value, according to the
897 // rules in section 4.2 above."
898 assert_equals(window[this.name][member.name], constValue(member. value),
899 "property has wrong value");
900 // "The property has attributes { [[Writable]]: false,
901 // [[Enumerable]]: true, [[Configurable]]: false }."
902 var desc = Object.getOwnPropertyDescriptor(window[this.name], me mber.name);
903 assert_false("get" in desc, "property has getter");
904 assert_false("set" in desc, "property has setter");
905 assert_false(desc.writable, "property is writable");
906 assert_true(desc.enumerable, "property is not enumerable");
907 assert_false(desc.configurable, "property is configurable");
908 }.bind(this), this.name + " exception: constant " + member.name + " on exception interface object");
909 // "In addition, a property with the same characteristics must
910 // exist on the exception interface prototype object."
911 test(function()
912 {
913 assert_own_property(window, this.name,
914 "window does not have own property " + forma t_value(this.name));
915 assert_own_property(window[this.name], "prototype",
916 'exception "' + this.name + '" does not have own property "prototype"');
917
918 assert_own_property(window[this.name].prototype, member.name);
919 assert_equals(window[this.name].prototype[member.name], constVal ue(member.value),
920 "property has wrong value");
921 var desc = Object.getOwnPropertyDescriptor(window[this.name].pro totype, member.name);
922 assert_false("get" in desc, "property has getter");
923 assert_false("set" in desc, "property has setter");
924 assert_false(desc.writable, "property is writable");
925 assert_true(desc.enumerable, "property is not enumerable");
926 assert_false(desc.configurable, "property is configurable");
927 }.bind(this), this.name + " exception: constant " + member.name + " on exception interface prototype object");
928 }
929 else if (member.type == "field")
930 {
931 test(function()
932 {
933 assert_own_property(window, this.name,
934 "window does not have own property " + forma t_value(this.name));
935 assert_own_property(window[this.name], "prototype",
936 'exception "' + this.name + '" does not have own property "prototype"');
937
938 // "For each exception field, there must be a corresponding
939 // property on the exception interface prototype object, whose
940 // characteristics are as follows:
941 // "The name of the property is the identifier of the exception
942 // field."
943 assert_own_property(window[this.name].prototype, member.name);
944 // "The property has attributes { [[Get]]: G, [[Enumerable]]:
945 // true, [[Configurable]]: true }, where G is the exception
946 // field getter, defined below."
947 var desc = Object.getOwnPropertyDescriptor(window[this.name].pro totype, member.name);
948 assert_false("value" in desc, "property descriptor has value but is supposed to be accessor");
949 assert_false("writable" in desc, 'property descriptor has "writa ble" field but is supposed to be accessor');
950 // TODO: ES5 doesn't seem to say whether desc should have a
951 // .set property.
952 assert_true(desc.enumerable, "property is not enumerable");
953 assert_true(desc.configurable, "property is not configurable");
954 // "The exception field getter is a Function object whose
955 // behavior when invoked is as follows:"
956 assert_equals(typeof desc.get, "function", "typeof getter");
957 // "The value of the Function object’s “length” property is the
958 // Number value 0."
959 // This test is before the TypeError tests so that it's easiest
960 // to see that Firefox 11a1 only fails one assert in this test.
961 assert_equals(desc.get.length, 0, "getter length");
962 // "Let O be the result of calling ToObject on the this value.
963 // "If O is not a platform object representing an exception for
964 // the exception on which the exception field was declared,
965 // then throw a TypeError."
966 // TODO: Test on a platform object representing an exception.
967 assert_throws(new TypeError(), function()
968 {
969 window[this.name].prototype[member.name];
970 }.bind(this), "getting property on prototype object must throw T ypeError");
971 assert_throws(new TypeError(), function()
972 {
973 desc.get.call({});
974 }.bind(this), "calling getter on wrong object type must throw Ty peError");
975 }.bind(this), this.name + " exception: field " + member.name + " on exception interface prototype object");
976 }
977 }
978 };
979
980 //@}
981 IdlException.prototype.test_object = function(desc)
982 //@{
983 {
984 var obj, exception = null;
985 try
986 {
987 obj = eval(desc);
988 }
989 catch(e)
990 {
991 exception = e;
992 }
993
994 test(function()
995 {
996 assert_equals(exception, null, "Unexpected exception when evaluating obj ect");
997 assert_equals(typeof obj, "object", "wrong typeof object");
998
999 // We can't easily test that its prototype is correct if there's no
1000 // interface object, or the object is from a different global
1001 // environment (not instanceof Object). TODO: test in this case that
1002 // its prototype at least looks correct, even if we can't test that
1003 // it's actually correct.
1004 if (!this.has_extended_attribute("NoInterfaceObject")
1005 && (typeof obj != "object" || obj instanceof Object))
1006 {
1007 assert_own_property(window, this.name,
1008 "window does not have own property " + format_va lue(this.name));
1009 assert_own_property(window[this.name], "prototype",
1010 'exception "' + this.name + '" does not have own property "prototype"');
1011
1012 // "The value of the internal [[Prototype]] property of the
1013 // exception object must be the exception interface prototype
1014 // object from the global environment the exception object is
1015 // associated with."
1016 assert_equals(Object.getPrototypeOf(obj),
1017 window[this.name].prototype,
1018 desc + "'s prototype is not " + this.name + ".prototyp e");
1019 }
1020
1021 // "The class string of the exception object must be the identifier of
1022 // the exception."
1023 assert_class_string(obj, this.name, "class string of " + desc);
1024 // Stringifier is not defined for DOMExceptions, because message isn't
1025 // defined.
1026 }.bind(this), this.name + " must be represented by " + desc);
1027
1028 for (var i = 0; i < this.members.length; i++)
1029 {
1030 var member = this.members[i];
1031 test(function()
1032 {
1033 assert_equals(exception, null, "Unexpected exception when evaluating object");
1034 assert_equals(typeof obj, "object", "wrong typeof object");
1035 assert_inherits(obj, member.name);
1036 if (member.type == "const")
1037 {
1038 assert_equals(obj[member.name], constValue(member.value));
1039 }
1040 if (member.type == "field")
1041 {
1042 this.array.assert_type_is(obj[member.name], member.idlType);
1043 }
1044 }.bind(this), this.name + " exception: " + desc + ' must inherit propert y "' + member.name + '" with the proper type');
1045 }
1046 };
1047 //@}
1048
1049 /// IdlInterface ///
1050 function IdlInterface(obj) { IdlExceptionOrInterface.call(this, obj); }
1051 IdlInterface.prototype = Object.create(IdlExceptionOrInterface.prototype);
1052 IdlInterface.prototype.is_callback = function()
1053 //@{
1054 {
1055 return this.has_extended_attribute("Callback");
1056 };
1057 //@}
1058
1059 IdlInterface.prototype.has_constants = function()
1060 //@{
1061 {
1062 return this.members.some(function(member) {
1063 return member.type === "const";
1064 });
1065 };
1066 //@} 623 //@}
1067 624
1068 IdlInterface.prototype.test_self = function() 625 IdlInterface.prototype.test_self = function()
1069 //@{ 626 //@{
1070 { 627 {
1071 test(function() 628 test(function()
1072 { 629 {
1073 // This function tests WebIDL as of 2012-11-28. 630 // This function tests WebIDL as of 2015-01-13.
631 // TODO: Consider [Exposed].
1074 632
1075 // "For every interface that: 633 // "For every interface that is exposed in a given ECMAScript global
634 // environment and:
1076 // * is a callback interface that has constants declared on it, or 635 // * is a callback interface that has constants declared on it, or
1077 // * is a non-callback interface that is not declared with the 636 // * is a non-callback interface that is not declared with the
1078 // [NoInterfaceObject] extended attribute, 637 // [NoInterfaceObject] extended attribute,
1079 // a corresponding property MUST exist on the ECMAScript global object. 638 // a corresponding property MUST exist on the ECMAScript global object.
1080 // The name of the property is the identifier of the interface, and its 639 // The name of the property is the identifier of the interface, and its
1081 // value is an object called the interface object. 640 // value is an object called the interface object.
1082 // The property has the attributes { [[Writable]]: true, 641 // The property has the attributes { [[Writable]]: true,
1083 // [[Enumerable]]: false, [[Configurable]]: true }." 642 // [[Enumerable]]: false, [[Configurable]]: true }."
1084 if (this.is_callback() && !this.has_constants()) { 643 if (this.is_callback() && !this.has_constants()) {
1085 return; 644 return;
1086 } 645 }
1087 646
1088 // TODO: Should we test here that the property is actually writable 647 // TODO: Should we test here that the property is actually writable
1089 // etc., or trust getOwnPropertyDescriptor? 648 // etc., or trust getOwnPropertyDescriptor?
1090 assert_own_property(window, this.name, 649 assert_own_property(self, this.name,
1091 "window does not have own property " + format_value( this.name)); 650 "self does not have own property " + format_value(th is.name));
1092 var desc = Object.getOwnPropertyDescriptor(window, this.name); 651 var desc = Object.getOwnPropertyDescriptor(self, this.name);
1093 assert_false("get" in desc, "window's property " + format_value(this.nam e) + " has getter"); 652 assert_false("get" in desc, "self's property " + format_value(this.name) + " has getter");
1094 assert_false("set" in desc, "window's property " + format_value(this.nam e) + " has setter"); 653 assert_false("set" in desc, "self's property " + format_value(this.name) + " has setter");
1095 assert_true(desc.writable, "window's property " + format_value(this.name ) + " is not writable"); 654 assert_true(desc.writable, "self's property " + format_value(this.name) + " is not writable");
1096 assert_false(desc.enumerable, "window's property " + format_value(this.n ame) + " is enumerable"); 655 assert_false(desc.enumerable, "self's property " + format_value(this.nam e) + " is enumerable");
1097 assert_true(desc.configurable, "window's property " + format_value(this. name) + " is not configurable"); 656 assert_true(desc.configurable, "self's property " + format_value(this.na me) + " is not configurable");
1098 657
1099 if (this.is_callback()) { 658 if (this.is_callback()) {
1100 // "The internal [[Prototype]] property of an interface object for 659 // "The internal [[Prototype]] property of an interface object for
1101 // a callback interface MUST be the Object.prototype object." 660 // a callback interface MUST be the Object.prototype object."
1102 assert_equals(Object.getPrototypeOf(window[this.name]), Object.proto type, 661 assert_equals(Object.getPrototypeOf(self[this.name]), Object.prototy pe,
1103 "prototype of window's property " + format_value(this. name) + " is not Object.prototype"); 662 "prototype of self's property " + format_value(this.na me) + " is not Object.prototype");
1104 663
1105 return; 664 return;
1106 } 665 }
1107 666
1108 // "The interface object for a given non-callback interface is a 667 // "The interface object for a given non-callback interface is a
1109 // function object." 668 // function object."
1110 // "If an object is defined to be a function object, then it has 669 // "If an object is defined to be a function object, then it has
1111 // characteristics as follows:" 670 // characteristics as follows:"
1112 671
1113 // "* Its [[Prototype]] internal property is the Function prototype 672 // Its [[Prototype]] internal property is otherwise specified (see
1114 // object." 673 // below).
1115 assert_equals(Object.getPrototypeOf(window[this.name]), Function.prototy pe,
1116 "prototype of window's property " + format_value(this.name ) + " is not Function.prototype");
1117 674
1118 // "* Its [[Get]] internal property is set as described in ECMA-262 675 // "* Its [[Get]] internal property is set as described in ECMA-262
1119 // section 15.3.5.4." 676 // section 9.1.8."
1120 // Not much to test for this. 677 // Not much to test for this.
1121 678
1122 // "* Its [[Construct]] internal property is set as described in 679 // "* Its [[Construct]] internal property is set as described in
1123 // ECMA-262 section 13.2.2." 680 // ECMA-262 section 19.2.2.3."
1124 // Tested below if no constructor is defined. TODO: test constructors 681 // Tested below if no constructor is defined. TODO: test constructors
1125 // if defined. 682 // if defined.
1126 683
1127 // "* Its [[HasInstance]] internal property is set as described in 684 // "* Its @@hasInstance property is set as described in ECMA-262
1128 // ECMA-262 section 15.3.5.3, unless otherwise specified." 685 // section 19.2.3.8, unless otherwise specified."
1129 // TODO 686 // TODO
1130 687
1131 // "* Its [[NativeBrand]] internal property is “Function”." 688 // ES6 (rev 30) 19.1.3.6:
1132 // String() returns something implementation-dependent, because it calls 689 // "Else, if O has a [[Call]] internal method, then let builtinTag be
1133 // Function#toString. 690 // "Function"."
1134 assert_class_string(window[this.name], "Function", "class string of " + this.name); 691 assert_class_string(self[this.name], "Function", "class string of " + th is.name);
692
693 // "The [[Prototype]] internal property of an interface object for a
694 // non-callback interface is determined as follows:"
695 var prototype = Object.getPrototypeOf(self[this.name]);
696 if (this.base) {
697 // "* If the interface inherits from some other interface, the
698 // value of [[Prototype]] is the interface object for that other
699 // interface."
700 var has_interface_object =
701 !this.array
702 .members[this.base]
703 .has_extended_attribute("NoInterfaceObject");
704 if (has_interface_object) {
705 assert_own_property(self, this.base,
706 'should inherit from ' + this.base +
707 ', but self has no such property');
708 assert_equals(prototype, self[this.base],
709 'prototype of ' + this.name + ' is not ' +
710 this.base);
711 }
712 } else {
713 // "If the interface doesn't inherit from any other interface, the
714 // value of [[Prototype]] is %FunctionPrototype% ([ECMA-262],
715 // section 6.1.7.4)."
716 assert_equals(prototype, Function.prototype,
717 "prototype of self's property " + format_value(this.na me) + " is not Function.prototype");
718 }
1135 719
1136 if (!this.has_extended_attribute("Constructor")) { 720 if (!this.has_extended_attribute("Constructor")) {
1137 // "The internal [[Call]] method of the interface object behaves as 721 // "The internal [[Call]] method of the interface object behaves as
1138 // follows . . . 722 // follows . . .
1139 // 723 //
1140 // "If I was not declared with a [Constructor] extended attribute, 724 // "If I was not declared with a [Constructor] extended attribute,
1141 // then throw a TypeError." 725 // then throw a TypeError."
1142 assert_throws(new TypeError(), function() { 726 assert_throws(new TypeError(), function() {
1143 window[this.name](); 727 self[this.name]();
1144 }.bind(this), "interface object didn't throw TypeError when called a s a function"); 728 }.bind(this), "interface object didn't throw TypeError when called a s a function");
1145 assert_throws(new TypeError(), function() { 729 assert_throws(new TypeError(), function() {
1146 new window[this.name](); 730 new self[this.name]();
1147 }.bind(this), "interface object didn't throw TypeError when called a s a constructor"); 731 }.bind(this), "interface object didn't throw TypeError when called a s a constructor");
1148 } 732 }
1149 }.bind(this), this.name + " interface: existence and properties of interface object"); 733 }.bind(this), this.name + " interface: existence and properties of interface object");
1150 734
1151 if (!this.is_callback()) { 735 if (!this.is_callback()) {
1152 test(function() { 736 test(function() {
1153 // This function tests WebIDL as of 2013-08-25. 737 // This function tests WebIDL as of 2014-10-25.
1154 // http://dev.w3.org/2006/webapi/WebIDL/#es-interface-call 738 // https://heycam.github.io/webidl/#es-interface-call
1155 739
1156 assert_own_property(window, this.name, 740 assert_own_property(self, this.name,
1157 "window does not have own property " + format_va lue(this.name)); 741 "self does not have own property " + format_valu e(this.name));
1158 742
1159 // "Interface objects for non-callback interfaces MUST have a 743 // "Interface objects for non-callback interfaces MUST have a
1160 // property named “length” with attributes { [[Writable]]: false, 744 // property named “length” with attributes { [[Writable]]: false,
1161 // [[Enumerable]]: false, [[Configurable]]: false } whose value is 745 // [[Enumerable]]: false, [[Configurable]]: true } whose value is
1162 // a Number." 746 // a Number."
1163 assert_own_property(window[this.name], "length"); 747 assert_own_property(self[this.name], "length");
1164 var desc = Object.getOwnPropertyDescriptor(window[this.name], "lengt h"); 748 var desc = Object.getOwnPropertyDescriptor(self[this.name], "length" );
1165 assert_false("get" in desc, this.name + ".length has getter"); 749 assert_false("get" in desc, this.name + ".length has getter");
1166 assert_false("set" in desc, this.name + ".length has setter"); 750 assert_false("set" in desc, this.name + ".length has setter");
1167 assert_false(desc.writable, this.name + ".length is writable"); 751 assert_false(desc.writable, this.name + ".length is writable");
1168 assert_false(desc.enumerable, this.name + ".length is enumerable"); 752 assert_false(desc.enumerable, this.name + ".length is enumerable");
1169 assert_false(desc.configurable, this.name + ".length is configurable "); 753 assert_true(desc.configurable, this.name + ".length is not configura ble");
1170 754
1171 var constructors = this.extAttrs 755 var constructors = this.extAttrs
1172 .filter(function(attr) { return attr.name == "Constructor"; }); 756 .filter(function(attr) { return attr.name == "Constructor"; });
1173 var expected_length; 757 var expected_length;
1174 if (!constructors.length) { 758 if (!constructors.length) {
1175 // "If the [Constructor] extended attribute, does not appear on 759 // "If the [Constructor] extended attribute, does not appear on
1176 // the interface definition, then the value is 0." 760 // the interface definition, then the value is 0."
1177 expected_length = 0; 761 expected_length = 0;
1178 } else { 762 } else {
1179 // "Otherwise, the value is determined as follows: . . . 763 // "Otherwise, the value is determined as follows: . . .
1180 // "Return the length of the shortest argument list of the 764 // "Return the length of the shortest argument list of the
1181 // entries in S." 765 // entries in S."
1182 expected_length = constructors.map(function(attr) { 766 expected_length = constructors.map(function(attr) {
1183 return attr.arguments ? attr.arguments.filter(function(arg) { 767 return attr.arguments ? attr.arguments.filter(function(arg) {
1184 return !arg.optional; 768 return !arg.optional;
1185 }).length : 0; 769 }).length : 0;
1186 }) 770 })
1187 .reduce(function(m, n) { return Math.min(m, n); }); 771 .reduce(function(m, n) { return Math.min(m, n); });
1188 } 772 }
1189 assert_equals(window[this.name].length, expected_length, "wrong valu e for " + this.name + ".length"); 773 assert_equals(self[this.name].length, expected_length, "wrong value for " + this.name + ".length");
1190 }.bind(this), this.name + " interface object length"); 774 }.bind(this), this.name + " interface object length");
1191 } 775 }
1192 776
1193 // TODO: Test named constructors if I find any interfaces that have them. 777 // TODO: Test named constructors if I find any interfaces that have them.
1194 778
1195 test(function() 779 test(function()
1196 { 780 {
1197 assert_own_property(window, this.name, 781 // This function tests WebIDL as of 2015-01-21.
1198 "window does not have own property " + format_value( this.name)); 782 // https://heycam.github.io/webidl/#interface-object
1199 783
1200 if (this.has_extended_attribute("Callback")) { 784 if (this.is_callback() && !this.has_constants()) {
1201 assert_false("prototype" in window[this.name], 785 return;
786 }
787
788 assert_own_property(self, this.name,
789 "self does not have own property " + format_value(th is.name));
790
791 if (this.is_callback()) {
792 assert_false("prototype" in self[this.name],
1202 this.name + ' should not have a "prototype" property'); 793 this.name + ' should not have a "prototype" property');
1203 return; 794 return;
1204 } 795 }
1205 796
1206 // "The interface object must also have a property named “prototype” 797 // "An interface object for a non-callback interface must have a
1207 // with attributes { [[Writable]]: false, [[Enumerable]]: false, 798 // property named “prototype” with attributes { [[Writable]]: false,
1208 // [[Configurable]]: false } whose value is an object called the 799 // [[Enumerable]]: false, [[Configurable]]: false } whose value is an
1209 // interface prototype object. This object has properties that 800 // object called the interface prototype object. This object has
1210 // correspond to the attributes and operations defined on the 801 // properties that correspond to the regular attributes and regular
1211 // interface, and is described in more detail in section 4.5.3 below." 802 // operations defined on the interface, and is described in more detail
1212 assert_own_property(window[this.name], "prototype", 803 // in section 4.5.4 below."
804 assert_own_property(self[this.name], "prototype",
1213 'interface "' + this.name + '" does not have own pro perty "prototype"'); 805 'interface "' + this.name + '" does not have own pro perty "prototype"');
1214 var desc = Object.getOwnPropertyDescriptor(window[this.name], "prototype "); 806 var desc = Object.getOwnPropertyDescriptor(self[this.name], "prototype") ;
1215 assert_false("get" in desc, this.name + ".prototype has getter"); 807 assert_false("get" in desc, this.name + ".prototype has getter");
1216 assert_false("set" in desc, this.name + ".prototype has setter"); 808 assert_false("set" in desc, this.name + ".prototype has setter");
1217 assert_false(desc.writable, this.name + ".prototype is writable"); 809 assert_false(desc.writable, this.name + ".prototype is writable");
1218 assert_false(desc.enumerable, this.name + ".prototype is enumerable"); 810 assert_false(desc.enumerable, this.name + ".prototype is enumerable");
1219 assert_false(desc.configurable, this.name + ".prototype is configurable" ); 811 assert_false(desc.configurable, this.name + ".prototype is configurable" );
1220 812
1221 // Next, test that the [[Prototype]] of the interface prototype object 813 // Next, test that the [[Prototype]] of the interface prototype object
1222 // is correct. (This is made somewhat difficult by the existence of 814 // is correct. (This is made somewhat difficult by the existence of
1223 // [NoInterfaceObject].) 815 // [NoInterfaceObject].)
1224 // TODO: Aryeh thinks there's at least other place in this file where 816 // TODO: Aryeh thinks there's at least other place in this file where
1225 // we try to figure out if an interface prototype object is 817 // we try to figure out if an interface prototype object is
1226 // correct. Consolidate that code. 818 // correct. Consolidate that code.
1227 819
1228 // "The interface prototype object for a given interface A must have an 820 // "The interface prototype object for a given interface A must have an
1229 // internal [[Prototype]] property whose value is as follows: 821 // internal [[Prototype]] property whose value is returned from the
1230 // "If A is not declared to inherit from another interface, then the 822 // following steps:
1231 // value of the internal [[Prototype]] property of A is the Array 823 // "If A is declared with the [Global] or [PrimaryGlobal] extended
1232 // prototype object ([ECMA-262], section 15.4.4) if the interface was 824 // attribute, and A supports named properties, then return the named
1233 // declared with ArrayClass, or the Object prototype object otherwise 825 // properties object for A, as defined in section 4.5.5 below.
826 // "Otherwise, if A is declared to inherit from another interface, then
827 // return the interface prototype object for the inherited interface.
828 // "Otherwise, if A is declared with the [ArrayClass] extended
829 // attribute, then return %ArrayPrototype% ([ECMA-262], section
830 // 6.1.7.4).
831 // "Otherwise, return %ObjectPrototype% ([ECMA-262], section 6.1.7.4).
1234 // ([ECMA-262], section 15.2.4). 832 // ([ECMA-262], section 15.2.4).
1235 // "Otherwise, A does inherit from another interface. The value of the 833 if (this.name === "Window") {
1236 // internal [[Prototype]] property of A is the interface prototype 834 assert_class_string(Object.getPrototypeOf(self[this.name].prototype) ,
1237 // object for the inherited interface." 835 'WindowProperties',
1238 var inherit_interface, inherit_interface_has_interface_object; 836 'Class name for prototype of Window' +
1239 if (this.base) { 837 '.prototype is not "WindowProperties"');
1240 inherit_interface = this.base;
1241 inherit_interface_has_interface_object =
1242 !this.array
1243 .members[inherit_interface]
1244 .has_extended_attribute("NoInterfaceObject");
1245 } else if (this.has_extended_attribute('ArrayClass')) {
1246 inherit_interface = 'Array';
1247 inherit_interface_has_interface_object = true;
1248 } else { 838 } else {
1249 inherit_interface = 'Object'; 839 var inherit_interface, inherit_interface_has_interface_object;
1250 inherit_interface_has_interface_object = true; 840 if (this.base) {
1251 } 841 inherit_interface = this.base;
1252 if (inherit_interface_has_interface_object) { 842 inherit_interface_has_interface_object =
1253 assert_own_property(window, inherit_interface, 843 !this.array
1254 'should inherit from ' + inherit_interface + ', but window has no such property'); 844 .members[inherit_interface]
1255 assert_own_property(window[inherit_interface], 'prototype', 845 .has_extended_attribute("NoInterfaceObject");
1256 'should inherit from ' + inherit_interface + ', but that object has no "prototype" property'); 846 } else if (this.has_extended_attribute('ArrayClass')) {
1257 assert_equals(Object.getPrototypeOf(window[this.name].prototype), 847 inherit_interface = 'Array';
1258 window[inherit_interface].prototype, 848 inherit_interface_has_interface_object = true;
1259 'prototype of ' + this.name + '.prototype is not ' + i nherit_interface + '.prototype'); 849 } else {
1260 } else { 850 inherit_interface = 'Object';
1261 // We can't test that we get the correct object, because this is the 851 inherit_interface_has_interface_object = true;
1262 // only way to get our hands on it. We only test that its class 852 }
1263 // string, at least, is correct. 853 if (inherit_interface_has_interface_object) {
1264 assert_class_string(Object.getPrototypeOf(window[this.name].prototyp e), 854 assert_own_property(self, inherit_interface,
1265 inherit_interface + 'Prototype', 855 'should inherit from ' + inherit_interface + ', but self has no such property');
1266 'Class name for prototype of ' + this.name + 856 assert_own_property(self[inherit_interface], 'prototype',
1267 '.prototype is not "' + inherit_interface + 'Pro totype"'); 857 'should inherit from ' + inherit_interface + ', but that object has no "prototype" property');
858 assert_equals(Object.getPrototypeOf(self[this.name].prototype),
859 self[inherit_interface].prototype,
860 'prototype of ' + this.name + '.prototype is not ' + inherit_interface + '.prototype');
861 } else {
862 // We can't test that we get the correct object, because this is the
863 // only way to get our hands on it. We only test that its class
864 // string, at least, is correct.
865 assert_class_string(Object.getPrototypeOf(self[this.name].protot ype),
866 inherit_interface + 'Prototype',
867 'Class name for prototype of ' + this.name +
868 '.prototype is not "' + inherit_interface + 'Prototype"');
869 }
1268 } 870 }
1269 871
1270 // "The class string of an interface prototype object is the 872 // "The class string of an interface prototype object is the
1271 // concatenation of the interface’s identifier and the string 873 // concatenation of the interface’s identifier and the string
1272 // “Prototype”." 874 // “Prototype”."
1273 assert_class_string(window[this.name].prototype, this.name + "Prototype" , 875 assert_class_string(self[this.name].prototype, this.name + "Prototype",
1274 "class string of " + this.name + ".prototype"); 876 "class string of " + this.name + ".prototype");
1275 // String() should end up calling {}.toString if nothing defines a 877 // String() should end up calling {}.toString if nothing defines a
1276 // stringifier. 878 // stringifier.
1277 if (!this.has_stringifier()) { 879 if (!this.has_stringifier()) {
1278 assert_equals(String(window[this.name].prototype), "[object " + this .name + "Prototype]", 880 assert_equals(String(self[this.name].prototype), "[object " + this.n ame + "Prototype]",
1279 "String(" + this.name + ".prototype)"); 881 "String(" + this.name + ".prototype)");
1280 } 882 }
1281 }.bind(this), this.name + " interface: existence and properties of interface prototype object"); 883 }.bind(this), this.name + " interface: existence and properties of interface prototype object");
1282 884
1283 test(function() 885 test(function()
1284 { 886 {
1285 assert_own_property(window, this.name, 887 if (this.is_callback() && !this.has_constants()) {
1286 "window does not have own property " + format_value( this.name)); 888 return;
889 }
1287 890
1288 if (this.has_extended_attribute("Callback")) { 891 assert_own_property(self, this.name,
1289 assert_false("prototype" in window[this.name], 892 "self does not have own property " + format_value(th is.name));
893
894 if (this.is_callback()) {
895 assert_false("prototype" in self[this.name],
1290 this.name + ' should not have a "prototype" property'); 896 this.name + ' should not have a "prototype" property');
1291 return; 897 return;
1292 } 898 }
1293 899
1294 assert_own_property(window[this.name], "prototype", 900 assert_own_property(self[this.name], "prototype",
1295 'interface "' + this.name + '" does not have own pro perty "prototype"'); 901 'interface "' + this.name + '" does not have own pro perty "prototype"');
1296 902
1297 // "If the [NoInterfaceObject] extended attribute was not specified on 903 // "If the [NoInterfaceObject] extended attribute was not specified on
1298 // the interface, then the interface prototype object must also have a 904 // the interface, then the interface prototype object must also have a
1299 // property named “constructor” with attributes { [[Writable]]: true, 905 // property named “constructor” with attributes { [[Writable]]: true,
1300 // [[Enumerable]]: false, [[Configurable]]: true } whose value is a 906 // [[Enumerable]]: false, [[Configurable]]: true } whose value is a
1301 // reference to the interface object for the interface." 907 // reference to the interface object for the interface."
1302 assert_own_property(window[this.name].prototype, "constructor", 908 assert_own_property(self[this.name].prototype, "constructor",
1303 this.name + '.prototype does not have own property " constructor"'); 909 this.name + '.prototype does not have own property " constructor"');
1304 var desc = Object.getOwnPropertyDescriptor(window[this.name].prototype, "constructor"); 910 var desc = Object.getOwnPropertyDescriptor(self[this.name].prototype, "c onstructor");
1305 assert_false("get" in desc, this.name + ".prototype.constructor has gett er"); 911 assert_false("get" in desc, this.name + ".prototype.constructor has gett er");
1306 assert_false("set" in desc, this.name + ".prototype.constructor has sett er"); 912 assert_false("set" in desc, this.name + ".prototype.constructor has sett er");
1307 assert_true(desc.writable, this.name + ".prototype.constructor is not wr itable"); 913 assert_true(desc.writable, this.name + ".prototype.constructor is not wr itable");
1308 assert_false(desc.enumerable, this.name + ".prototype.constructor is enu merable"); 914 assert_false(desc.enumerable, this.name + ".prototype.constructor is enu merable");
1309 assert_true(desc.configurable, this.name + ".prototype.constructor in no t configurable"); 915 assert_true(desc.configurable, this.name + ".prototype.constructor in no t configurable");
1310 assert_equals(window[this.name].prototype.constructor, window[this.name] , 916 assert_equals(self[this.name].prototype.constructor, self[this.name],
1311 this.name + '.prototype.constructor is not the same object as ' + this.name); 917 this.name + '.prototype.constructor is not the same object as ' + this.name);
1312 }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property'); 918 }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property');
1313 }; 919 };
1314 920
1315 //@} 921 //@}
922 IdlInterface.prototype.test_member_const = function(member)
923 //@{
924 {
925 test(function()
926 {
927 if (this.is_callback() && !this.has_constants()) {
928 return;
929 }
930
931 assert_own_property(self, this.name,
932 "self does not have own property " + format_value(th is.name));
933
934 // "For each constant defined on an interface A, there must be
935 // a corresponding property on the interface object, if it
936 // exists."
937 assert_own_property(self[this.name], member.name);
938 // "The value of the property is that which is obtained by
939 // converting the constant’s IDL value to an ECMAScript
940 // value."
941 assert_equals(self[this.name][member.name], constValue(member.value),
942 "property has wrong value");
943 // "The property has attributes { [[Writable]]: false,
944 // [[Enumerable]]: true, [[Configurable]]: false }."
945 var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name) ;
946 assert_false("get" in desc, "property has getter");
947 assert_false("set" in desc, "property has setter");
948 assert_false(desc.writable, "property is writable");
949 assert_true(desc.enumerable, "property is not enumerable");
950 assert_false(desc.configurable, "property is configurable");
951 }.bind(this), this.name + " interface: constant " + member.name + " on inter face object");
952 // "In addition, a property with the same characteristics must
953 // exist on the interface prototype object."
954 test(function()
955 {
956 if (this.is_callback() && !this.has_constants()) {
957 return;
958 }
959
960 assert_own_property(self, this.name,
961 "self does not have own property " + format_value(th is.name));
962
963 if (this.is_callback()) {
964 assert_false("prototype" in self[this.name],
965 this.name + ' should not have a "prototype" property');
966 return;
967 }
968
969 assert_own_property(self[this.name], "prototype",
970 'interface "' + this.name + '" does not have own pro perty "prototype"');
971
972 assert_own_property(self[this.name].prototype, member.name);
973 assert_equals(self[this.name].prototype[member.name], constValue(member. value),
974 "property has wrong value");
975 var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name) ;
976 assert_false("get" in desc, "property has getter");
977 assert_false("set" in desc, "property has setter");
978 assert_false(desc.writable, "property is writable");
979 assert_true(desc.enumerable, "property is not enumerable");
980 assert_false(desc.configurable, "property is configurable");
981 }.bind(this), this.name + " interface: constant " + member.name + " on inter face prototype object");
982 };
983
984
985 //@}
986 IdlInterface.prototype.test_member_attribute = function(member)
987 //@{
988 {
989 test(function()
990 {
991 if (this.is_callback() && !this.has_constants()) {
992 return;
993 }
994
995 assert_own_property(self, this.name,
996 "self does not have own property " + format_value(th is.name));
997 assert_own_property(self[this.name], "prototype",
998 'interface "' + this.name + '" does not have own pro perty "prototype"');
999
1000 if (member["static"]) {
1001 assert_own_property(self[this.name], member.name,
1002 "The interface object must have a property " +
1003 format_value(member.name));
1004 } else if (this.is_global()) {
1005 assert_own_property(self, member.name,
1006 "The global object must have a property " +
1007 format_value(member.name));
1008 assert_false(member.name in self[this.name].prototype,
1009 "The prototype object must not have a property " +
1010 format_value(member.name));
1011
1012 // Try/catch around the get here, since it can legitimately throw.
1013 // If it does, we obviously can't check for equality with direct
1014 // invocation of the getter.
1015 var gotValue;
1016 var propVal;
1017 try {
1018 propVal = self[member.name];
1019 gotValue = true;
1020 } catch (e) {
1021 gotValue = false;
1022 }
1023 if (gotValue) {
1024 var getter = Object.getOwnPropertyDescriptor(self, member.name). get;
1025 assert_equals(typeof(getter), "function",
1026 format_value(member.name) + " must have a getter") ;
1027 assert_equals(propVal, getter.call(undefined),
1028 "Gets on a global should not require an explicit t his");
1029 }
1030 this.do_interface_attribute_asserts(self, member);
1031 } else {
1032 assert_true(member.name in self[this.name].prototype,
1033 "The prototype object must have a property " +
1034 format_value(member.name));
1035
1036 if (!member.has_extended_attribute("LenientThis")) {
1037 assert_throws(new TypeError(), function() {
1038 self[this.name].prototype[member.name];
1039 }.bind(this), "getting property on prototype object must throw T ypeError");
1040 } else {
1041 assert_equals(self[this.name].prototype[member.name], undefined,
1042 "getting property on prototype object must return undefined");
1043 }
1044 this.do_interface_attribute_asserts(self[this.name].prototype, membe r);
1045 }
1046 }.bind(this), this.name + " interface: attribute " + member.name);
1047 };
1048
1049 //@}
1050 IdlInterface.prototype.test_member_operation = function(member)
1051 //@{
1052 {
1053 test(function()
1054 {
1055 if (this.is_callback() && !this.has_constants()) {
1056 return;
1057 }
1058
1059 assert_own_property(self, this.name,
1060 "self does not have own property " + format_value(th is.name));
1061
1062 if (this.is_callback()) {
1063 assert_false("prototype" in self[this.name],
1064 this.name + ' should not have a "prototype" property');
1065 return;
1066 }
1067
1068 assert_own_property(self[this.name], "prototype",
1069 'interface "' + this.name + '" does not have own pro perty "prototype"');
1070
1071 // "For each unique identifier of an operation defined on the
1072 // interface, there must be a corresponding property on the
1073 // interface prototype object (if it is a regular operation) or
1074 // the interface object (if it is a static operation), unless
1075 // the effective overload set for that identifier and operation
1076 // and with an argument count of 0 (for the ECMAScript language
1077 // binding) has no entries."
1078 //
1079 var memberHolderObject;
1080 if (member["static"]) {
1081 assert_own_property(self[this.name], member.name,
1082 "interface object missing static operation");
1083 memberHolderObject = self[this.name];
1084 } else if (this.is_global()) {
1085 assert_own_property(self, member.name,
1086 "global object missing non-static operation");
1087 memberHolderObject = self;
1088 } else {
1089 assert_own_property(self[this.name].prototype, member.name,
1090 "interface prototype object missing non-static operation");
1091 memberHolderObject = self[this.name].prototype;
1092 }
1093
1094 this.do_member_operation_asserts(memberHolderObject, member);
1095 }.bind(this), this.name + " interface: operation " + member.name +
1096 "(" + member.arguments.map(function(m) { return m.idlType.idlType; }) +
1097 ")");
1098 };
1099
1100 //@}
1101 IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject , member)
1102 //@{
1103 {
1104 var operationUnforgeable = member.isUnforgeable;
1105 var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);
1106 // "The property has attributes { [[Writable]]: B,
1107 // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
1108 // operation is unforgeable on the interface, and true otherwise".
1109 assert_false("get" in desc, "property has getter");
1110 assert_false("set" in desc, "property has setter");
1111 assert_equals(desc.writable, !operationUnforgeable,
1112 "property should be writable if and only if not unforgeable");
1113 assert_true(desc.enumerable, "property is not enumerable");
1114 assert_equals(desc.configurable, !operationUnforgeable,
1115 "property should be configurable if and only if not unforgeabl e");
1116 // "The value of the property is a Function object whose
1117 // behavior is as follows . . ."
1118 assert_equals(typeof memberHolderObject[member.name], "function",
1119 "property must be a function");
1120 // "The value of the Function object’s “length” property is
1121 // a Number determined as follows:
1122 // ". . .
1123 // "Return the length of the shortest argument list of the
1124 // entries in S."
1125 //
1126 // TODO: Doesn't handle overloading or variadic arguments.
1127 assert_equals(memberHolderObject[member.name].length,
1128 member.arguments.filter(function(arg) {
1129 return !arg.optional;
1130 }).length,
1131 "property has wrong .length");
1132
1133 // Make some suitable arguments
1134 var args = member.arguments.map(function(arg) {
1135 return create_suitable_object(arg.idlType);
1136 });
1137
1138 // "Let O be a value determined as follows:
1139 // ". . .
1140 // "Otherwise, throw a TypeError."
1141 // This should be hit if the operation is not static, there is
1142 // no [ImplicitThis] attribute, and the this value is null.
1143 //
1144 // TODO: We currently ignore the [ImplicitThis] case. Except we manually
1145 // check for globals, since otherwise we'll invoke window.close(). And we
1146 // have to skip this test for anything that on the proto chain of "self",
1147 // since that does in fact have implicit-this behavior.
1148 if (!member["static"]) {
1149 if (!this.is_global() &&
1150 memberHolderObject[member.name] != self[member.name])
1151 {
1152 assert_throws(new TypeError(), function() {
1153 memberHolderObject[member.name].apply(null, args);
1154 }, "calling operation with this = null didn't throw TypeError");
1155 }
1156
1157 // ". . . If O is not null and is also not a platform object
1158 // that implements interface I, throw a TypeError."
1159 //
1160 // TODO: Test a platform object that implements some other
1161 // interface. (Have to be sure to get inheritance right.)
1162 assert_throws(new TypeError(), function() {
1163 memberHolderObject[member.name].apply({}, args);
1164 }, "calling operation with this = {} didn't throw TypeError");
1165 }
1166 }
1167
1168 //@}
1169 IdlInterface.prototype.test_member_stringifier = function(member)
1170 //@{
1171 {
1172 test(function()
1173 {
1174 if (this.is_callback() && !this.has_constants()) {
1175 return;
1176 }
1177
1178 assert_own_property(self, this.name,
1179 "self does not have own property " + format_value(th is.name));
1180
1181 if (this.is_callback()) {
1182 assert_false("prototype" in self[this.name],
1183 this.name + ' should not have a "prototype" property');
1184 return;
1185 }
1186
1187 assert_own_property(self[this.name], "prototype",
1188 'interface "' + this.name + '" does not have own pro perty "prototype"');
1189
1190 // ". . . the property exists on the interface prototype object."
1191 var interfacePrototypeObject = self[this.name].prototype;
1192 assert_own_property(self[this.name].prototype, "toString",
1193 "interface prototype object missing non-static operation");
1194
1195 var stringifierUnforgeable = member.isUnforgeable;
1196 var desc = Object.getOwnPropertyDescriptor(interfacePrototypeObject, "to String");
1197 // "The property has attributes { [[Writable]]: B,
1198 // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
1199 // stringifier is unforgeable on the interface, and true otherwise."
1200 assert_false("get" in desc, "property has getter");
1201 assert_false("set" in desc, "property has setter");
1202 assert_equals(desc.writable, !stringifierUnforgeable,
1203 "property should be writable if and only if not unforgeabl e");
1204 assert_true(desc.enumerable, "property is not enumerable");
1205 assert_equals(desc.configurable, !stringifierUnforgeable,
1206 "property should be configurable if and only if not unforg eable");
1207 // "The value of the property is a Function object, which behaves as
1208 // follows . . ."
1209 assert_equals(typeof interfacePrototypeObject.toString, "function",
1210 "property must be a function");
1211 // "The value of the Function object’s “length” property is the Number
1212 // value 0."
1213 assert_equals(interfacePrototypeObject.toString.length, 0,
1214 "property has wrong .length");
1215
1216 // "Let O be the result of calling ToObject on the this value."
1217 assert_throws(new TypeError(), function() {
1218 self[this.name].prototype.toString.apply(null, []);
1219 }, "calling stringifier with this = null didn't throw TypeError");
1220
1221 // "If O is not an object that implements the interface on which the
1222 // stringifier was declared, then throw a TypeError."
1223 //
1224 // TODO: Test a platform object that implements some other
1225 // interface. (Have to be sure to get inheritance right.)
1226 assert_throws(new TypeError(), function() {
1227 self[this.name].prototype.toString.apply({}, []);
1228 }, "calling stringifier with this = {} didn't throw TypeError");
1229 }.bind(this), this.name + " interface: stringifier");
1230 };
1231
1232 //@}
1316 IdlInterface.prototype.test_members = function() 1233 IdlInterface.prototype.test_members = function()
1317 //@{ 1234 //@{
1318 { 1235 {
1319 for (var i = 0; i < this.members.length; i++) 1236 for (var i = 0; i < this.members.length; i++)
1320 { 1237 {
1321 var member = this.members[i]; 1238 var member = this.members[i];
1322 if (member.untested) 1239 if (member.untested) {
1323 {
1324 continue; 1240 continue;
1325 } 1241 }
1326 if (member.type == "const") 1242
1327 { 1243 switch (member.type) {
1328 test(function() 1244 case "const":
1245 this.test_member_const(member);
1246 break;
1247
1248 case "attribute":
1249 // For unforgeable attributes, we do the checks in
1250 // test_interface_of instead.
1251 if (!member.isUnforgeable)
1329 { 1252 {
1330 assert_own_property(window, this.name, 1253 this.test_member_attribute(member);
1331 "window does not have own property " + forma t_value(this.name)); 1254 }
1332 1255 break;
1333 // "For each constant defined on an interface A, there must be 1256
1334 // a corresponding property on the interface object, if it 1257 case "operation":
1335 // exists."
1336 assert_own_property(window[this.name], member.name);
1337 // "The value of the property is that which is obtained by
1338 // converting the constant’s IDL value to an ECMAScript
1339 // value."
1340 assert_equals(window[this.name][member.name], constValue(member. value),
1341 "property has wrong value");
1342 // "The property has attributes { [[Writable]]: false,
1343 // [[Enumerable]]: true, [[Configurable]]: false }."
1344 var desc = Object.getOwnPropertyDescriptor(window[this.name], me mber.name);
1345 assert_false("get" in desc, "property has getter");
1346 assert_false("set" in desc, "property has setter");
1347 assert_false(desc.writable, "property is writable");
1348 assert_true(desc.enumerable, "property is not enumerable");
1349 assert_false(desc.configurable, "property is configurable");
1350 }.bind(this), this.name + " interface: constant " + member.name + " on interface object");
1351 // "In addition, a property with the same characteristics must
1352 // exist on the interface prototype object."
1353 test(function()
1354 {
1355 assert_own_property(window, this.name,
1356 "window does not have own property " + forma t_value(this.name));
1357
1358 if (this.has_extended_attribute("Callback")) {
1359 assert_false("prototype" in window[this.name],
1360 this.name + ' should not have a "prototype" pro perty');
1361 return;
1362 }
1363
1364 assert_own_property(window[this.name], "prototype",
1365 'interface "' + this.name + '" does not have own property "prototype"');
1366
1367 assert_own_property(window[this.name].prototype, member.name);
1368 assert_equals(window[this.name].prototype[member.name], constVal ue(member.value),
1369 "property has wrong value");
1370 var desc = Object.getOwnPropertyDescriptor(window[this.name], me mber.name);
1371 assert_false("get" in desc, "property has getter");
1372 assert_false("set" in desc, "property has setter");
1373 assert_false(desc.writable, "property is writable");
1374 assert_true(desc.enumerable, "property is not enumerable");
1375 assert_false(desc.configurable, "property is configurable");
1376 }.bind(this), this.name + " interface: constant " + member.name + " on interface prototype object");
1377 }
1378 else if (member.type == "attribute")
1379 {
1380 if (member.has_extended_attribute("Unforgeable"))
1381 {
1382 // We do the checks in test_interface_of instead
1383 continue;
1384 }
1385 test(function()
1386 {
1387 assert_own_property(window, this.name,
1388 "window does not have own property " + forma t_value(this.name));
1389 assert_own_property(window[this.name], "prototype",
1390 'interface "' + this.name + '" does not have own property "prototype"');
1391
1392 if (member["static"]) {
1393 assert_own_property(window[this.name], member.name,
1394 "The interface object must have a property " +
1395 format_value(member.name));
1396 }
1397 else
1398 {
1399 assert_true(member.name in window[this.name].prototype,
1400 "The prototype object must have a property " +
1401 format_value(member.name));
1402
1403 // TODO: Needs to test for LenientThis.
1404 assert_throws(new TypeError(), function() {
1405 window[this.name].prototype[member.name];
1406 }.bind(this), "getting property on prototype object must thr ow TypeError");
1407 do_interface_attribute_asserts(window[this.name].prototype, member);
1408 }
1409 }.bind(this), this.name + " interface: attribute " + member.name);
1410 }
1411 else if (member.type == "operation")
1412 {
1413 // TODO: Need to correctly handle multiple operations with the same 1258 // TODO: Need to correctly handle multiple operations with the same
1414 // identifier. 1259 // identifier.
1415 if (!member.name) 1260 // For unforgeable operations, we do the checks in
1416 { 1261 // test_interface_of instead.
1417 // Unnamed getter or such 1262 if (member.name) {
1418 continue; 1263 if (!member.isUnforgeable)
1419 } 1264 {
1420 test(function() 1265 this.test_member_operation(member);
1421 {
1422 assert_own_property(window, this.name,
1423 "window does not have own property " + forma t_value(this.name));
1424
1425 if (this.has_extended_attribute("Callback")) {
1426 assert_false("prototype" in window[this.name],
1427 this.name + ' should not have a "prototype" pro perty');
1428 return;
1429 } 1266 }
1430 1267 } else if (member.stringifier) {
1431 assert_own_property(window[this.name], "prototype", 1268 this.test_member_stringifier(member);
1432 'interface "' + this.name + '" does not have own property "prototype"'); 1269 }
1433 1270 break;
1434 // "For each unique identifier of an operation defined on the 1271
1435 // interface, there must be a corresponding property on the 1272 default:
1436 // interface prototype object (if it is a regular operation) or 1273 // TODO: check more member types.
1437 // the interface object (if it is a static operation), unless 1274 break;
1438 // the effective overload set for that identifier and operation 1275 }
1439 // and with an argument count of 0 (for the ECMAScript language
1440 // binding) has no entries."
1441 //
1442 var prototypeOrInterfaceObject;
1443 if (member["static"]) {
1444 assert_own_property(window[this.name], member.name,
1445 "interface prototype object missing static operation ");
1446 prototypeOrInterfaceObject = window[this.name];
1447 }
1448 else
1449 {
1450 assert_own_property(window[this.name].prototype, member.name ,
1451 "interface prototype object missing non-static opera tion");
1452 prototypeOrInterfaceObject = window[this.name].prototype;
1453 }
1454
1455 var desc = Object.getOwnPropertyDescriptor(prototypeOrInterfaceO bject, member.name);
1456 // "The property has attributes { [[Writable]]: true,
1457 // [[Enumerable]]: true, [[Configurable]]: true }."
1458 assert_false("get" in desc, "property has getter");
1459 assert_false("set" in desc, "property has setter");
1460 assert_true(desc.writable, "property is not writable");
1461 assert_true(desc.enumerable, "property is not enumerable");
1462 assert_true(desc.configurable, "property is not configurable");
1463 // "The value of the property is a Function object whose
1464 // behavior is as follows . . ."
1465 assert_equals(typeof prototypeOrInterfaceObject[member.name], "f unction",
1466 "property must be a function");
1467 // "The value of the Function object’s “length” property is
1468 // a Number determined as follows:
1469 // ". . .
1470 // "Return the length of the shortest argument list of the
1471 // entries in S."
1472 //
1473 // TODO: Doesn't handle overloading or variadic arguments.
1474 assert_equals(prototypeOrInterfaceObject[member.name].length,
1475 member.arguments.filter(function(arg) {
1476 return !arg.optional;
1477 }).length,
1478 "property has wrong .length");
1479
1480 // Make some suitable arguments
1481 var args = member.arguments.map(function(arg) {
1482 return create_suitable_object(arg.idlType);
1483 });
1484
1485 // "Let O be a value determined as follows:
1486 // ". . .
1487 // "Otherwise, throw a TypeError."
1488 // This should be hit if the operation is not static, there is
1489 // no [ImplicitThis] attribute, and the this value is null.
1490 //
1491 // TODO: We currently ignore the [ImplicitThis] case.
1492 if (!member["static"]) {
1493 assert_throws(new TypeError(), function() {
1494 window[this.name].prototype[member.name].apply(null, arg s);
1495 }, "calling operation with this = null didn't throw TypeErro r");
1496 }
1497
1498 // ". . . If O is not null and is also not a platform object
1499 // that implements interface I, throw a TypeError."
1500 //
1501 // TODO: Test a platform object that implements some other
1502 // interface. (Have to be sure to get inheritance right.)
1503 assert_throws(new TypeError(), function() {
1504 window[this.name].prototype[member.name].apply({}, args);
1505 }, "calling operation with this = {} didn't throw TypeError");
1506 }.bind(this), this.name + " interface: operation " + member.name +
1507 "(" + member.arguments.map(function(m) { return m.idlType.idlType; } ) +
1508 ")");
1509 }
1510 // TODO: check more member types, like stringifier
1511 } 1276 }
1512 }; 1277 };
1513 1278
1514 //@} 1279 //@}
1515 IdlInterface.prototype.test_object = function(desc) 1280 IdlInterface.prototype.test_object = function(desc)
1516 //@{ 1281 //@{
1517 { 1282 {
1518 var obj, exception = null; 1283 var obj, exception = null;
1519 try 1284 try
1520 { 1285 {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1560 // interface object, or the object is from a different global environment 1325 // interface object, or the object is from a different global environment
1561 // (not instanceof Object). TODO: test in this case that its prototype at 1326 // (not instanceof Object). TODO: test in this case that its prototype at
1562 // least looks correct, even if we can't test that it's actually correct. 1327 // least looks correct, even if we can't test that it's actually correct.
1563 if (!this.has_extended_attribute("NoInterfaceObject") 1328 if (!this.has_extended_attribute("NoInterfaceObject")
1564 && (typeof obj != expected_typeof || obj instanceof Object)) 1329 && (typeof obj != expected_typeof || obj instanceof Object))
1565 { 1330 {
1566 test(function() 1331 test(function()
1567 { 1332 {
1568 assert_equals(exception, null, "Unexpected exception when evaluating object"); 1333 assert_equals(exception, null, "Unexpected exception when evaluating object");
1569 assert_equals(typeof obj, expected_typeof, "wrong typeof object"); 1334 assert_equals(typeof obj, expected_typeof, "wrong typeof object");
1570 assert_own_property(window, this.name, 1335 assert_own_property(self, this.name,
1571 "window does not have own property " + format_va lue(this.name)); 1336 "self does not have own property " + format_valu e(this.name));
1572 assert_own_property(window[this.name], "prototype", 1337 assert_own_property(self[this.name], "prototype",
1573 'interface "' + this.name + '" does not have own property "prototype"'); 1338 'interface "' + this.name + '" does not have own property "prototype"');
1574 1339
1575 // "The value of the internal [[Prototype]] property of the 1340 // "The value of the internal [[Prototype]] property of the
1576 // platform object is the interface prototype object of the primary 1341 // platform object is the interface prototype object of the primary
1577 // interface from the platform object’s associated global 1342 // interface from the platform object’s associated global
1578 // environment." 1343 // environment."
1579 assert_equals(Object.getPrototypeOf(obj), 1344 assert_equals(Object.getPrototypeOf(obj),
1580 window[this.name].prototype, 1345 self[this.name].prototype,
1581 desc + "'s prototype is not " + this.name + ".prototyp e"); 1346 desc + "'s prototype is not " + this.name + ".prototyp e");
1582 }.bind(this), this.name + " must be primary interface of " + desc); 1347 }.bind(this), this.name + " must be primary interface of " + desc);
1583 } 1348 }
1584 1349
1585 // "The class string of a platform object that implements one or more 1350 // "The class string of a platform object that implements one or more
1586 // interfaces must be the identifier of the primary interface of the 1351 // interfaces must be the identifier of the primary interface of the
1587 // platform object." 1352 // platform object."
1588 test(function() 1353 test(function()
1589 { 1354 {
1590 assert_equals(exception, null, "Unexpected exception when evaluating obj ect"); 1355 assert_equals(exception, null, "Unexpected exception when evaluating obj ect");
1591 assert_equals(typeof obj, expected_typeof, "wrong typeof object"); 1356 assert_equals(typeof obj, expected_typeof, "wrong typeof object");
1592 assert_class_string(obj, this.name, "class string of " + desc); 1357 assert_class_string(obj, this.name, "class string of " + desc);
1593 if (!this.has_stringifier()) 1358 if (!this.has_stringifier())
1594 { 1359 {
1595 assert_equals(String(obj), "[object " + this.name + "]", "String(" + desc + ")"); 1360 assert_equals(String(obj), "[object " + this.name + "]", "String(" + desc + ")");
1596 } 1361 }
1597 }.bind(this), "Stringification of " + desc); 1362 }.bind(this), "Stringification of " + desc);
1598 }; 1363 };
1599 1364
1600 //@} 1365 //@}
1601 IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expect ed_typeof) 1366 IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expect ed_typeof)
1602 //@{ 1367 //@{
1603 { 1368 {
1604 // TODO: Indexed and named properties, more checks on interface members 1369 // TODO: Indexed and named properties, more checks on interface members
1605 this.already_tested = true; 1370 this.already_tested = true;
1606 1371
1607 for (var i = 0; i < this.members.length; i++) 1372 for (var i = 0; i < this.members.length; i++)
1608 { 1373 {
1609 var member = this.members[i]; 1374 var member = this.members[i];
1610 if (member.has_extended_attribute("Unforgeable")) 1375 if (member.type == "attribute" && member.isUnforgeable)
1611 { 1376 {
1612 test(function() 1377 test(function()
1613 { 1378 {
1614 assert_equals(exception, null, "Unexpected exception when evalua ting object"); 1379 assert_equals(exception, null, "Unexpected exception when evalua ting object");
1615 assert_equals(typeof obj, expected_typeof, "wrong typeof object" ); 1380 assert_equals(typeof obj, expected_typeof, "wrong typeof object" );
1616 do_interface_attribute_asserts(obj, member); 1381 this.do_interface_attribute_asserts(obj, member);
1382 }.bind(this), this.name + " interface: " + desc + ' must have own pr operty "' + member.name + '"');
1383 }
1384 else if (member.type == "operation" &&
1385 member.name &&
1386 member.isUnforgeable)
1387 {
1388 test(function()
1389 {
1390 assert_equals(exception, null, "Unexpected exception when evalua ting object");
1391 assert_equals(typeof obj, expected_typeof, "wrong typeof object" );
1392 assert_own_property(obj, member.name,
1393 "Doesn't have the unforgeable operation prop erty");
1394 this.do_member_operation_asserts(obj, member);
1617 }.bind(this), this.name + " interface: " + desc + ' must have own pr operty "' + member.name + '"'); 1395 }.bind(this), this.name + " interface: " + desc + ' must have own pr operty "' + member.name + '"');
1618 } 1396 }
1619 else if ((member.type == "const" 1397 else if ((member.type == "const"
1620 || member.type == "attribute" 1398 || member.type == "attribute"
1621 || member.type == "operation") 1399 || member.type == "operation")
1622 && member.name) 1400 && member.name)
1623 { 1401 {
1624 test(function() 1402 test(function()
1625 { 1403 {
1626 assert_equals(exception, null, "Unexpected exception when evalua ting object"); 1404 assert_equals(exception, null, "Unexpected exception when evalua ting object");
1627 assert_equals(typeof obj, expected_typeof, "wrong typeof object" ); 1405 assert_equals(typeof obj, expected_typeof, "wrong typeof object" );
1628 if (!member["static"]) { 1406 if (!member["static"]) {
1629 assert_inherits(obj, member.name); 1407 if (!this.is_global()) {
1408 assert_inherits(obj, member.name);
1409 } else {
1410 assert_own_property(obj, member.name);
1411 }
1412
1630 if (member.type == "const") 1413 if (member.type == "const")
1631 { 1414 {
1632 assert_equals(obj[member.name], constValue(member.value) ); 1415 assert_equals(obj[member.name], constValue(member.value) );
1633 } 1416 }
1634 if (member.type == "attribute") 1417 if (member.type == "attribute")
1635 { 1418 {
1636 // Attributes are accessor properties, so they might 1419 // Attributes are accessor properties, so they might
1637 // legitimately throw an exception rather than returning 1420 // legitimately throw an exception rather than returning
1638 // anything. 1421 // anything.
1639 var property, thrown = false; 1422 var property, thrown = false;
(...skipping 20 matching lines...) Expand all
1660 // TODO: This is wrong if there are multiple operations with the same 1443 // TODO: This is wrong if there are multiple operations with the same
1661 // identifier. 1444 // identifier.
1662 // TODO: Test passing arguments of the wrong type. 1445 // TODO: Test passing arguments of the wrong type.
1663 if (member.type == "operation" && member.name && member.arguments.length ) 1446 if (member.type == "operation" && member.name && member.arguments.length )
1664 { 1447 {
1665 test(function() 1448 test(function()
1666 { 1449 {
1667 assert_equals(exception, null, "Unexpected exception when evalua ting object"); 1450 assert_equals(exception, null, "Unexpected exception when evalua ting object");
1668 assert_equals(typeof obj, expected_typeof, "wrong typeof object" ); 1451 assert_equals(typeof obj, expected_typeof, "wrong typeof object" );
1669 if (!member["static"]) { 1452 if (!member["static"]) {
1670 assert_inherits(obj, member.name); 1453 if (!this.is_global() && !member.isUnforgeable) {
1454 assert_inherits(obj, member.name);
1455 } else {
1456 assert_own_property(obj, member.name);
1457 }
1671 } 1458 }
1672 else 1459 else
1673 { 1460 {
1674 assert_false(member.name in obj); 1461 assert_false(member.name in obj);
1675 } 1462 }
1676 var args = []; 1463 var args = [];
1677 for (var i = 0; i < member.arguments.length; i++) 1464 for (var i = 0; i < member.arguments.length; i++)
1678 { 1465 {
1679 if (member.arguments[i].optional) 1466 if (member.arguments[i].optional)
1680 { 1467 {
(...skipping 21 matching lines...) Expand all
1702 return true; 1489 return true;
1703 } 1490 }
1704 if (this.base && 1491 if (this.base &&
1705 this.array.members[this.base].has_stringifier()) { 1492 this.array.members[this.base].has_stringifier()) {
1706 return true; 1493 return true;
1707 } 1494 }
1708 return false; 1495 return false;
1709 }; 1496 };
1710 1497
1711 //@} 1498 //@}
1712 function do_interface_attribute_asserts(obj, member) 1499 IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member)
1713 //@{ 1500 //@{
1714 { 1501 {
1715 // "For each attribute defined on the interface, there must exist a 1502 // This function tests WebIDL as of 2015-01-27.
1716 // corresponding property. If the attribute was declared with the 1503 // TODO: Consider [Exposed].
1717 // [Unforgeable] extended attribute, then the property exists on every 1504
1718 // object that implements the interface. Otherwise, it exists on the 1505 // This is called by test_member_attribute() with the prototype as obj if
1719 // interface’s interface prototype object." 1506 // it is not a global, and the global otherwise, and by test_interface_of()
1720 // 1507 // with the object as obj.
1721 // This is called by test_self() with the prototype as obj, and by 1508
1722 // test_interface_of() with the object as obj. 1509 // "For each exposed attribute of the interface, whether it was declared on
1510 // the interface itself or one of its consequential interfaces, there MUST
1511 // exist a corresponding property. The characteristics of this property are
1512 // as follows:"
1513
1514 // "The name of the property is the identifier of the attribute."
1723 assert_own_property(obj, member.name); 1515 assert_own_property(obj, member.name);
1724 1516
1725 // "The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]: 1517 // "The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
1726 // true, [[Configurable]]: configurable }, where: 1518 // true, [[Configurable]]: configurable }, where:
1727 // "configurable is false if the attribute was declared with the 1519 // "configurable is false if the attribute was declared with the
1728 // [Unforgeable] extended attribute and true otherwise; 1520 // [Unforgeable] extended attribute and true otherwise;
1729 // "G is the attribute getter, defined below; and 1521 // "G is the attribute getter, defined below; and
1730 // "S is the attribute setter, also defined below." 1522 // "S is the attribute setter, also defined below."
1731 var desc = Object.getOwnPropertyDescriptor(obj, member.name); 1523 var desc = Object.getOwnPropertyDescriptor(obj, member.name);
1732 assert_false("value" in desc, 'property descriptor has value but is supposed to be accessor'); 1524 assert_false("value" in desc, 'property descriptor has value but is supposed to be accessor');
1733 assert_false("writable" in desc, 'property descriptor has "writable" field b ut is supposed to be accessor'); 1525 assert_false("writable" in desc, 'property descriptor has "writable" field b ut is supposed to be accessor');
1734 assert_true(desc.enumerable, "property is not enumerable"); 1526 assert_true(desc.enumerable, "property is not enumerable");
1735 if (member.has_extended_attribute("Unforgeable")) 1527 if (member.isUnforgeable)
1736 { 1528 {
1737 assert_false(desc.configurable, "[Unforgeable] property must not be conf igurable"); 1529 assert_false(desc.configurable, "[Unforgeable] property must not be conf igurable");
1738 } 1530 }
1739 else 1531 else
1740 { 1532 {
1741 assert_true(desc.configurable, "property must be configurable"); 1533 assert_true(desc.configurable, "property must be configurable");
1742 } 1534 }
1743 1535
1536
1744 // "The attribute getter is a Function object whose behavior when invoked 1537 // "The attribute getter is a Function object whose behavior when invoked
1745 // is as follows: 1538 // is as follows:"
1746 // "... 1539 assert_equals(typeof desc.get, "function", "getter must be Function");
1540
1541 // "If the attribute is a regular attribute, then:"
1542 if (!member["static"]) {
1543 // "If O is not a platform object that implements I, then:
1544 // "If the attribute was specified with the [LenientThis] extended
1545 // attribute, then return undefined.
1546 // "Otherwise, throw a TypeError."
1547 if (!member.has_extended_attribute("LenientThis")) {
1548 assert_throws(new TypeError(), function() {
1549 desc.get.call({});
1550 }.bind(this), "calling getter on wrong object type must throw TypeEr ror");
1551 } else {
1552 assert_equals(desc.get.call({}), undefined,
1553 "calling getter on wrong object type must return undef ined");
1554 }
1555 }
1556
1747 // "The value of the Function object’s “length” property is the Number 1557 // "The value of the Function object’s “length” property is the Number
1748 // value 0." 1558 // value 0."
1749 assert_equals(typeof desc.get, "function", "getter must be Function");
1750 assert_equals(desc.get.length, 0, "getter length must be 0"); 1559 assert_equals(desc.get.length, 0, "getter length must be 0");
1751 // TODO: Account for LenientThis 1560
1752 assert_throws(new TypeError(), function()
1753 {
1754 desc.get.call({});
1755 }.bind(this), "calling getter on wrong object type must throw TypeError");
1756 1561
1757 // TODO: Test calling setter on the interface prototype (should throw 1562 // TODO: Test calling setter on the interface prototype (should throw
1758 // TypeError in most cases). 1563 // TypeError in most cases).
1759 //
1760 // "The attribute setter is undefined if the attribute is declared readonly
1761 // and has neither a [PutForwards] nor a [Replaceable] extended attribute
1762 // declared on it. Otherwise, it is a Function object whose behavior when
1763 // invoked is as follows:
1764 // "...
1765 // "The value of the Function object’s “length” property is the Number
1766 // value 1."
1767 if (member.readonly 1564 if (member.readonly
1768 && !member.has_extended_attribute("PutForwards") 1565 && !member.has_extended_attribute("PutForwards")
1769 && !member.has_extended_attribute("Replaceable")) 1566 && !member.has_extended_attribute("Replaceable"))
1770 { 1567 {
1568 // "The attribute setter is undefined if the attribute is declared
1569 // readonly and has neither a [PutForwards] nor a [Replaceable]
1570 // extended attribute declared on it."
1771 assert_equals(desc.set, undefined, "setter must be undefined for readonl y attributes"); 1571 assert_equals(desc.set, undefined, "setter must be undefined for readonl y attributes");
1772 } 1572 }
1773 else 1573 else
1774 { 1574 {
1575 // "Otherwise, it is a Function object whose behavior when
1576 // invoked is as follows:"
1775 assert_equals(typeof desc.set, "function", "setter must be function for PutForwards, Replaceable, or non-readonly attributes"); 1577 assert_equals(typeof desc.set, "function", "setter must be function for PutForwards, Replaceable, or non-readonly attributes");
1578
1579 // "If the attribute is a regular attribute, then:"
1580 if (!member["static"]) {
1581 // "If /validThis/ is false and the attribute was not specified
1582 // with the [LenientThis] extended attribute, then throw a
1583 // TypeError."
1584 // "If the attribute is declared with a [Replaceable] extended
1585 // attribute, then: ..."
1586 // "If validThis is false, then return."
1587 if (!member.has_extended_attribute("LenientThis")) {
1588 assert_throws(new TypeError(), function() {
1589 desc.set.call({});
1590 }.bind(this), "calling setter on wrong object type must throw Ty peError");
1591 } else {
1592 assert_equals(desc.set.call({}), undefined,
1593 "calling setter on wrong object type must return u ndefined");
1594 }
1595 }
1596
1597 // "The value of the Function object’s “length” property is the Number
1598 // value 1."
1776 assert_equals(desc.set.length, 1, "setter length must be 1"); 1599 assert_equals(desc.set.length, 1, "setter length must be 1");
1777 } 1600 }
1778 } 1601 }
1779 //@} 1602 //@}
1780 1603
1781 /// IdlInterfaceMember /// 1604 /// IdlInterfaceMember ///
1782 function IdlInterfaceMember(obj) 1605 function IdlInterfaceMember(obj)
1783 //@{ 1606 //@{
1784 { 1607 {
1785 /** 1608 /**
1786 * obj is an object produced by the WebIDLParser.js "ifMember" production. 1609 * obj is an object produced by the WebIDLParser.js "ifMember" production.
1787 * We just forward all properties to this object without modification, 1610 * We just forward all properties to this object without modification,
1788 * except for special extAttrs handling. 1611 * except for special extAttrs handling.
1789 */ 1612 */
1790 for (var k in obj) 1613 for (var k in obj)
1791 { 1614 {
1792 this[k] = obj[k]; 1615 this[k] = obj[k];
1793 } 1616 }
1794 if (!("extAttrs" in this)) 1617 if (!("extAttrs" in this))
1795 { 1618 {
1796 this.extAttrs = []; 1619 this.extAttrs = [];
1797 } 1620 }
1621
1622 this.isUnforgeable = this.has_extended_attribute("Unforgeable");
1798 } 1623 }
1799 1624
1800 //@} 1625 //@}
1801 IdlInterfaceMember.prototype = Object.create(IdlObject.prototype); 1626 IdlInterfaceMember.prototype = Object.create(IdlObject.prototype);
1802 1627
1803 /// Internal helper functions /// 1628 /// Internal helper functions ///
1804 function create_suitable_object(type) 1629 function create_suitable_object(type)
1805 //@{ 1630 //@{
1806 { 1631 {
1807 /** 1632 /**
(...skipping 11 matching lines...) Expand all
1819 case "boolean": 1644 case "boolean":
1820 return true; 1645 return true;
1821 1646
1822 case "byte": case "octet": case "short": case "unsigned short": 1647 case "byte": case "octet": case "short": case "unsigned short":
1823 case "long": case "unsigned long": case "long long": 1648 case "long": case "unsigned long": case "long long":
1824 case "unsigned long long": case "float": case "double": 1649 case "unsigned long long": case "float": case "double":
1825 case "unrestricted float": case "unrestricted double": 1650 case "unrestricted float": case "unrestricted double":
1826 return 7; 1651 return 7;
1827 1652
1828 case "DOMString": 1653 case "DOMString":
1654 case "ByteString":
1655 case "USVString":
1829 return "foo"; 1656 return "foo";
1830 1657
1831 case "object": 1658 case "object":
1832 return {a: "b"}; 1659 return {a: "b"};
1833 1660
1834 case "Node": 1661 case "Node":
1835 return document.createTextNode("abc"); 1662 return document.createTextNode("abc");
1836 } 1663 }
1837 return null; 1664 return null;
1838 } 1665 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1875 /** An array of values produced by the "typedef" production. */ 1702 /** An array of values produced by the "typedef" production. */
1876 this.values = obj.values; 1703 this.values = obj.values;
1877 1704
1878 } 1705 }
1879 //@} 1706 //@}
1880 1707
1881 IdlTypedef.prototype = Object.create(IdlObject.prototype); 1708 IdlTypedef.prototype = Object.create(IdlObject.prototype);
1882 1709
1883 }()); 1710 }());
1884 // vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker: 1711 // vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698