How to use iteratorDesc method in wpt

Best JavaScript code snippet using wpt

idlharness.js

Source:idlharness.js Github

copy

Full Screen

1/* For user documentation see docs/_writing-tests/idlharness.md */2/**3 * Notes for people who want to edit this file (not just use it as a library):4 *5 * Most of the interesting stuff happens in the derived classes of IdlObject,6 * especially IdlInterface. The entry point for all IdlObjects is .test(),7 * which is called by IdlArray.test(). An IdlObject is conceptually just8 * "thing we want to run tests on", and an IdlArray is an array of IdlObjects9 * with some additional data thrown in.10 *11 * The object model is based on what WebIDLParser.js produces, which is in turn12 * based on its pegjs grammar. If you want to figure out what properties an13 * object will have from WebIDLParser.js, the best way is to look at the14 * grammar:15 *16 * https://github.com/darobin/webidl.js/blob/master/lib/grammar.peg17 *18 * So for instance:19 *20 * // interface definition21 * interface22 * = extAttrs:extendedAttributeList? S? "interface" S name:identifier w herit:ifInheritance? w "{" w mem:ifMember* w "}" w ";" w23 * { return { type: "interface", name: name, inheritance: herit, members: mem, extAttrs: extAttrs }; }24 *25 * This means that an "interface" object will have a .type property equal to26 * the string "interface", a .name property equal to the identifier that the27 * parser found, an .inheritance property equal to either null or the result of28 * the "ifInheritance" production found elsewhere in the grammar, and so on.29 * After each grammatical production is a JavaScript function in curly braces30 * that gets called with suitable arguments and returns some JavaScript value.31 *32 * (Note that the version of WebIDLParser.js we use might sometimes be33 * out-of-date or forked.)34 *35 * The members and methods of the classes defined by this file are all at least36 * briefly documented, hopefully.37 */38(function(){39"use strict";40// Support subsetTestByKey from /common/subset-tests-by-key.js, but make it optional41if (!('subsetTestByKey' in self)) {42 self.subsetTestByKey = function(key, callback, ...args) {43 return callback(...args);44 }45 self.shouldRunSubTest = () => true;46}47/// Helpers ///48function constValue (cnt)49{50 if (cnt.type === "null") return null;51 if (cnt.type === "NaN") return NaN;52 if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity;53 if (cnt.type === "number") return +cnt.value;54 return cnt.value;55}56function minOverloadLength(overloads)57{58 // "The value of the Function object’s “length” property is59 // a Number determined as follows:60 // ". . .61 // "Return the length of the shortest argument list of the62 // entries in S."63 if (!overloads.length) {64 return 0;65 }66 return overloads.map(function(attr) {67 return attr.arguments ? attr.arguments.filter(function(arg) {68 return !arg.optional && !arg.variadic;69 }).length : 0;70 })71 .reduce(function(m, n) { return Math.min(m, n); });72}73// A helper to get the global of a Function object. This is needed to determine74// which global exceptions the function throws will come from.75function globalOf(func)76{77 try {78 // Use the fact that .constructor for a Function object is normally the79 // Function constructor, which can be used to mint a new function in the80 // right global.81 return func.constructor("return this;")();82 } catch (e) {83 }84 // If the above fails, because someone gave us a non-function, or a function85 // with a weird proto chain or weird .constructor property, just fall back86 // to 'self'.87 return self;88}89// https://esdiscuss.org/topic/isconstructor#content-1190function isConstructor(o) {91 try {92 new (new Proxy(o, {construct: () => ({})}));93 return true;94 } catch(e) {95 return false;96 }97}98function throwOrReject(a_test, operation, fn, obj, args, message, cb)99{100 if (operation.idlType.generic !== "Promise") {101 assert_throws_js(globalOf(fn).TypeError, function() {102 fn.apply(obj, args);103 }, message);104 cb();105 } else {106 try {107 promise_rejects_js(a_test, TypeError, fn.apply(obj, args), message).then(cb, cb);108 } catch (e){109 a_test.step(function() {110 assert_unreached("Throws \"" + e + "\" instead of rejecting promise");111 cb();112 });113 }114 }115}116function awaitNCallbacks(n, cb, ctx)117{118 var counter = 0;119 return function() {120 counter++;121 if (counter >= n) {122 cb();123 }124 };125}126/// IdlHarnessError ///127// Entry point128self.IdlHarnessError = function(message)129{130 /**131 * Message to be printed as the error's toString invocation.132 */133 this.message = message;134};135IdlHarnessError.prototype = Object.create(Error.prototype);136IdlHarnessError.prototype.toString = function()137{138 return this.message;139};140/// IdlArray ///141// Entry point142self.IdlArray = function()143{144 /**145 * A map from strings to the corresponding named IdlObject, such as146 * IdlInterface or IdlException. These are the things that test() will run147 * tests on.148 */149 this.members = {};150 /**151 * A map from strings to arrays of strings. The keys are interface or152 * exception names, and are expected to also exist as keys in this.members153 * (otherwise they'll be ignored). This is populated by add_objects() --154 * see documentation at the start of the file. The actual tests will be155 * run by calling this.members[name].test_object(obj) for each obj in156 * this.objects[name]. obj is a string that will be eval'd to produce a157 * JavaScript value, which is supposed to be an object implementing the158 * given IdlObject (interface, exception, etc.).159 */160 this.objects = {};161 /**162 * When adding multiple collections of IDLs one at a time, an earlier one163 * might contain a partial interface or includes statement that depends164 * on a later one. Save these up and handle them right before we run165 * tests.166 *167 * Both this.partials and this.includes will be the objects as parsed by168 * WebIDLParser.js, not wrapped in IdlInterface or similar.169 */170 this.partials = [];171 this.includes = [];172 /**173 * Record of skipped IDL items, in case we later realize that they are a174 * dependency (to retroactively process them).175 */176 this.skipped = new Map();177};178IdlArray.prototype.add_idls = function(raw_idls, options)179{180 /** Entry point. See documentation at beginning of file. */181 this.internal_add_idls(WebIDL2.parse(raw_idls), options);182};183IdlArray.prototype.add_untested_idls = function(raw_idls, options)184{185 /** Entry point. See documentation at beginning of file. */186 var parsed_idls = WebIDL2.parse(raw_idls);187 this.mark_as_untested(parsed_idls);188 this.internal_add_idls(parsed_idls, options);189};190IdlArray.prototype.mark_as_untested = function (parsed_idls)191{192 for (var i = 0; i < parsed_idls.length; i++) {193 parsed_idls[i].untested = true;194 if ("members" in parsed_idls[i]) {195 for (var j = 0; j < parsed_idls[i].members.length; j++) {196 parsed_idls[i].members[j].untested = true;197 }198 }199 }200};201IdlArray.prototype.is_excluded_by_options = function (name, options)202{203 return options &&204 (options.except && options.except.includes(name)205 || options.only && !options.only.includes(name));206};207IdlArray.prototype.add_dependency_idls = function(raw_idls, options)208{209 return this.internal_add_dependency_idls(WebIDL2.parse(raw_idls), options);210};211IdlArray.prototype.internal_add_dependency_idls = function(parsed_idls, options)212{213 const new_options = { only: [] }214 const all_deps = new Set();215 Object.values(this.members).forEach(v => {216 if (v.base) {217 all_deps.add(v.base);218 }219 });220 // Add both 'A' and 'B' for each 'A includes B' entry.221 this.includes.forEach(i => {222 all_deps.add(i.target);223 all_deps.add(i.includes);224 });225 this.partials.forEach(p => all_deps.add(p.name));226 // Add 'TypeOfType' for each "typedef TypeOfType MyType;" entry.227 Object.entries(this.members).forEach(([k, v]) => {228 if (v instanceof IdlTypedef) {229 let defs = v.idlType.union230 ? v.idlType.idlType.map(t => t.idlType)231 : [v.idlType.idlType];232 defs.forEach(d => all_deps.add(d));233 }234 });235 // Add the attribute idlTypes of all the nested members of idls.236 const attrDeps = parsedIdls => {237 return parsedIdls.reduce((deps, parsed) => {238 if (parsed.members) {239 for (const attr of Object.values(parsed.members).filter(m => m.type === 'attribute')) {240 let attrType = attr.idlType;241 // Check for generic members (e.g. FrozenArray<MyType>)242 if (attrType.generic) {243 deps.add(attrType.generic);244 attrType = attrType.idlType;245 }246 deps.add(attrType.idlType);247 }248 }249 if (parsed.base in this.members) {250 attrDeps([this.members[parsed.base]]).forEach(dep => deps.add(dep));251 }252 return deps;253 }, new Set());254 };255 const testedMembers = Object.values(this.members).filter(m => !m.untested && m.members);256 attrDeps(testedMembers).forEach(dep => all_deps.add(dep));257 const testedPartials = this.partials.filter(m => !m.untested && m.members);258 attrDeps(testedPartials).forEach(dep => all_deps.add(dep));259 if (options && options.except && options.only) {260 throw new IdlHarnessError("The only and except options can't be used together.");261 }262 const defined_or_untested = name => {263 // NOTE: Deps are untested, so we're lenient, and skip re-encountered definitions.264 // e.g. for 'idl' containing A:B, B:C, C:D265 // array.add_idls(idl, {only: ['A','B']}).266 // array.add_dependency_idls(idl);267 // B would be encountered as tested, and encountered as a dep, so we ignore.268 return name in this.members269 || this.is_excluded_by_options(name, options);270 }271 // Maps name -> [parsed_idl, ...]272 const process = function(parsed) {273 var deps = [];274 if (parsed.name) {275 deps.push(parsed.name);276 } else if (parsed.type === "includes") {277 deps.push(parsed.target);278 deps.push(parsed.includes);279 }280 deps = deps.filter(function(name) {281 if (!name282 || name === parsed.name && defined_or_untested(name)283 || !all_deps.has(name)) {284 // Flag as skipped, if it's not already processed, so we can285 // come back to it later if we retrospectively call it a dep.286 if (name && !(name in this.members)) {287 this.skipped.has(name)288 ? this.skipped.get(name).push(parsed)289 : this.skipped.set(name, [parsed]);290 }291 return false;292 }293 return true;294 }.bind(this));295 deps.forEach(function(name) {296 if (!new_options.only.includes(name)) {297 new_options.only.push(name);298 }299 const follow_up = new Set();300 for (const dep_type of ["inheritance", "includes"]) {301 if (parsed[dep_type]) {302 const inheriting = parsed[dep_type];303 const inheritor = parsed.name || parsed.target;304 const deps = [inheriting];305 // For A includes B, we can ignore A, unless B (or some of its306 // members) is being tested.307 if (dep_type !== "includes"308 || inheriting in this.members && !this.members[inheriting].untested309 || this.partials.some(function(p) {310 return p.name === inheriting;311 })) {312 deps.push(inheritor);313 }314 for (const dep of deps) {315 if (!new_options.only.includes(dep)) {316 new_options.only.push(dep);317 }318 all_deps.add(dep);319 follow_up.add(dep);320 }321 }322 }323 for (const deferred of follow_up) {324 if (this.skipped.has(deferred)) {325 const next = this.skipped.get(deferred);326 this.skipped.delete(deferred);327 next.forEach(process);328 }329 }330 }.bind(this));331 }.bind(this);332 for (let parsed of parsed_idls) {333 process(parsed);334 }335 this.mark_as_untested(parsed_idls);336 if (new_options.only.length) {337 this.internal_add_idls(parsed_idls, new_options);338 }339}340IdlArray.prototype.internal_add_idls = function(parsed_idls, options)341{342 /**343 * Internal helper called by add_idls() and add_untested_idls().344 *345 * parsed_idls is an array of objects that come from WebIDLParser.js's346 * "definitions" production. The add_untested_idls() entry point347 * additionally sets an .untested property on each object (and its348 * .members) so that they'll be skipped by test() -- they'll only be349 * used for base interfaces of tested interfaces, return types, etc.350 *351 * options is a dictionary that can have an only or except member which are352 * arrays. If only is given then only members, partials and interface353 * targets listed will be added, and if except is given only those that354 * aren't listed will be added. Only one of only and except can be used.355 */356 if (options && options.only && options.except)357 {358 throw new IdlHarnessError("The only and except options can't be used together.");359 }360 var should_skip = name => {361 return this.is_excluded_by_options(name, options);362 }363 parsed_idls.forEach(function(parsed_idl)364 {365 var partial_types = [366 "interface",367 "interface mixin",368 "dictionary",369 "namespace",370 ];371 if (parsed_idl.partial && partial_types.includes(parsed_idl.type))372 {373 if (should_skip(parsed_idl.name))374 {375 return;376 }377 this.partials.push(parsed_idl);378 return;379 }380 if (parsed_idl.type == "includes")381 {382 if (should_skip(parsed_idl.target))383 {384 return;385 }386 this.includes.push(parsed_idl);387 return;388 }389 parsed_idl.array = this;390 if (should_skip(parsed_idl.name))391 {392 return;393 }394 if (parsed_idl.name in this.members)395 {396 throw new IdlHarnessError("Duplicate identifier " + parsed_idl.name);397 }398 switch(parsed_idl.type)399 {400 case "interface":401 this.members[parsed_idl.name] =402 new IdlInterface(parsed_idl, /* is_callback = */ false, /* is_mixin = */ false);403 break;404 case "interface mixin":405 this.members[parsed_idl.name] =406 new IdlInterface(parsed_idl, /* is_callback = */ false, /* is_mixin = */ true);407 break;408 case "dictionary":409 // Nothing to test, but we need the dictionary info around for type410 // checks411 this.members[parsed_idl.name] = new IdlDictionary(parsed_idl);412 break;413 case "typedef":414 this.members[parsed_idl.name] = new IdlTypedef(parsed_idl);415 break;416 case "callback":417 this.members[parsed_idl.name] = new IdlCallback(parsed_idl);418 break;419 case "enum":420 this.members[parsed_idl.name] = new IdlEnum(parsed_idl);421 break;422 case "callback interface":423 this.members[parsed_idl.name] =424 new IdlInterface(parsed_idl, /* is_callback = */ true, /* is_mixin = */ false);425 break;426 case "namespace":427 this.members[parsed_idl.name] = new IdlNamespace(parsed_idl);428 break;429 default:430 throw parsed_idl.name + ": " + parsed_idl.type + " not yet supported";431 }432 }.bind(this));433};434IdlArray.prototype.add_objects = function(dict)435{436 /** Entry point. See documentation at beginning of file. */437 for (var k in dict)438 {439 if (k in this.objects)440 {441 this.objects[k] = this.objects[k].concat(dict[k]);442 }443 else444 {445 this.objects[k] = dict[k];446 }447 }448};449IdlArray.prototype.prevent_multiple_testing = function(name)450{451 /** Entry point. See documentation at beginning of file. */452 this.members[name].prevent_multiple_testing = true;453};454IdlArray.prototype.is_json_type = function(type)455{456 /**457 * Checks whether type is a JSON type as per458 * https://webidl.spec.whatwg.org/#dfn-json-types459 */460 var idlType = type.idlType;461 if (type.generic == "Promise") { return false; }462 // nullable and annotated types don't need to be handled separately,463 // as webidl2 doesn't represent them wrapped-up (as they're described464 // in WebIDL).465 // union and record types466 if (type.union || type.generic == "record") {467 return idlType.every(this.is_json_type, this);468 }469 // sequence types470 if (type.generic == "sequence" || type.generic == "FrozenArray") {471 return this.is_json_type(idlType[0]);472 }473 if (typeof idlType != "string") { throw new Error("Unexpected type " + JSON.stringify(idlType)); }474 switch (idlType)475 {476 // Numeric types477 case "byte":478 case "octet":479 case "short":480 case "unsigned short":481 case "long":482 case "unsigned long":483 case "long long":484 case "unsigned long long":485 case "float":486 case "double":487 case "unrestricted float":488 case "unrestricted double":489 // boolean490 case "boolean":491 // string types492 case "DOMString":493 case "ByteString":494 case "USVString":495 // object type496 case "object":497 return true;498 case "Error":499 case "DOMException":500 case "Int8Array":501 case "Int16Array":502 case "Int32Array":503 case "Uint8Array":504 case "Uint16Array":505 case "Uint32Array":506 case "Uint8ClampedArray":507 case "BigInt64Array":508 case "BigUint64Array":509 case "Float32Array":510 case "Float64Array":511 case "ArrayBuffer":512 case "DataView":513 case "any":514 return false;515 default:516 var thing = this.members[idlType];517 if (!thing) { throw new Error("Type " + idlType + " not found"); }518 if (thing instanceof IdlEnum) { return true; }519 if (thing instanceof IdlTypedef) {520 return this.is_json_type(thing.idlType);521 }522 // dictionaries where all of their members are JSON types523 if (thing instanceof IdlDictionary) {524 const map = new Map();525 for (const dict of thing.get_reverse_inheritance_stack()) {526 for (const m of dict.members) {527 map.set(m.name, m.idlType);528 }529 }530 return Array.from(map.values()).every(this.is_json_type, this);531 }532 // interface types that have a toJSON operation declared on themselves or533 // one of their inherited interfaces.534 if (thing instanceof IdlInterface) {535 var base;536 while (thing)537 {538 if (thing.has_to_json_regular_operation()) { return true; }539 var mixins = this.includes[thing.name];540 if (mixins) {541 mixins = mixins.map(function(id) {542 var mixin = this.members[id];543 if (!mixin) {544 throw new Error("Interface " + id + " not found (implemented by " + thing.name + ")");545 }546 return mixin;547 }, this);548 if (mixins.some(function(m) { return m.has_to_json_regular_operation() } )) { return true; }549 }550 if (!thing.base) { return false; }551 base = this.members[thing.base];552 if (!base) {553 throw new Error("Interface " + thing.base + " not found (inherited by " + thing.name + ")");554 }555 thing = base;556 }557 return false;558 }559 return false;560 }561};562function exposure_set(object, default_set) {563 var exposed = object.extAttrs && object.extAttrs.filter(a => a.name === "Exposed");564 if (exposed && exposed.length > 1) {565 throw new IdlHarnessError(566 `Multiple 'Exposed' extended attributes on ${object.name}`);567 }568 let result = default_set || ["Window"];569 if (result && !(result instanceof Set)) {570 result = new Set(result);571 }572 if (exposed && exposed.length) {573 const { rhs } = exposed[0];574 // Could be a list or a string.575 const set =576 rhs.type === "*" ?577 [ "*" ] :578 rhs.type === "identifier-list" ?579 rhs.value.map(id => id.value) :580 [ rhs.value ];581 result = new Set(set);582 }583 if (result && result.has("*")) {584 return "*";585 }586 if (result && result.has("Worker")) {587 result.delete("Worker");588 result.add("DedicatedWorker");589 result.add("ServiceWorker");590 result.add("SharedWorker");591 }592 return result;593}594function exposed_in(globals) {595 if (globals === "*") {596 return true;597 }598 if ('Window' in self) {599 return globals.has("Window");600 }601 if ('DedicatedWorkerGlobalScope' in self &&602 self instanceof DedicatedWorkerGlobalScope) {603 return globals.has("DedicatedWorker");604 }605 if ('SharedWorkerGlobalScope' in self &&606 self instanceof SharedWorkerGlobalScope) {607 return globals.has("SharedWorker");608 }609 if ('ServiceWorkerGlobalScope' in self &&610 self instanceof ServiceWorkerGlobalScope) {611 return globals.has("ServiceWorker");612 }613 if (Object.getPrototypeOf(self) === Object.prototype) {614 // ShadowRealm - only exposed with `"*"`.615 return false;616 }617 throw new IdlHarnessError("Unexpected global object");618}619/**620 * Asserts that the given error message is thrown for the given function.621 * @param {string|IdlHarnessError} error Expected Error message.622 * @param {Function} idlArrayFunc Function operating on an IdlArray that should throw.623 */624IdlArray.prototype.assert_throws = function(error, idlArrayFunc)625{626 try {627 idlArrayFunc.call(this, this);628 } catch (e) {629 if (e instanceof AssertionError) {630 throw e;631 }632 // Assertions for behaviour of the idlharness.js engine.633 if (error instanceof IdlHarnessError) {634 error = error.message;635 }636 if (e.message !== error) {637 throw new IdlHarnessError(`${idlArrayFunc} threw "${e}", not the expected IdlHarnessError "${error}"`);638 }639 return;640 }641 throw new IdlHarnessError(`${idlArrayFunc} did not throw the expected IdlHarnessError`);642}643IdlArray.prototype.test = function()644{645 /** Entry point. See documentation at beginning of file. */646 // First merge in all partial definitions and interface mixins.647 this.merge_partials();648 this.merge_mixins();649 // Assert B defined for A : B650 for (const member of Object.values(this.members).filter(m => m.base)) {651 const lhs = member.name;652 const rhs = member.base;653 if (!(rhs in this.members)) throw new IdlHarnessError(`${lhs} inherits ${rhs}, but ${rhs} is undefined.`);654 const lhs_is_interface = this.members[lhs] instanceof IdlInterface;655 const rhs_is_interface = this.members[rhs] instanceof IdlInterface;656 if (rhs_is_interface != lhs_is_interface) {657 if (!lhs_is_interface) throw new IdlHarnessError(`${lhs} inherits ${rhs}, but ${lhs} is not an interface.`);658 if (!rhs_is_interface) throw new IdlHarnessError(`${lhs} inherits ${rhs}, but ${rhs} is not an interface.`);659 }660 // Check for circular dependencies.661 member.get_reverse_inheritance_stack();662 }663 Object.getOwnPropertyNames(this.members).forEach(function(memberName) {664 var member = this.members[memberName];665 if (!(member instanceof IdlInterface)) {666 return;667 }668 var globals = exposure_set(member);669 member.exposed = exposed_in(globals);670 member.exposureSet = globals;671 }.bind(this));672 // Now run test() on every member, and test_object() for every object.673 for (var name in this.members)674 {675 this.members[name].test();676 if (name in this.objects)677 {678 const objects = this.objects[name];679 if (!objects || !Array.isArray(objects)) {680 throw new IdlHarnessError(`Invalid or empty objects for member ${name}`);681 }682 objects.forEach(function(str)683 {684 if (!this.members[name] || !(this.members[name] instanceof IdlInterface)) {685 throw new IdlHarnessError(`Invalid object member name ${name}`);686 }687 this.members[name].test_object(str);688 }.bind(this));689 }690 }691};692IdlArray.prototype.merge_partials = function()693{694 const testedPartials = new Map();695 this.partials.forEach(function(parsed_idl)696 {697 const originalExists = parsed_idl.name in this.members698 && (this.members[parsed_idl.name] instanceof IdlInterface699 || this.members[parsed_idl.name] instanceof IdlDictionary700 || this.members[parsed_idl.name] instanceof IdlNamespace);701 // Ensure unique test name in case of multiple partials.702 let partialTestName = parsed_idl.name;703 let partialTestCount = 1;704 if (testedPartials.has(parsed_idl.name)) {705 partialTestCount += testedPartials.get(parsed_idl.name);706 partialTestName = `${partialTestName}[${partialTestCount}]`;707 }708 testedPartials.set(parsed_idl.name, partialTestCount);709 if (!parsed_idl.untested) {710 test(function () {711 assert_true(originalExists, `Original ${parsed_idl.type} should be defined`);712 var expected;713 switch (parsed_idl.type) {714 case 'dictionary': expected = IdlDictionary; break;715 case 'namespace': expected = IdlNamespace; break;716 case 'interface':717 case 'interface mixin':718 default:719 expected = IdlInterface; break;720 }721 assert_true(722 expected.prototype.isPrototypeOf(this.members[parsed_idl.name]),723 `Original ${parsed_idl.name} definition should have type ${parsed_idl.type}`);724 }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: original ${parsed_idl.type} defined`);725 }726 if (!originalExists) {727 // Not good.. but keep calm and carry on.728 return;729 }730 if (parsed_idl.extAttrs)731 {732 // Special-case "Exposed". Must be a subset of original interface's exposure.733 // Exposed on a partial is the equivalent of having the same Exposed on all nested members.734 // See https://github.com/heycam/webidl/issues/154 for discrepency between Exposed and735 // other extended attributes on partial interfaces.736 const exposureAttr = parsed_idl.extAttrs.find(a => a.name === "Exposed");737 if (exposureAttr) {738 if (!parsed_idl.untested) {739 test(function () {740 const partialExposure = exposure_set(parsed_idl);741 const memberExposure = exposure_set(this.members[parsed_idl.name]);742 if (memberExposure === "*") {743 return;744 }745 if (partialExposure === "*") {746 throw new IdlHarnessError(747 `Partial ${parsed_idl.name} ${parsed_idl.type} is exposed everywhere, the original ${parsed_idl.type} is not.`);748 }749 partialExposure.forEach(name => {750 if (!memberExposure || !memberExposure.has(name)) {751 throw new IdlHarnessError(752 `Partial ${parsed_idl.name} ${parsed_idl.type} is exposed to '${name}', the original ${parsed_idl.type} is not.`);753 }754 });755 }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: valid exposure set`);756 }757 parsed_idl.members.forEach(function (member) {758 member.extAttrs.push(exposureAttr);759 }.bind(this));760 }761 parsed_idl.extAttrs.forEach(function(extAttr)762 {763 // "Exposed" already handled above.764 if (extAttr.name === "Exposed") {765 return;766 }767 this.members[parsed_idl.name].extAttrs.push(extAttr);768 }.bind(this));769 }770 if (parsed_idl.members.length) {771 test(function () {772 var clash = parsed_idl.members.find(function(member) {773 return this.members[parsed_idl.name].members.find(function(m) {774 return this.are_duplicate_members(m, member);775 }.bind(this));776 }.bind(this));777 parsed_idl.members.forEach(function(member)778 {779 this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member));780 }.bind(this));781 assert_true(!clash, "member " + (clash && clash.name) + " is unique");782 }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: member names are unique`);783 }784 }.bind(this));785 this.partials = [];786}787IdlArray.prototype.merge_mixins = function()788{789 for (const parsed_idl of this.includes)790 {791 const lhs = parsed_idl.target;792 const rhs = parsed_idl.includes;793 var errStr = lhs + " includes " + rhs + ", but ";794 if (!(lhs in this.members)) throw errStr + lhs + " is undefined.";795 if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + " is not an interface.";796 if (!(rhs in this.members)) throw errStr + rhs + " is undefined.";797 if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface.";798 if (this.members[rhs].members.length) {799 test(function () {800 var clash = this.members[rhs].members.find(function(member) {801 return this.members[lhs].members.find(function(m) {802 return this.are_duplicate_members(m, member);803 }.bind(this));804 }.bind(this));805 this.members[rhs].members.forEach(function(member) {806 assert_true(807 this.members[lhs].members.every(m => !this.are_duplicate_members(m, member)),808 "member " + member.name + " is unique");809 this.members[lhs].members.push(new IdlInterfaceMember(member));810 }.bind(this));811 assert_true(!clash, "member " + (clash && clash.name) + " is unique");812 }.bind(this), lhs + " includes " + rhs + ": member names are unique");813 }814 }815 this.includes = [];816}817IdlArray.prototype.are_duplicate_members = function(m1, m2) {818 if (m1.name !== m2.name) {819 return false;820 }821 if (m1.type === 'operation' && m2.type === 'operation'822 && m1.arguments.length !== m2.arguments.length) {823 // Method overload. TODO: Deep comparison of arguments.824 return false;825 }826 return true;827}828IdlArray.prototype.assert_type_is = function(value, type)829{830 if (type.idlType in this.members831 && this.members[type.idlType] instanceof IdlTypedef) {832 this.assert_type_is(value, this.members[type.idlType].idlType);833 return;834 }835 if (type.nullable && value === null)836 {837 // This is fine838 return;839 }840 if (type.union) {841 for (var i = 0; i < type.idlType.length; i++) {842 try {843 this.assert_type_is(value, type.idlType[i]);844 // No AssertionError, so we match one type in the union845 return;846 } catch(e) {847 if (e instanceof AssertionError) {848 // We didn't match this type, let's try some others849 continue;850 }851 throw e;852 }853 }854 // TODO: Is there a nice way to list the union's types in the message?855 assert_true(false, "Attribute has value " + format_value(value)856 + " which doesn't match any of the types in the union");857 }858 /**859 * Helper function that tests that value is an instance of type according860 * to the rules of WebIDL. value is any JavaScript value, and type is an861 * object produced by WebIDLParser.js' "type" production. That production862 * is fairly elaborate due to the complexity of WebIDL's types, so it's863 * best to look at the grammar to figure out what properties it might have.864 */865 if (type.idlType == "any")866 {867 // No assertions to make868 return;869 }870 if (type.array)871 {872 // TODO: not supported yet873 return;874 }875 if (type.generic === "sequence" || type.generic == "ObservableArray")876 {877 assert_true(Array.isArray(value), "should be an Array");878 if (!value.length)879 {880 // Nothing we can do.881 return;882 }883 this.assert_type_is(value[0], type.idlType[0]);884 return;885 }886 if (type.generic === "Promise") {887 assert_true("then" in value, "Attribute with a Promise type should have a then property");888 // TODO: Ideally, we would check on project fulfillment889 // that we get the right type890 // but that would require making the type check async891 return;892 }893 if (type.generic === "FrozenArray") {894 assert_true(Array.isArray(value), "Value should be array");895 assert_true(Object.isFrozen(value), "Value should be frozen");896 if (!value.length)897 {898 // Nothing we can do.899 return;900 }901 this.assert_type_is(value[0], type.idlType[0]);902 return;903 }904 type = Array.isArray(type.idlType) ? type.idlType[0] : type.idlType;905 switch(type)906 {907 case "undefined":908 assert_equals(value, undefined);909 return;910 case "boolean":911 assert_equals(typeof value, "boolean");912 return;913 case "byte":914 assert_equals(typeof value, "number");915 assert_equals(value, Math.floor(value), "should be an integer");916 assert_true(-128 <= value && value <= 127, "byte " + value + " should be in range [-128, 127]");917 return;918 case "octet":919 assert_equals(typeof value, "number");920 assert_equals(value, Math.floor(value), "should be an integer");921 assert_true(0 <= value && value <= 255, "octet " + value + " should be in range [0, 255]");922 return;923 case "short":924 assert_equals(typeof value, "number");925 assert_equals(value, Math.floor(value), "should be an integer");926 assert_true(-32768 <= value && value <= 32767, "short " + value + " should be in range [-32768, 32767]");927 return;928 case "unsigned short":929 assert_equals(typeof value, "number");930 assert_equals(value, Math.floor(value), "should be an integer");931 assert_true(0 <= value && value <= 65535, "unsigned short " + value + " should be in range [0, 65535]");932 return;933 case "long":934 assert_equals(typeof value, "number");935 assert_equals(value, Math.floor(value), "should be an integer");936 assert_true(-2147483648 <= value && value <= 2147483647, "long " + value + " should be in range [-2147483648, 2147483647]");937 return;938 case "unsigned long":939 assert_equals(typeof value, "number");940 assert_equals(value, Math.floor(value), "should be an integer");941 assert_true(0 <= value && value <= 4294967295, "unsigned long " + value + " should be in range [0, 4294967295]");942 return;943 case "long long":944 assert_equals(typeof value, "number");945 return;946 case "unsigned long long":947 case "DOMTimeStamp":948 assert_equals(typeof value, "number");949 assert_true(0 <= value, "unsigned long long should be positive");950 return;951 case "float":952 assert_equals(typeof value, "number");953 assert_equals(value, Math.fround(value), "float rounded to 32-bit float should be itself");954 assert_not_equals(value, Infinity);955 assert_not_equals(value, -Infinity);956 assert_not_equals(value, NaN);957 return;958 case "DOMHighResTimeStamp":959 case "double":960 assert_equals(typeof value, "number");961 assert_not_equals(value, Infinity);962 assert_not_equals(value, -Infinity);963 assert_not_equals(value, NaN);964 return;965 case "unrestricted float":966 assert_equals(typeof value, "number");967 assert_equals(value, Math.fround(value), "unrestricted float rounded to 32-bit float should be itself");968 return;969 case "unrestricted double":970 assert_equals(typeof value, "number");971 return;972 case "DOMString":973 assert_equals(typeof value, "string");974 return;975 case "ByteString":976 assert_equals(typeof value, "string");977 assert_regexp_match(value, /^[\x00-\x7F]*$/);978 return;979 case "USVString":980 assert_equals(typeof value, "string");981 assert_regexp_match(value, /^([\x00-\ud7ff\ue000-\uffff]|[\ud800-\udbff][\udc00-\udfff])*$/);982 return;983 case "ArrayBufferView":984 assert_true(ArrayBuffer.isView(value));985 return;986 case "object":987 assert_in_array(typeof value, ["object", "function"], "wrong type: not object or function");988 return;989 }990 // This is a catch-all for any IDL type name which follows JS class991 // semantics. This includes some non-interface IDL types (e.g. Int8Array,992 // Function, ...), as well as any interface types that are not in the IDL993 // that is fed to the harness. If an IDL type does not follow JS class994 // semantics then it should go in the switch statement above. If an IDL995 // type needs full checking, then the test should include it in the IDL it996 // feeds to the harness.997 if (!(type in this.members))998 {999 assert_true(value instanceof self[type], "wrong type: not a " + type);1000 return;1001 }1002 if (this.members[type] instanceof IdlInterface)1003 {1004 // We don't want to run the full1005 // IdlInterface.prototype.test_instance_of, because that could result1006 // in an infinite loop. TODO: This means we don't have tests for1007 // LegacyNoInterfaceObject interfaces, and we also can't test objects1008 // that come from another self.1009 assert_in_array(typeof value, ["object", "function"], "wrong type: not object or function");1010 if (value instanceof Object1011 && !this.members[type].has_extended_attribute("LegacyNoInterfaceObject")1012 && type in self)1013 {1014 assert_true(value instanceof self[type], "instanceof " + type);1015 }1016 }1017 else if (this.members[type] instanceof IdlEnum)1018 {1019 assert_equals(typeof value, "string");1020 }1021 else if (this.members[type] instanceof IdlDictionary)1022 {1023 // TODO: Test when we actually have something to test this on1024 }1025 else if (this.members[type] instanceof IdlCallback)1026 {1027 assert_equals(typeof value, "function");1028 }1029 else1030 {1031 throw new IdlHarnessError("Type " + type + " isn't an interface, callback or dictionary");1032 }1033};1034/// IdlObject ///1035function IdlObject() {}1036IdlObject.prototype.test = function()1037{1038 /**1039 * By default, this does nothing, so no actual tests are run for IdlObjects1040 * that don't define any (e.g., IdlDictionary at the time of this writing).1041 */1042};1043IdlObject.prototype.has_extended_attribute = function(name)1044{1045 /**1046 * This is only meaningful for things that support extended attributes,1047 * such as interfaces, exceptions, and members.1048 */1049 return this.extAttrs.some(function(o)1050 {1051 return o.name == name;1052 });1053};1054/// IdlDictionary ///1055// Used for IdlArray.prototype.assert_type_is1056function IdlDictionary(obj)1057{1058 /**1059 * obj is an object produced by the WebIDLParser.js "dictionary"1060 * production.1061 */1062 /** Self-explanatory. */1063 this.name = obj.name;1064 /** A back-reference to our IdlArray. */1065 this.array = obj.array;1066 /** An array of objects produced by the "dictionaryMember" production. */1067 this.members = obj.members;1068 /**1069 * The name (as a string) of the dictionary type we inherit from, or null1070 * if there is none.1071 */1072 this.base = obj.inheritance;1073}1074IdlDictionary.prototype = Object.create(IdlObject.prototype);1075IdlDictionary.prototype.get_reverse_inheritance_stack = function() {1076 return IdlInterface.prototype.get_reverse_inheritance_stack.call(this);1077};1078/// IdlInterface ///1079function IdlInterface(obj, is_callback, is_mixin)1080{1081 /**1082 * obj is an object produced by the WebIDLParser.js "interface" production.1083 */1084 /** Self-explanatory. */1085 this.name = obj.name;1086 /** A back-reference to our IdlArray. */1087 this.array = obj.array;1088 /**1089 * An indicator of whether we should run tests on the interface object and1090 * interface prototype object. Tests on members are controlled by .untested1091 * on each member, not this.1092 */1093 this.untested = obj.untested;1094 /** An array of objects produced by the "ExtAttr" production. */1095 this.extAttrs = obj.extAttrs;1096 /** An array of IdlInterfaceMembers. */1097 this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); });1098 if (this.has_extended_attribute("LegacyUnforgeable")) {1099 this.members1100 .filter(function(m) { return m.special !== "static" && (m.type == "attribute" || m.type == "operation"); })1101 .forEach(function(m) { return m.isUnforgeable = true; });1102 }1103 /**1104 * The name (as a string) of the type we inherit from, or null if there is1105 * none.1106 */1107 this.base = obj.inheritance;1108 this._is_callback = is_callback;1109 this._is_mixin = is_mixin;1110}1111IdlInterface.prototype = Object.create(IdlObject.prototype);1112IdlInterface.prototype.is_callback = function()1113{1114 return this._is_callback;1115};1116IdlInterface.prototype.is_mixin = function()1117{1118 return this._is_mixin;1119};1120IdlInterface.prototype.has_constants = function()1121{1122 return this.members.some(function(member) {1123 return member.type === "const";1124 });1125};1126IdlInterface.prototype.get_unscopables = function()1127{1128 return this.members.filter(function(member) {1129 return member.isUnscopable;1130 });1131};1132IdlInterface.prototype.is_global = function()1133{1134 return this.extAttrs.some(function(attribute) {1135 return attribute.name === "Global";1136 });1137};1138/**1139 * Value of the LegacyNamespace extended attribute, if any.1140 *1141 * https://webidl.spec.whatwg.org/#LegacyNamespace1142 */1143IdlInterface.prototype.get_legacy_namespace = function()1144{1145 var legacyNamespace = this.extAttrs.find(function(attribute) {1146 return attribute.name === "LegacyNamespace";1147 });1148 return legacyNamespace ? legacyNamespace.rhs.value : undefined;1149};1150IdlInterface.prototype.get_interface_object_owner = function()1151{1152 var legacyNamespace = this.get_legacy_namespace();1153 return legacyNamespace ? self[legacyNamespace] : self;1154};1155IdlInterface.prototype.should_have_interface_object = function()1156{1157 // "For every interface that is exposed in a given ECMAScript global1158 // environment and:1159 // * is a callback interface that has constants declared on it, or1160 // * is a non-callback interface that is not declared with the1161 // [LegacyNoInterfaceObject] extended attribute,1162 // a corresponding property MUST exist on the ECMAScript global object.1163 return this.is_callback() ? this.has_constants() : !this.has_extended_attribute("LegacyNoInterfaceObject");1164};1165IdlInterface.prototype.assert_interface_object_exists = function()1166{1167 var owner = this.get_legacy_namespace() || "self";1168 assert_own_property(self[owner], this.name, owner + " does not have own property " + format_value(this.name));1169};1170IdlInterface.prototype.get_interface_object = function() {1171 if (!this.should_have_interface_object()) {1172 var reason = this.is_callback() ? "lack of declared constants" : "declared [LegacyNoInterfaceObject] attribute";1173 throw new IdlHarnessError(this.name + " has no interface object due to " + reason);1174 }1175 return this.get_interface_object_owner()[this.name];1176};1177IdlInterface.prototype.get_qualified_name = function() {1178 // https://webidl.spec.whatwg.org/#qualified-name1179 var legacyNamespace = this.get_legacy_namespace();1180 if (legacyNamespace) {1181 return legacyNamespace + "." + this.name;1182 }1183 return this.name;1184};1185IdlInterface.prototype.has_to_json_regular_operation = function() {1186 return this.members.some(function(m) {1187 return m.is_to_json_regular_operation();1188 });1189};1190IdlInterface.prototype.has_default_to_json_regular_operation = function() {1191 return this.members.some(function(m) {1192 return m.is_to_json_regular_operation() && m.has_extended_attribute("Default");1193 });1194};1195/**1196 * Implementation of https://webidl.spec.whatwg.org/#create-an-inheritance-stack1197 * with the order reversed.1198 *1199 * The order is reversed so that the base class comes first in the list, because1200 * this is what all call sites need.1201 *1202 * So given:1203 *1204 * A : B {};1205 * B : C {};1206 * C {};1207 *1208 * then A.get_reverse_inheritance_stack() returns [C, B, A],1209 * and B.get_reverse_inheritance_stack() returns [C, B].1210 *1211 * Note: as dictionary inheritance is expressed identically by the AST,1212 * this works just as well for getting a stack of inherited dictionaries.1213 */1214IdlInterface.prototype.get_reverse_inheritance_stack = function() {1215 const stack = [this];1216 let idl_interface = this;1217 while (idl_interface.base) {1218 const base = this.array.members[idl_interface.base];1219 if (!base) {1220 throw new Error(idl_interface.type + " " + idl_interface.base + " not found (inherited by " + idl_interface.name + ")");1221 } else if (stack.indexOf(base) > -1) {1222 stack.unshift(base);1223 const dep_chain = stack.map(i => i.name).join(',');1224 throw new IdlHarnessError(`${this.name} has a circular dependency: ${dep_chain}`);1225 }1226 idl_interface = base;1227 stack.unshift(idl_interface);1228 }1229 return stack;1230};1231/**1232 * Implementation of1233 * https://webidl.spec.whatwg.org/#default-tojson-operation1234 * for testing purposes.1235 *1236 * Collects the IDL types of the attributes that meet the criteria1237 * for inclusion in the default toJSON operation for easy1238 * comparison with actual value1239 */1240IdlInterface.prototype.default_to_json_operation = function() {1241 const map = new Map()1242 let isDefault = false;1243 for (const I of this.get_reverse_inheritance_stack()) {1244 if (I.has_default_to_json_regular_operation()) {1245 isDefault = true;1246 for (const m of I.members) {1247 if (m.special !== "static" && m.type == "attribute" && I.array.is_json_type(m.idlType)) {1248 map.set(m.name, m.idlType);1249 }1250 }1251 } else if (I.has_to_json_regular_operation()) {1252 isDefault = false;1253 }1254 }1255 return isDefault ? map : null;1256};1257IdlInterface.prototype.test = function()1258{1259 if (this.has_extended_attribute("LegacyNoInterfaceObject") || this.is_mixin())1260 {1261 // No tests to do without an instance. TODO: We should still be able1262 // to run tests on the prototype object, if we obtain one through some1263 // other means.1264 return;1265 }1266 // If the interface object is not exposed, only test that. Members can't be1267 // tested either, but objects could still be tested in |test_object|.1268 if (!this.exposed)1269 {1270 if (!this.untested)1271 {1272 subsetTestByKey(this.name, test, function() {1273 assert_false(this.name in self);1274 }.bind(this), this.name + " interface: existence and properties of interface object");1275 }1276 return;1277 }1278 if (!this.untested)1279 {1280 // First test things to do with the exception/interface object and1281 // exception/interface prototype object.1282 this.test_self();1283 }1284 // Then test things to do with its members (constants, fields, attributes,1285 // operations, . . .). These are run even if .untested is true, because1286 // members might themselves be marked as .untested. This might happen to1287 // interfaces if the interface itself is untested but a partial interface1288 // that extends it is tested -- then the interface itself and its initial1289 // members will be marked as untested, but the members added by the partial1290 // interface are still tested.1291 this.test_members();1292};1293IdlInterface.prototype.constructors = function()1294{1295 return this.members1296 .filter(function(m) { return m.type == "constructor"; });1297}1298IdlInterface.prototype.test_self = function()1299{1300 subsetTestByKey(this.name, test, function()1301 {1302 if (!this.should_have_interface_object()) {1303 return;1304 }1305 // The name of the property is the identifier of the interface, and its1306 // value is an object called the interface object.1307 // The property has the attributes { [[Writable]]: true,1308 // [[Enumerable]]: false, [[Configurable]]: true }."1309 // TODO: Should we test here that the property is actually writable1310 // etc., or trust getOwnPropertyDescriptor?1311 this.assert_interface_object_exists();1312 var desc = Object.getOwnPropertyDescriptor(this.get_interface_object_owner(), this.name);1313 assert_false("get" in desc, "self's property " + format_value(this.name) + " should not have a getter");1314 assert_false("set" in desc, "self's property " + format_value(this.name) + " should not have a setter");1315 assert_true(desc.writable, "self's property " + format_value(this.name) + " should be writable");1316 assert_false(desc.enumerable, "self's property " + format_value(this.name) + " should not be enumerable");1317 assert_true(desc.configurable, "self's property " + format_value(this.name) + " should be configurable");1318 if (this.is_callback()) {1319 // "The internal [[Prototype]] property of an interface object for1320 // a callback interface must be the Function.prototype object."1321 assert_equals(Object.getPrototypeOf(this.get_interface_object()), Function.prototype,1322 "prototype of self's property " + format_value(this.name) + " is not Object.prototype");1323 return;1324 }1325 // "The interface object for a given non-callback interface is a1326 // function object."1327 // "If an object is defined to be a function object, then it has1328 // characteristics as follows:"1329 // Its [[Prototype]] internal property is otherwise specified (see1330 // below).1331 // "* Its [[Get]] internal property is set as described in ECMA-2621332 // section 9.1.8."1333 // Not much to test for this.1334 // "* Its [[Construct]] internal property is set as described in1335 // ECMA-262 section 19.2.2.3."1336 // "* Its @@hasInstance property is set as described in ECMA-2621337 // section 19.2.3.8, unless otherwise specified."1338 // TODO1339 // ES6 (rev 30) 19.1.3.6:1340 // "Else, if O has a [[Call]] internal method, then let builtinTag be1341 // "Function"."1342 assert_class_string(this.get_interface_object(), "Function", "class string of " + this.name);1343 // "The [[Prototype]] internal property of an interface object for a1344 // non-callback interface is determined as follows:"1345 var prototype = Object.getPrototypeOf(this.get_interface_object());1346 if (this.base) {1347 // "* If the interface inherits from some other interface, the1348 // value of [[Prototype]] is the interface object for that other1349 // interface."1350 var inherited_interface = this.array.members[this.base];1351 if (!inherited_interface.has_extended_attribute("LegacyNoInterfaceObject")) {1352 inherited_interface.assert_interface_object_exists();1353 assert_equals(prototype, inherited_interface.get_interface_object(),1354 'prototype of ' + this.name + ' is not ' +1355 this.base);1356 }1357 } else {1358 // "If the interface doesn't inherit from any other interface, the1359 // value of [[Prototype]] is %FunctionPrototype% ([ECMA-262],1360 // section 6.1.7.4)."1361 assert_equals(prototype, Function.prototype,1362 "prototype of self's property " + format_value(this.name) + " is not Function.prototype");1363 }1364 // Always test for [[Construct]]:1365 // https://github.com/heycam/webidl/issues/6981366 assert_true(isConstructor(this.get_interface_object()), "interface object must pass IsConstructor check");1367 var interface_object = this.get_interface_object();1368 assert_throws_js(globalOf(interface_object).TypeError, function() {1369 interface_object();1370 }, "interface object didn't throw TypeError when called as a function");1371 if (!this.constructors().length) {1372 assert_throws_js(globalOf(interface_object).TypeError, function() {1373 new interface_object();1374 }, "interface object didn't throw TypeError when called as a constructor");1375 }1376 }.bind(this), this.name + " interface: existence and properties of interface object");1377 if (this.should_have_interface_object() && !this.is_callback()) {1378 subsetTestByKey(this.name, test, function() {1379 // This function tests WebIDL as of 2014-10-25.1380 // https://webidl.spec.whatwg.org/#es-interface-call1381 this.assert_interface_object_exists();1382 // "Interface objects for non-callback interfaces MUST have a1383 // property named “length” with attributes { [[Writable]]: false,1384 // [[Enumerable]]: false, [[Configurable]]: true } whose value is1385 // a Number."1386 assert_own_property(this.get_interface_object(), "length");1387 var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), "length");1388 assert_false("get" in desc, this.name + ".length should not have a getter");1389 assert_false("set" in desc, this.name + ".length should not have a setter");1390 assert_false(desc.writable, this.name + ".length should not be writable");1391 assert_false(desc.enumerable, this.name + ".length should not be enumerable");1392 assert_true(desc.configurable, this.name + ".length should be configurable");1393 var constructors = this.constructors();1394 var expected_length = minOverloadLength(constructors);1395 assert_equals(this.get_interface_object().length, expected_length, "wrong value for " + this.name + ".length");1396 }.bind(this), this.name + " interface object length");1397 }1398 if (this.should_have_interface_object()) {1399 subsetTestByKey(this.name, test, function() {1400 // This function tests WebIDL as of 2015-11-17.1401 // https://webidl.spec.whatwg.org/#interface-object1402 this.assert_interface_object_exists();1403 // "All interface objects must have a property named “name” with1404 // attributes { [[Writable]]: false, [[Enumerable]]: false,1405 // [[Configurable]]: true } whose value is the identifier of the1406 // corresponding interface."1407 assert_own_property(this.get_interface_object(), "name");1408 var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), "name");1409 assert_false("get" in desc, this.name + ".name should not have a getter");1410 assert_false("set" in desc, this.name + ".name should not have a setter");1411 assert_false(desc.writable, this.name + ".name should not be writable");1412 assert_false(desc.enumerable, this.name + ".name should not be enumerable");1413 assert_true(desc.configurable, this.name + ".name should be configurable");1414 assert_equals(this.get_interface_object().name, this.name, "wrong value for " + this.name + ".name");1415 }.bind(this), this.name + " interface object name");1416 }1417 if (this.has_extended_attribute("LegacyWindowAlias")) {1418 subsetTestByKey(this.name, test, function()1419 {1420 var aliasAttrs = this.extAttrs.filter(function(o) { return o.name === "LegacyWindowAlias"; });1421 if (aliasAttrs.length > 1) {1422 throw new IdlHarnessError("Invalid IDL: multiple LegacyWindowAlias extended attributes on " + this.name);1423 }1424 if (this.is_callback()) {1425 throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on non-interface " + this.name);1426 }1427 if (!(this.exposureSet === "*" || this.exposureSet.has("Window"))) {1428 throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " which is not exposed in Window");1429 }1430 // TODO: when testing of [LegacyNoInterfaceObject] interfaces is supported,1431 // check that it's not specified together with LegacyWindowAlias.1432 // TODO: maybe check that [LegacyWindowAlias] is not specified on a partial interface.1433 var rhs = aliasAttrs[0].rhs;1434 if (!rhs) {1435 throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " without identifier");1436 }1437 var aliases;1438 if (rhs.type === "identifier-list") {1439 aliases = rhs.value.map(id => id.value);1440 } else { // rhs.type === identifier1441 aliases = [ rhs.value ];1442 }1443 // OK now actually check the aliases...1444 var alias;1445 if (exposed_in(exposure_set(this, this.exposureSet)) && 'document' in self) {1446 for (alias of aliases) {1447 assert_true(alias in self, alias + " should exist");1448 assert_equals(self[alias], this.get_interface_object(), "self." + alias + " should be the same value as self." + this.get_qualified_name());1449 var desc = Object.getOwnPropertyDescriptor(self, alias);1450 assert_equals(desc.value, this.get_interface_object(), "wrong value in " + alias + " property descriptor");1451 assert_true(desc.writable, alias + " should be writable");1452 assert_false(desc.enumerable, alias + " should not be enumerable");1453 assert_true(desc.configurable, alias + " should be configurable");1454 assert_false('get' in desc, alias + " should not have a getter");1455 assert_false('set' in desc, alias + " should not have a setter");1456 }1457 } else {1458 for (alias of aliases) {1459 assert_false(alias in self, alias + " should not exist");1460 }1461 }1462 }.bind(this), this.name + " interface: legacy window alias");1463 }1464 if (this.has_extended_attribute("LegacyFactoryFunction")) {1465 var constructors = this.extAttrs1466 .filter(function(attr) { return attr.name == "LegacyFactoryFunction"; });1467 if (constructors.length !== 1) {1468 throw new IdlHarnessError("Internal error: missing support for multiple LegacyFactoryFunction extended attributes");1469 }1470 var constructor = constructors[0];1471 var min_length = minOverloadLength([constructor]);1472 subsetTestByKey(this.name, test, function()1473 {1474 // This function tests WebIDL as of 2019-01-14.1475 // "for every [LegacyFactoryFunction] extended attribute on an exposed1476 // interface, a corresponding property must exist on the ECMAScript1477 // global object. The name of the property is the1478 // [LegacyFactoryFunction]'s identifier, and its value is an object1479 // called a named constructor, ... . The property has the attributes1480 // { [[Writable]]: true, [[Enumerable]]: false,1481 // [[Configurable]]: true }."1482 var name = constructor.rhs.value;1483 assert_own_property(self, name);1484 var desc = Object.getOwnPropertyDescriptor(self, name);1485 assert_equals(desc.value, self[name], "wrong value in " + name + " property descriptor");1486 assert_true(desc.writable, name + " should be writable");1487 assert_false(desc.enumerable, name + " should not be enumerable");1488 assert_true(desc.configurable, name + " should be configurable");1489 assert_false("get" in desc, name + " should not have a getter");1490 assert_false("set" in desc, name + " should not have a setter");1491 }.bind(this), this.name + " interface: named constructor");1492 subsetTestByKey(this.name, test, function()1493 {1494 // This function tests WebIDL as of 2019-01-14.1495 // "2. Let F be ! CreateBuiltinFunction(realm, steps,1496 // realm.[[Intrinsics]].[[%FunctionPrototype%]])."1497 var name = constructor.rhs.value;1498 var value = self[name];1499 assert_equals(typeof value, "function", "type of value in " + name + " property descriptor");1500 assert_not_equals(value, this.get_interface_object(), "wrong value in " + name + " property descriptor");1501 assert_equals(Object.getPrototypeOf(value), Function.prototype, "wrong value for " + name + "'s prototype");1502 }.bind(this), this.name + " interface: named constructor object");1503 subsetTestByKey(this.name, test, function()1504 {1505 // This function tests WebIDL as of 2019-01-14.1506 // "7. Let proto be the interface prototype object of interface I1507 // in realm.1508 // "8. Perform ! DefinePropertyOrThrow(F, "prototype",1509 // PropertyDescriptor{1510 // [[Value]]: proto, [[Writable]]: false,1511 // [[Enumerable]]: false, [[Configurable]]: false1512 // })."1513 var name = constructor.rhs.value;1514 var expected = this.get_interface_object().prototype;1515 var desc = Object.getOwnPropertyDescriptor(self[name], "prototype");1516 assert_equals(desc.value, expected, "wrong value for " + name + ".prototype");1517 assert_false(desc.writable, "prototype should not be writable");1518 assert_false(desc.enumerable, "prototype should not be enumerable");1519 assert_false(desc.configurable, "prototype should not be configurable");1520 assert_false("get" in desc, "prototype should not have a getter");1521 assert_false("set" in desc, "prototype should not have a setter");1522 }.bind(this), this.name + " interface: named constructor prototype property");1523 subsetTestByKey(this.name, test, function()1524 {1525 // This function tests WebIDL as of 2019-01-14.1526 // "3. Perform ! SetFunctionName(F, id)."1527 var name = constructor.rhs.value;1528 var desc = Object.getOwnPropertyDescriptor(self[name], "name");1529 assert_equals(desc.value, name, "wrong value for " + name + ".name");1530 assert_false(desc.writable, "name should not be writable");1531 assert_false(desc.enumerable, "name should not be enumerable");1532 assert_true(desc.configurable, "name should be configurable");1533 assert_false("get" in desc, "name should not have a getter");1534 assert_false("set" in desc, "name should not have a setter");1535 }.bind(this), this.name + " interface: named constructor name");1536 subsetTestByKey(this.name, test, function()1537 {1538 // This function tests WebIDL as of 2019-01-14.1539 // "4. Initialize S to the effective overload set for constructors1540 // with identifier id on interface I and with argument count 0.1541 // "5. Let length be the length of the shortest argument list of1542 // the entries in S.1543 // "6. Perform ! SetFunctionLength(F, length)."1544 var name = constructor.rhs.value;1545 var desc = Object.getOwnPropertyDescriptor(self[name], "length");1546 assert_equals(desc.value, min_length, "wrong value for " + name + ".length");1547 assert_false(desc.writable, "length should not be writable");1548 assert_false(desc.enumerable, "length should not be enumerable");1549 assert_true(desc.configurable, "length should be configurable");1550 assert_false("get" in desc, "length should not have a getter");1551 assert_false("set" in desc, "length should not have a setter");1552 }.bind(this), this.name + " interface: named constructor length");1553 subsetTestByKey(this.name, test, function()1554 {1555 // This function tests WebIDL as of 2019-01-14.1556 // "1. Let steps be the following steps:1557 // " 1. If NewTarget is undefined, then throw a TypeError."1558 var name = constructor.rhs.value;1559 var args = constructor.arguments.map(function(arg) {1560 return create_suitable_object(arg.idlType);1561 });1562 assert_throws_js(globalOf(self[name]).TypeError, function() {1563 self[name](...args);1564 }.bind(this));1565 }.bind(this), this.name + " interface: named constructor without 'new'");1566 }1567 subsetTestByKey(this.name, test, function()1568 {1569 // This function tests WebIDL as of 2015-01-21.1570 // https://webidl.spec.whatwg.org/#interface-object1571 if (!this.should_have_interface_object()) {1572 return;1573 }1574 this.assert_interface_object_exists();1575 if (this.is_callback()) {1576 assert_false("prototype" in this.get_interface_object(),1577 this.name + ' should not have a "prototype" property');1578 return;1579 }1580 // "An interface object for a non-callback interface must have a1581 // property named “prototype” with attributes { [[Writable]]: false,1582 // [[Enumerable]]: false, [[Configurable]]: false } whose value is an1583 // object called the interface prototype object. This object has1584 // properties that correspond to the regular attributes and regular1585 // operations defined on the interface, and is described in more detail1586 // in section 4.5.4 below."1587 assert_own_property(this.get_interface_object(), "prototype",1588 'interface "' + this.name + '" does not have own property "prototype"');1589 var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), "prototype");1590 assert_false("get" in desc, this.name + ".prototype should not have a getter");1591 assert_false("set" in desc, this.name + ".prototype should not have a setter");1592 assert_false(desc.writable, this.name + ".prototype should not be writable");1593 assert_false(desc.enumerable, this.name + ".prototype should not be enumerable");1594 assert_false(desc.configurable, this.name + ".prototype should not be configurable");1595 // Next, test that the [[Prototype]] of the interface prototype object1596 // is correct. (This is made somewhat difficult by the existence of1597 // [LegacyNoInterfaceObject].)1598 // TODO: Aryeh thinks there's at least other place in this file where1599 // we try to figure out if an interface prototype object is1600 // correct. Consolidate that code.1601 // "The interface prototype object for a given interface A must have an1602 // internal [[Prototype]] property whose value is returned from the1603 // following steps:1604 // "If A is declared with the [Global] extended1605 // attribute, and A supports named properties, then return the named1606 // properties object for A, as defined in §3.6.4 Named properties1607 // object.1608 // "Otherwise, if A is declared to inherit from another interface, then1609 // return the interface prototype object for the inherited interface.1610 // "Otherwise, return %ObjectPrototype%.1611 //1612 // "In the ECMAScript binding, the DOMException type has some additional1613 // requirements:1614 //1615 // "Unlike normal interface types, the interface prototype object1616 // for DOMException must have as its [[Prototype]] the intrinsic1617 // object %ErrorPrototype%."1618 //1619 if (this.name === "Window") {1620 assert_class_string(Object.getPrototypeOf(this.get_interface_object().prototype),1621 'WindowProperties',1622 'Class name for prototype of Window' +1623 '.prototype is not "WindowProperties"');1624 } else {1625 var inherit_interface, inherit_interface_interface_object;1626 if (this.base) {1627 inherit_interface = this.base;1628 var parent = this.array.members[inherit_interface];1629 if (!parent.has_extended_attribute("LegacyNoInterfaceObject")) {1630 parent.assert_interface_object_exists();1631 inherit_interface_interface_object = parent.get_interface_object();1632 }1633 } else if (this.name === "DOMException") {1634 inherit_interface = 'Error';1635 inherit_interface_interface_object = self.Error;1636 } else {1637 inherit_interface = 'Object';1638 inherit_interface_interface_object = self.Object;1639 }1640 if (inherit_interface_interface_object) {1641 assert_not_equals(inherit_interface_interface_object, undefined,1642 'should inherit from ' + inherit_interface + ', but there is no such property');1643 assert_own_property(inherit_interface_interface_object, 'prototype',1644 'should inherit from ' + inherit_interface + ', but that object has no "prototype" property');1645 assert_equals(Object.getPrototypeOf(this.get_interface_object().prototype),1646 inherit_interface_interface_object.prototype,1647 'prototype of ' + this.name + '.prototype is not ' + inherit_interface + '.prototype');1648 } else {1649 // We can't test that we get the correct object, because this is the1650 // only way to get our hands on it. We only test that its class1651 // string, at least, is correct.1652 assert_class_string(Object.getPrototypeOf(this.get_interface_object().prototype),1653 inherit_interface + 'Prototype',1654 'Class name for prototype of ' + this.name +1655 '.prototype is not "' + inherit_interface + 'Prototype"');1656 }1657 }1658 // "The class string of an interface prototype object is the1659 // concatenation of the interface’s qualified identifier and the string1660 // “Prototype”."1661 // Skip these tests for now due to a specification issue about1662 // prototype name.1663 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=282441664 // assert_class_string(this.get_interface_object().prototype, this.get_qualified_name() + "Prototype",1665 // "class string of " + this.name + ".prototype");1666 // String() should end up calling {}.toString if nothing defines a1667 // stringifier.1668 if (!this.has_stringifier()) {1669 // assert_equals(String(this.get_interface_object().prototype), "[object " + this.get_qualified_name() + "Prototype]",1670 // "String(" + this.name + ".prototype)");1671 }1672 }.bind(this), this.name + " interface: existence and properties of interface prototype object");1673 // "If the interface is declared with the [Global]1674 // extended attribute, or the interface is in the set of inherited1675 // interfaces for any other interface that is declared with one of these1676 // attributes, then the interface prototype object must be an immutable1677 // prototype exotic object."1678 // https://webidl.spec.whatwg.org/#interface-prototype-object1679 if (this.is_global()) {1680 this.test_immutable_prototype("interface prototype object", this.get_interface_object().prototype);1681 }1682 subsetTestByKey(this.name, test, function()1683 {1684 if (!this.should_have_interface_object()) {1685 return;1686 }1687 this.assert_interface_object_exists();1688 if (this.is_callback()) {1689 assert_false("prototype" in this.get_interface_object(),1690 this.name + ' should not have a "prototype" property');1691 return;1692 }1693 assert_own_property(this.get_interface_object(), "prototype",1694 'interface "' + this.name + '" does not have own property "prototype"');1695 // "If the [LegacyNoInterfaceObject] extended attribute was not specified1696 // on the interface, then the interface prototype object must also have a1697 // property named “constructor” with attributes { [[Writable]]: true,1698 // [[Enumerable]]: false, [[Configurable]]: true } whose value is a1699 // reference to the interface object for the interface."1700 assert_own_property(this.get_interface_object().prototype, "constructor",1701 this.name + '.prototype does not have own property "constructor"');1702 var desc = Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, "constructor");1703 assert_false("get" in desc, this.name + ".prototype.constructor should not have a getter");1704 assert_false("set" in desc, this.name + ".prototype.constructor should not have a setter");1705 assert_true(desc.writable, this.name + ".prototype.constructor should be writable");1706 assert_false(desc.enumerable, this.name + ".prototype.constructor should not be enumerable");1707 assert_true(desc.configurable, this.name + ".prototype.constructor should be configurable");1708 assert_equals(this.get_interface_object().prototype.constructor, this.get_interface_object(),1709 this.name + '.prototype.constructor is not the same object as ' + this.name);1710 }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property');1711 subsetTestByKey(this.name, test, function()1712 {1713 if (!this.should_have_interface_object()) {1714 return;1715 }1716 this.assert_interface_object_exists();1717 if (this.is_callback()) {1718 assert_false("prototype" in this.get_interface_object(),1719 this.name + ' should not have a "prototype" property');1720 return;1721 }1722 assert_own_property(this.get_interface_object(), "prototype",1723 'interface "' + this.name + '" does not have own property "prototype"');1724 // If the interface has any member declared with the [Unscopable] extended1725 // attribute, then there must be a property on the interface prototype object1726 // whose name is the @@unscopables symbol, which has the attributes1727 // { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true },1728 // and whose value is an object created as follows...1729 var unscopables = this.get_unscopables().map(m => m.name);1730 var proto = this.get_interface_object().prototype;1731 if (unscopables.length != 0) {1732 assert_own_property(1733 proto, Symbol.unscopables,1734 this.name + '.prototype should have an @@unscopables property');1735 var desc = Object.getOwnPropertyDescriptor(proto, Symbol.unscopables);1736 assert_false("get" in desc,1737 this.name + ".prototype[Symbol.unscopables] should not have a getter");1738 assert_false("set" in desc, this.name + ".prototype[Symbol.unscopables] should not have a setter");1739 assert_false(desc.writable, this.name + ".prototype[Symbol.unscopables] should not be writable");1740 assert_false(desc.enumerable, this.name + ".prototype[Symbol.unscopables] should not be enumerable");1741 assert_true(desc.configurable, this.name + ".prototype[Symbol.unscopables] should be configurable");1742 assert_equals(desc.value, proto[Symbol.unscopables],1743 this.name + '.prototype[Symbol.unscopables] should be in the descriptor');1744 assert_equals(typeof desc.value, "object",1745 this.name + '.prototype[Symbol.unscopables] should be an object');1746 assert_equals(Object.getPrototypeOf(desc.value), null,1747 this.name + '.prototype[Symbol.unscopables] should have a null prototype');1748 assert_equals(Object.getOwnPropertySymbols(desc.value).length,1749 0,1750 this.name + '.prototype[Symbol.unscopables] should have the right number of symbol-named properties');1751 // Check that we do not have _extra_ unscopables. Checking that we1752 // have all the ones we should will happen in the per-member tests.1753 var observed = Object.getOwnPropertyNames(desc.value);1754 for (var prop of observed) {1755 assert_not_equals(unscopables.indexOf(prop),1756 -1,1757 this.name + '.prototype[Symbol.unscopables] has unexpected property "' + prop + '"');1758 }1759 } else {1760 assert_equals(Object.getOwnPropertyDescriptor(this.get_interface_object().prototype, Symbol.unscopables),1761 undefined,1762 this.name + '.prototype should not have @@unscopables');1763 }1764 }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s @@unscopables property');1765};1766IdlInterface.prototype.test_immutable_prototype = function(type, obj)1767{1768 if (typeof Object.setPrototypeOf !== "function") {1769 return;1770 }1771 subsetTestByKey(this.name, test, function(t) {1772 var originalValue = Object.getPrototypeOf(obj);1773 var newValue = Object.create(null);1774 t.add_cleanup(function() {1775 try {1776 Object.setPrototypeOf(obj, originalValue);1777 } catch (err) {}1778 });1779 assert_throws_js(TypeError, function() {1780 Object.setPrototypeOf(obj, newValue);1781 });1782 assert_equals(1783 Object.getPrototypeOf(obj),1784 originalValue,1785 "original value not modified"1786 );1787 }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +1788 "of " + type + " - setting to a new value via Object.setPrototypeOf " +1789 "should throw a TypeError");1790 subsetTestByKey(this.name, test, function(t) {1791 var originalValue = Object.getPrototypeOf(obj);1792 var newValue = Object.create(null);1793 t.add_cleanup(function() {1794 let setter = Object.getOwnPropertyDescriptor(1795 Object.prototype, '__proto__'1796 ).set;1797 try {1798 setter.call(obj, originalValue);1799 } catch (err) {}1800 });1801 // We need to find the actual setter for the '__proto__' property, so we1802 // can determine the right global for it. Walk up the prototype chain1803 // looking for that property until we find it.1804 let setter;1805 {1806 let cur = obj;1807 while (cur) {1808 const desc = Object.getOwnPropertyDescriptor(cur, "__proto__");1809 if (desc) {1810 setter = desc.set;1811 break;1812 }1813 cur = Object.getPrototypeOf(cur);1814 }1815 }1816 assert_throws_js(globalOf(setter).TypeError, function() {1817 obj.__proto__ = newValue;1818 });1819 assert_equals(1820 Object.getPrototypeOf(obj),1821 originalValue,1822 "original value not modified"1823 );1824 }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +1825 "of " + type + " - setting to a new value via __proto__ " +1826 "should throw a TypeError");1827 subsetTestByKey(this.name, test, function(t) {1828 var originalValue = Object.getPrototypeOf(obj);1829 var newValue = Object.create(null);1830 t.add_cleanup(function() {1831 try {1832 Reflect.setPrototypeOf(obj, originalValue);1833 } catch (err) {}1834 });1835 assert_false(Reflect.setPrototypeOf(obj, newValue));1836 assert_equals(1837 Object.getPrototypeOf(obj),1838 originalValue,1839 "original value not modified"1840 );1841 }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +1842 "of " + type + " - setting to a new value via Reflect.setPrototypeOf " +1843 "should return false");1844 subsetTestByKey(this.name, test, function() {1845 var originalValue = Object.getPrototypeOf(obj);1846 Object.setPrototypeOf(obj, originalValue);1847 }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +1848 "of " + type + " - setting to its original value via Object.setPrototypeOf " +1849 "should not throw");1850 subsetTestByKey(this.name, test, function() {1851 var originalValue = Object.getPrototypeOf(obj);1852 obj.__proto__ = originalValue;1853 }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +1854 "of " + type + " - setting to its original value via __proto__ " +1855 "should not throw");1856 subsetTestByKey(this.name, test, function() {1857 var originalValue = Object.getPrototypeOf(obj);1858 assert_true(Reflect.setPrototypeOf(obj, originalValue));1859 }.bind(this), this.name + " interface: internal [[SetPrototypeOf]] method " +1860 "of " + type + " - setting to its original value via Reflect.setPrototypeOf " +1861 "should return true");1862};1863IdlInterface.prototype.test_member_const = function(member)1864{1865 if (!this.has_constants()) {1866 throw new IdlHarnessError("Internal error: test_member_const called without any constants");1867 }1868 subsetTestByKey(this.name, test, function()1869 {1870 this.assert_interface_object_exists();1871 // "For each constant defined on an interface A, there must be1872 // a corresponding property on the interface object, if it1873 // exists."1874 assert_own_property(this.get_interface_object(), member.name);1875 // "The value of the property is that which is obtained by1876 // converting the constant’s IDL value to an ECMAScript1877 // value."1878 assert_equals(this.get_interface_object()[member.name], constValue(member.value),1879 "property has wrong value");1880 // "The property has attributes { [[Writable]]: false,1881 // [[Enumerable]]: true, [[Configurable]]: false }."1882 var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), member.name);1883 assert_false("get" in desc, "property should not have a getter");1884 assert_false("set" in desc, "property should not have a setter");1885 assert_false(desc.writable, "property should not be writable");1886 assert_true(desc.enumerable, "property should be enumerable");1887 assert_false(desc.configurable, "property should not be configurable");1888 }.bind(this), this.name + " interface: constant " + member.name + " on interface object");1889 // "In addition, a property with the same characteristics must1890 // exist on the interface prototype object."1891 subsetTestByKey(this.name, test, function()1892 {1893 this.assert_interface_object_exists();1894 if (this.is_callback()) {1895 assert_false("prototype" in this.get_interface_object(),1896 this.name + ' should not have a "prototype" property');1897 return;1898 }1899 assert_own_property(this.get_interface_object(), "prototype",1900 'interface "' + this.name + '" does not have own property "prototype"');1901 assert_own_property(this.get_interface_object().prototype, member.name);1902 assert_equals(this.get_interface_object().prototype[member.name], constValue(member.value),1903 "property has wrong value");1904 var desc = Object.getOwnPropertyDescriptor(this.get_interface_object(), member.name);1905 assert_false("get" in desc, "property should not have a getter");1906 assert_false("set" in desc, "property should not have a setter");1907 assert_false(desc.writable, "property should not be writable");1908 assert_true(desc.enumerable, "property should be enumerable");1909 assert_false(desc.configurable, "property should not be configurable");1910 }.bind(this), this.name + " interface: constant " + member.name + " on interface prototype object");1911};1912IdlInterface.prototype.test_member_attribute = function(member)1913 {1914 if (!shouldRunSubTest(this.name)) {1915 return;1916 }1917 var a_test = subsetTestByKey(this.name, async_test, this.name + " interface: attribute " + member.name);1918 a_test.step(function()1919 {1920 if (!this.should_have_interface_object()) {1921 a_test.done();1922 return;1923 }1924 this.assert_interface_object_exists();1925 assert_own_property(this.get_interface_object(), "prototype",1926 'interface "' + this.name + '" does not have own property "prototype"');1927 if (member.special === "static") {1928 assert_own_property(this.get_interface_object(), member.name,1929 "The interface object must have a property " +1930 format_value(member.name));1931 a_test.done();1932 return;1933 }1934 this.do_member_unscopable_asserts(member);1935 if (this.is_global()) {1936 assert_own_property(self, member.name,1937 "The global object must have a property " +1938 format_value(member.name));1939 assert_false(member.name in this.get_interface_object().prototype,1940 "The prototype object should not have a property " +1941 format_value(member.name));1942 var getter = Object.getOwnPropertyDescriptor(self, member.name).get;1943 assert_equals(typeof(getter), "function",1944 format_value(member.name) + " must have a getter");1945 // Try/catch around the get here, since it can legitimately throw.1946 // If it does, we obviously can't check for equality with direct1947 // invocation of the getter.1948 var gotValue;1949 var propVal;1950 try {1951 propVal = self[member.name];1952 gotValue = true;1953 } catch (e) {1954 gotValue = false;1955 }1956 if (gotValue) {1957 assert_equals(propVal, getter.call(undefined),1958 "Gets on a global should not require an explicit this");1959 }1960 // do_interface_attribute_asserts must be the last thing we do,1961 // since it will call done() on a_test.1962 this.do_interface_attribute_asserts(self, member, a_test);1963 } else {1964 assert_true(member.name in this.get_interface_object().prototype,1965 "The prototype object must have a property " +1966 format_value(member.name));1967 if (!member.has_extended_attribute("LegacyLenientThis")) {1968 if (member.idlType.generic !== "Promise") {1969 // this.get_interface_object() returns a thing in our global1970 assert_throws_js(TypeError, function() {1971 this.get_interface_object().prototype[member.name];1972 }.bind(this), "getting property on prototype object must throw TypeError");1973 // do_interface_attribute_asserts must be the last thing we1974 // do, since it will call done() on a_test.1975 this.do_interface_attribute_asserts(this.get_interface_object().prototype, member, a_test);1976 } else {1977 promise_rejects_js(a_test, TypeError,1978 this.get_interface_object().prototype[member.name])1979 .then(a_test.step_func(function() {1980 // do_interface_attribute_asserts must be the last1981 // thing we do, since it will call done() on a_test.1982 this.do_interface_attribute_asserts(this.get_interface_object().prototype,1983 member, a_test);1984 }.bind(this)));1985 }1986 } else {1987 assert_equals(this.get_interface_object().prototype[member.name], undefined,1988 "getting property on prototype object must return undefined");1989 // do_interface_attribute_asserts must be the last thing we do,1990 // since it will call done() on a_test.1991 this.do_interface_attribute_asserts(this.get_interface_object().prototype, member, a_test);1992 }1993 }1994 }.bind(this));1995};1996IdlInterface.prototype.test_member_operation = function(member)1997{1998 if (!shouldRunSubTest(this.name)) {1999 return;2000 }2001 var a_test = subsetTestByKey(this.name, async_test, this.name + " interface: operation " + member);2002 a_test.step(function()2003 {2004 // This function tests WebIDL as of 2015-12-29.2005 // https://webidl.spec.whatwg.org/#es-operations2006 if (!this.should_have_interface_object()) {2007 a_test.done();2008 return;2009 }2010 this.assert_interface_object_exists();2011 if (this.is_callback()) {2012 assert_false("prototype" in this.get_interface_object(),2013 this.name + ' should not have a "prototype" property');2014 a_test.done();2015 return;2016 }2017 assert_own_property(this.get_interface_object(), "prototype",2018 'interface "' + this.name + '" does not have own property "prototype"');2019 // "For each unique identifier of an exposed operation defined on the2020 // interface, there must exist a corresponding property, unless the2021 // effective overload set for that identifier and operation and with an2022 // argument count of 0 has no entries."2023 // TODO: Consider [Exposed].2024 // "The location of the property is determined as follows:"2025 var memberHolderObject;2026 // "* If the operation is static, then the property exists on the2027 // interface object."2028 if (member.special === "static") {2029 assert_own_property(this.get_interface_object(), member.name,2030 "interface object missing static operation");2031 memberHolderObject = this.get_interface_object();2032 // "* Otherwise, [...] if the interface was declared with the [Global]2033 // extended attribute, then the property exists2034 // on every object that implements the interface."2035 } else if (this.is_global()) {2036 assert_own_property(self, member.name,2037 "global object missing non-static operation");2038 memberHolderObject = self;2039 // "* Otherwise, the property exists solely on the interface’s2040 // interface prototype object."2041 } else {2042 assert_own_property(this.get_interface_object().prototype, member.name,2043 "interface prototype object missing non-static operation");2044 memberHolderObject = this.get_interface_object().prototype;2045 }2046 this.do_member_unscopable_asserts(member);2047 this.do_member_operation_asserts(memberHolderObject, member, a_test);2048 }.bind(this));2049};2050IdlInterface.prototype.do_member_unscopable_asserts = function(member)2051{2052 // Check that if the member is unscopable then it's in the2053 // @@unscopables object properly.2054 if (!member.isUnscopable) {2055 return;2056 }2057 var unscopables = this.get_interface_object().prototype[Symbol.unscopables];2058 var prop = member.name;2059 var propDesc = Object.getOwnPropertyDescriptor(unscopables, prop);2060 assert_equals(typeof propDesc, "object",2061 this.name + '.prototype[Symbol.unscopables].' + prop + ' must exist')2062 assert_false("get" in propDesc,2063 this.name + '.prototype[Symbol.unscopables].' + prop + ' must have no getter');2064 assert_false("set" in propDesc,2065 this.name + '.prototype[Symbol.unscopables].' + prop + ' must have no setter');2066 assert_true(propDesc.writable,2067 this.name + '.prototype[Symbol.unscopables].' + prop + ' must be writable');2068 assert_true(propDesc.enumerable,2069 this.name + '.prototype[Symbol.unscopables].' + prop + ' must be enumerable');2070 assert_true(propDesc.configurable,2071 this.name + '.prototype[Symbol.unscopables].' + prop + ' must be configurable');2072 assert_equals(propDesc.value, true,2073 this.name + '.prototype[Symbol.unscopables].' + prop + ' must have the value `true`');2074};2075IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject, member, a_test)2076{2077 var done = a_test.done.bind(a_test);2078 var operationUnforgeable = member.isUnforgeable;2079 var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);2080 // "The property has attributes { [[Writable]]: B,2081 // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the2082 // operation is unforgeable on the interface, and true otherwise".2083 assert_false("get" in desc, "property should not have a getter");2084 assert_false("set" in desc, "property should not have a setter");2085 assert_equals(desc.writable, !operationUnforgeable,2086 "property should be writable if and only if not unforgeable");2087 assert_true(desc.enumerable, "property should be enumerable");2088 assert_equals(desc.configurable, !operationUnforgeable,2089 "property should be configurable if and only if not unforgeable");2090 // "The value of the property is a Function object whose2091 // behavior is as follows . . ."2092 assert_equals(typeof memberHolderObject[member.name], "function",2093 "property must be a function");2094 const ctors = this.members.filter(function(m) {2095 return m.type == "operation" && m.name == member.name;2096 });2097 assert_equals(2098 memberHolderObject[member.name].length,2099 minOverloadLength(ctors),2100 "property has wrong .length");2101 assert_equals(2102 memberHolderObject[member.name].name,2103 member.name,2104 "property has wrong .name");2105 // Make some suitable arguments2106 var args = member.arguments.map(function(arg) {2107 return create_suitable_object(arg.idlType);2108 });2109 // "Let O be a value determined as follows:2110 // ". . .2111 // "Otherwise, throw a TypeError."2112 // This should be hit if the operation is not static, there is2113 // no [ImplicitThis] attribute, and the this value is null.2114 //2115 // TODO: We currently ignore the [ImplicitThis] case. Except we manually2116 // check for globals, since otherwise we'll invoke window.close(). And we2117 // have to skip this test for anything that on the proto chain of "self",2118 // since that does in fact have implicit-this behavior.2119 if (member.special !== "static") {2120 var cb;2121 if (!this.is_global() &&2122 memberHolderObject[member.name] != self[member.name])2123 {2124 cb = awaitNCallbacks(2, done);2125 throwOrReject(a_test, member, memberHolderObject[member.name], null, args,2126 "calling operation with this = null didn't throw TypeError", cb);2127 } else {2128 cb = awaitNCallbacks(1, done);2129 }2130 // ". . . If O is not null and is also not a platform object2131 // that implements interface I, throw a TypeError."2132 //2133 // TODO: Test a platform object that implements some other2134 // interface. (Have to be sure to get inheritance right.)2135 throwOrReject(a_test, member, memberHolderObject[member.name], {}, args,2136 "calling operation with this = {} didn't throw TypeError", cb);2137 } else {2138 done();2139 }2140}2141IdlInterface.prototype.test_to_json_operation = function(desc, memberHolderObject, member) {2142 var instanceName = memberHolderObject && memberHolderObject.constructor.name2143 || member.name + " object";2144 if (member.has_extended_attribute("Default")) {2145 subsetTestByKey(this.name, test, function() {2146 var map = this.default_to_json_operation();2147 var json = memberHolderObject.toJSON();2148 map.forEach(function(type, k) {2149 assert_true(k in json, "property " + JSON.stringify(k) + " should be present in the output of " + this.name + ".prototype.toJSON()");2150 var descriptor = Object.getOwnPropertyDescriptor(json, k);2151 assert_true(descriptor.writable, "property " + k + " should be writable");2152 assert_true(descriptor.configurable, "property " + k + " should be configurable");2153 assert_true(descriptor.enumerable, "property " + k + " should be enumerable");2154 this.array.assert_type_is(json[k], type);2155 delete json[k];2156 }, this);2157 }.bind(this), this.name + " interface: default toJSON operation on " + desc);2158 } else {2159 subsetTestByKey(this.name, test, function() {2160 assert_true(this.array.is_json_type(member.idlType), JSON.stringify(member.idlType) + " is not an appropriate return value for the toJSON operation of " + instanceName);2161 this.array.assert_type_is(memberHolderObject.toJSON(), member.idlType);2162 }.bind(this), this.name + " interface: toJSON operation on " + desc);2163 }2164};2165IdlInterface.prototype.test_member_iterable = function(member)2166{2167 subsetTestByKey(this.name, test, function()2168 {2169 var isPairIterator = member.idlType.length === 2;2170 var proto = this.get_interface_object().prototype;2171 var iteratorDesc = Object.getOwnPropertyDescriptor(proto, Symbol.iterator);2172 assert_true(iteratorDesc.writable, "@@iterator property should be writable");2173 assert_true(iteratorDesc.configurable, "@@iterator property should be configurable");2174 assert_false(iteratorDesc.enumerable, "@@iterator property should not be enumerable");2175 assert_equals(typeof iteratorDesc.value, "function", "@@iterator property should be a function");2176 assert_equals(iteratorDesc.value.length, 0, "@@iterator function object length should be 0");2177 assert_equals(iteratorDesc.value.name, isPairIterator ? "entries" : "values", "@@iterator function object should have the right name");2178 if (isPairIterator) {2179 assert_equals(proto["entries"], proto[Symbol.iterator], "entries method should be the same as @@iterator method");2180 [2181 ["entries", 0],2182 ["keys", 0],2183 ["values", 0],2184 ["forEach", 1]2185 ].forEach(([property, length]) => {2186 var desc = Object.getOwnPropertyDescriptor(proto, property);2187 assert_equals(typeof desc.value, "function", property + " property should be a function");2188 assert_equals(desc.value.length, length, property + " function object should have the right length");2189 assert_equals(desc.value.name, property, property + " function object should have the right name");2190 });2191 } else {2192 assert_equals(proto[Symbol.iterator], Array.prototype[Symbol.iterator], "@@iterator method should be the same as Array prototype's");2193 ["entries", "keys", "values", "forEach", Symbol.iterator].forEach(property => {2194 var propertyName = property === Symbol.iterator ? "@@iterator" : property;2195 assert_equals(proto[property], Array.prototype[property], propertyName + " method should be the same as Array prototype's");2196 });2197 }2198 }.bind(this), this.name + " interface: iterable<" + member.idlType.map(function(t) { return t.idlType; }).join(", ") + ">");2199};2200IdlInterface.prototype.test_member_maplike = function(member) {2201 subsetTestByKey(this.name, test, () => {2202 const proto = this.get_interface_object().prototype;2203 const methods = [2204 ["entries", 0],2205 ["keys", 0],2206 ["values", 0],2207 ["forEach", 1],2208 ["get", 1],2209 ["has", 1]2210 ];2211 if (!member.readonly) {2212 methods.push(2213 ["set", 2],2214 ["delete", 1],2215 ["clear", 1]2216 );2217 }2218 for (const [name, length] of methods) {2219 const desc = Object.getOwnPropertyDescriptor(proto, name);2220 assert_equals(typeof desc.value, "function", `${name} should be a function`);2221 assert_equals(desc.enumerable, false, `${name} enumerable`);2222 assert_equals(desc.configurable, true, `${name} configurable`);2223 assert_equals(desc.writable, true, `${name} writable`);2224 assert_equals(desc.value.length, length, `${name} function object length should be ${length}`);2225 assert_equals(desc.value.name, name, `${name} function object should have the right name`);2226 }2227 const iteratorDesc = Object.getOwnPropertyDescriptor(proto, Symbol.iterator);2228 assert_equals(iteratorDesc.value, proto.entries, `@@iterator should equal entries`);2229 assert_equals(iteratorDesc.enumerable, false, `@@iterator enumerable`);2230 assert_equals(iteratorDesc.configurable, true, `@@iterator configurable`);2231 assert_equals(iteratorDesc.writable, true, `@@iterator writable`);2232 const sizeDesc = Object.getOwnPropertyDescriptor(proto, "size");2233 assert_equals(typeof sizeDesc.get, "function", `size getter should be a function`);2234 assert_equals(sizeDesc.set, undefined, `size should not have a setter`);2235 assert_equals(sizeDesc.enumerable, false, `size enumerable`);2236 assert_equals(sizeDesc.configurable, true, `size configurable`);2237 assert_equals(sizeDesc.get.length, 0, `size getter length should have the right length`);2238 assert_equals(sizeDesc.get.name, "get size", `size getter have the right name`);2239 }, `${this.name} interface: maplike<${member.idlType.map(t => t.idlType).join(", ")}>`);2240};2241IdlInterface.prototype.test_member_setlike = function(member) {2242 subsetTestByKey(this.name, test, () => {2243 const proto = this.get_interface_object().prototype;2244 const methods = [2245 ["entries", 0],2246 ["keys", 0],2247 ["values", 0],2248 ["forEach", 1],2249 ["has", 1]2250 ];2251 if (!member.readonly) {2252 methods.push(2253 ["add", 1],2254 ["delete", 1],2255 ["clear", 1]2256 );2257 }2258 for (const [name, length] of methods) {2259 const desc = Object.getOwnPropertyDescriptor(proto, name);2260 assert_equals(typeof desc.value, "function", `${name} should be a function`);2261 assert_equals(desc.enumerable, false, `${name} enumerable`);2262 assert_equals(desc.configurable, true, `${name} configurable`);2263 assert_equals(desc.writable, true, `${name} writable`);2264 assert_equals(desc.value.length, length, `${name} function object length should be ${length}`);2265 assert_equals(desc.value.name, name, `${name} function object should have the right name`);2266 }2267 const iteratorDesc = Object.getOwnPropertyDescriptor(proto, Symbol.iterator);2268 assert_equals(iteratorDesc.value, proto.values, `@@iterator should equal values`);2269 assert_equals(iteratorDesc.enumerable, false, `@@iterator enumerable`);2270 assert_equals(iteratorDesc.configurable, true, `@@iterator configurable`);2271 assert_equals(iteratorDesc.writable, true, `@@iterator writable`);2272 const sizeDesc = Object.getOwnPropertyDescriptor(proto, "size");2273 assert_equals(typeof sizeDesc.get, "function", `size getter should be a function`);2274 assert_equals(sizeDesc.set, undefined, `size should not have a setter`);2275 assert_equals(sizeDesc.enumerable, false, `size enumerable`);2276 assert_equals(sizeDesc.configurable, true, `size configurable`);2277 assert_equals(sizeDesc.get.length, 0, `size getter length should have the right length`);2278 assert_equals(sizeDesc.get.name, "size", `size getter have the right name`);2279 }, `${this.name} interface: setlike<${member.idlType.map(t => t.idlType).join(", ")}>`);2280};2281IdlInterface.prototype.test_member_async_iterable = function(member)2282{2283 subsetTestByKey(this.name, test, function()2284 {2285 var isPairIterator = member.idlType.length === 2;2286 var proto = this.get_interface_object().prototype;2287 var iteratorDesc = Object.getOwnPropertyDescriptor(proto, Symbol.asyncIterator);2288 assert_true(iteratorDesc.writable, "@@asyncIterator property should be writable");2289 assert_true(iteratorDesc.configurable, "@@asyncIterator property should be configurable");2290 assert_false(iteratorDesc.enumerable, "@@asyncIterator property should not be enumerable");2291 assert_equals(typeof iteratorDesc.value, "function", "@@asyncIterator property should be a function");2292 assert_equals(iteratorDesc.value.length, 0, "@@asyncIterator function object length should be 0");2293 assert_equals(iteratorDesc.value.name, isPairIterator ? "entries" : "values", "@@asyncIterator function object should have the right name");2294 if (isPairIterator) {2295 assert_equals(proto["entries"], proto[Symbol.asyncIterator], "entries method should be the same as @@asyncIterator method");2296 ["entries", "keys", "values"].forEach(property => {2297 var desc = Object.getOwnPropertyDescriptor(proto, property);2298 assert_equals(typeof desc.value, "function", property + " property should be a function");2299 assert_equals(desc.value.length, 0, property + " function object length should be 0");2300 assert_equals(desc.value.name, property, property + " function object should have the right name");2301 });2302 } else {2303 assert_equals(proto["values"], proto[Symbol.asyncIterator], "values method should be the same as @@asyncIterator method");2304 assert_false("entries" in proto, "should not have an entries method");2305 assert_false("keys" in proto, "should not have a keys method");2306 }2307 }.bind(this), this.name + " interface: async iterable<" + member.idlType.map(function(t) { return t.idlType; }).join(", ") + ">");2308};2309IdlInterface.prototype.test_member_stringifier = function(member)2310{2311 subsetTestByKey(this.name, test, function()2312 {2313 if (!this.should_have_interface_object()) {2314 return;2315 }2316 this.assert_interface_object_exists();2317 if (this.is_callback()) {2318 assert_false("prototype" in this.get_interface_object(),2319 this.name + ' should not have a "prototype" property');2320 return;2321 }2322 assert_own_property(this.get_interface_object(), "prototype",2323 'interface "' + this.name + '" does not have own property "prototype"');2324 // ". . . the property exists on the interface prototype object."2325 var interfacePrototypeObject = this.get_interface_object().prototype;2326 assert_own_property(interfacePrototypeObject, "toString",2327 "interface prototype object missing non-static operation");2328 var stringifierUnforgeable = member.isUnforgeable;2329 var desc = Object.getOwnPropertyDescriptor(interfacePrototypeObject, "toString");2330 // "The property has attributes { [[Writable]]: B,2331 // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the2332 // stringifier is unforgeable on the interface, and true otherwise."2333 assert_false("get" in desc, "property should not have a getter");2334 assert_false("set" in desc, "property should not have a setter");2335 assert_equals(desc.writable, !stringifierUnforgeable,2336 "property should be writable if and only if not unforgeable");2337 assert_true(desc.enumerable, "property should be enumerable");2338 assert_equals(desc.configurable, !stringifierUnforgeable,2339 "property should be configurable if and only if not unforgeable");2340 // "The value of the property is a Function object, which behaves as2341 // follows . . ."2342 assert_equals(typeof interfacePrototypeObject.toString, "function",2343 "property must be a function");2344 // "The value of the Function object’s “length” property is the Number2345 // value 0."2346 assert_equals(interfacePrototypeObject.toString.length, 0,2347 "property has wrong .length");2348 // "Let O be the result of calling ToObject on the this value."2349 assert_throws_js(globalOf(interfacePrototypeObject.toString).TypeError, function() {2350 interfacePrototypeObject.toString.apply(null, []);2351 }, "calling stringifier with this = null didn't throw TypeError");2352 // "If O is not an object that implements the interface on which the2353 // stringifier was declared, then throw a TypeError."2354 //2355 // TODO: Test a platform object that implements some other2356 // interface. (Have to be sure to get inheritance right.)2357 assert_throws_js(globalOf(interfacePrototypeObject.toString).TypeError, function() {2358 interfacePrototypeObject.toString.apply({}, []);2359 }, "calling stringifier with this = {} didn't throw TypeError");2360 }.bind(this), this.name + " interface: stringifier");2361};2362IdlInterface.prototype.test_members = function()2363{2364 for (var i = 0; i < this.members.length; i++)2365 {2366 var member = this.members[i];2367 if (member.untested) {2368 continue;2369 }2370 if (!exposed_in(exposure_set(member, this.exposureSet))) {2371 subsetTestByKey(this.name, test, function() {2372 // It's not exposed, so we shouldn't find it anywhere.2373 assert_false(member.name in this.get_interface_object(),2374 "The interface object must not have a property " +2375 format_value(member.name));2376 assert_false(member.name in this.get_interface_object().prototype,2377 "The prototype object must not have a property " +2378 format_value(member.name));2379 }.bind(this), this.name + " interface: member " + member.name);2380 continue;2381 }2382 switch (member.type) {2383 case "const":2384 this.test_member_const(member);2385 break;2386 case "attribute":2387 // For unforgeable attributes, we do the checks in2388 // test_interface_of instead.2389 if (!member.isUnforgeable)2390 {2391 this.test_member_attribute(member);2392 }2393 if (member.special === "stringifier") {2394 this.test_member_stringifier(member);2395 }2396 break;2397 case "operation":2398 // TODO: Need to correctly handle multiple operations with the same2399 // identifier.2400 // For unforgeable operations, we do the checks in2401 // test_interface_of instead.2402 if (member.name) {2403 if (!member.isUnforgeable)2404 {2405 this.test_member_operation(member);2406 }2407 } else if (member.special === "stringifier") {2408 this.test_member_stringifier(member);2409 }2410 break;2411 case "iterable":2412 if (member.async) {2413 this.test_member_async_iterable(member);2414 } else {2415 this.test_member_iterable(member);2416 }2417 break;2418 case "maplike":2419 this.test_member_maplike(member);2420 break;2421 case "setlike":2422 this.test_member_setlike(member);2423 break;2424 default:2425 // TODO: check more member types.2426 break;2427 }2428 }2429};2430IdlInterface.prototype.test_object = function(desc)2431{2432 var obj, exception = null;2433 try2434 {2435 obj = eval(desc);2436 }2437 catch(e)2438 {2439 exception = e;2440 }2441 var expected_typeof;2442 if (this.name == "HTMLAllCollection")2443 {2444 // Result of [[IsHTMLDDA]] slot2445 expected_typeof = "undefined";2446 }2447 else2448 {2449 expected_typeof = "object";2450 }2451 this.test_primary_interface_of(desc, obj, exception, expected_typeof);2452 var current_interface = this;2453 while (current_interface)2454 {2455 if (!(current_interface.name in this.array.members))2456 {2457 throw new IdlHarnessError("Interface " + current_interface.name + " not found (inherited by " + this.name + ")");2458 }2459 if (current_interface.prevent_multiple_testing && current_interface.already_tested)2460 {2461 return;2462 }2463 current_interface.test_interface_of(desc, obj, exception, expected_typeof);2464 current_interface = this.array.members[current_interface.base];2465 }2466};2467IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception, expected_typeof)2468{2469 // Only the object itself, not its members, are tested here, so if the2470 // interface is untested, there is nothing to do.2471 if (this.untested)2472 {2473 return;2474 }2475 // "The internal [[SetPrototypeOf]] method of every platform object that2476 // implements an interface with the [Global] extended2477 // attribute must execute the same algorithm as is defined for the2478 // [[SetPrototypeOf]] internal method of an immutable prototype exotic2479 // object."2480 // https://webidl.spec.whatwg.org/#platform-object-setprototypeof2481 if (this.is_global())2482 {2483 this.test_immutable_prototype("global platform object", obj);2484 }2485 // We can't easily test that its prototype is correct if there's no2486 // interface object, or the object is from a different global environment2487 // (not instanceof Object). TODO: test in this case that its prototype at2488 // least looks correct, even if we can't test that it's actually correct.2489 if (this.should_have_interface_object()2490 && (typeof obj != expected_typeof || obj instanceof Object))2491 {2492 subsetTestByKey(this.name, test, function()2493 {2494 assert_equals(exception, null, "Unexpected exception when evaluating object");2495 assert_equals(typeof obj, expected_typeof, "wrong typeof object");2496 this.assert_interface_object_exists();2497 assert_own_property(this.get_interface_object(), "prototype",2498 'interface "' + this.name + '" does not have own property "prototype"');2499 // "The value of the internal [[Prototype]] property of the2500 // platform object is the interface prototype object of the primary2501 // interface from the platform object’s associated global2502 // environment."2503 assert_equals(Object.getPrototypeOf(obj),2504 this.get_interface_object().prototype,2505 desc + "'s prototype is not " + this.name + ".prototype");2506 }.bind(this), this.name + " must be primary interface of " + desc);2507 }2508 // "The class string of a platform object that implements one or more2509 // interfaces must be the qualified name of the primary interface of the2510 // platform object."2511 subsetTestByKey(this.name, test, function()2512 {2513 assert_equals(exception, null, "Unexpected exception when evaluating object");2514 assert_equals(typeof obj, expected_typeof, "wrong typeof object");2515 assert_class_string(obj, this.get_qualified_name(), "class string of " + desc);2516 if (!this.has_stringifier())2517 {2518 assert_equals(String(obj), "[object " + this.get_qualified_name() + "]", "String(" + desc + ")");2519 }2520 }.bind(this), "Stringification of " + desc);2521};2522IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof)2523{2524 // TODO: Indexed and named properties, more checks on interface members2525 this.already_tested = true;2526 if (!shouldRunSubTest(this.name)) {2527 return;2528 }2529 for (var i = 0; i < this.members.length; i++)2530 {2531 var member = this.members[i];2532 if (member.untested) {2533 continue;2534 }2535 if (!exposed_in(exposure_set(member, this.exposureSet))) {2536 subsetTestByKey(this.name, test, function() {2537 assert_equals(exception, null, "Unexpected exception when evaluating object");2538 assert_false(member.name in obj);2539 }.bind(this), this.name + " interface: " + desc + ' must not have property "' + member.name + '"');2540 continue;2541 }2542 if (member.type == "attribute" && member.isUnforgeable)2543 {2544 var a_test = subsetTestByKey(this.name, async_test, this.name + " interface: " + desc + ' must have own property "' + member.name + '"');2545 a_test.step(function() {2546 assert_equals(exception, null, "Unexpected exception when evaluating object");2547 assert_equals(typeof obj, expected_typeof, "wrong typeof object");2548 // Call do_interface_attribute_asserts last, since it will call a_test.done()2549 this.do_interface_attribute_asserts(obj, member, a_test);2550 }.bind(this));2551 }2552 else if (member.type == "operation" &&2553 member.name &&2554 member.isUnforgeable)2555 {2556 var a_test = subsetTestByKey(this.name, async_test, this.name + " interface: " + desc + ' must have own property "' + member.name + '"');2557 a_test.step(function()2558 {2559 assert_equals(exception, null, "Unexpected exception when evaluating object");2560 assert_equals(typeof obj, expected_typeof, "wrong typeof object");2561 assert_own_property(obj, member.name,2562 "Doesn't have the unforgeable operation property");2563 this.do_member_operation_asserts(obj, member, a_test);2564 }.bind(this));2565 }2566 else if ((member.type == "const"2567 || member.type == "attribute"2568 || member.type == "operation")2569 && member.name)2570 {2571 subsetTestByKey(this.name, test, function()2572 {2573 assert_equals(exception, null, "Unexpected exception when evaluating object");2574 assert_equals(typeof obj, expected_typeof, "wrong typeof object");2575 if (member.special !== "static") {2576 if (!this.is_global()) {2577 assert_inherits(obj, member.name);2578 } else {2579 assert_own_property(obj, member.name);2580 }2581 if (member.type == "const")2582 {2583 assert_equals(obj[member.name], constValue(member.value));2584 }2585 if (member.type == "attribute")2586 {2587 // Attributes are accessor properties, so they might2588 // legitimately throw an exception rather than returning2589 // anything.2590 var property, thrown = false;2591 try2592 {2593 property = obj[member.name];2594 }2595 catch (e)2596 {2597 thrown = true;2598 }2599 if (!thrown)2600 {2601 if (this.name == "Document" && member.name == "all")2602 {2603 // Result of [[IsHTMLDDA]] slot2604 assert_equals(typeof property, "undefined");2605 }2606 else2607 {2608 this.array.assert_type_is(property, member.idlType);2609 }2610 }2611 }2612 if (member.type == "operation")2613 {2614 assert_equals(typeof obj[member.name], "function");2615 }2616 }2617 }.bind(this), this.name + " interface: " + desc + ' must inherit property "' + member + '" with the proper type');2618 }2619 // TODO: This is wrong if there are multiple operations with the same2620 // identifier.2621 // TODO: Test passing arguments of the wrong type.2622 if (member.type == "operation" && member.name && member.arguments.length)2623 {2624 var description =2625 this.name + " interface: calling " + member + " on " + desc +2626 " with too few arguments must throw TypeError";2627 var a_test = subsetTestByKey(this.name, async_test, description);2628 a_test.step(function()2629 {2630 assert_equals(exception, null, "Unexpected exception when evaluating object");2631 assert_equals(typeof obj, expected_typeof, "wrong typeof object");2632 var fn;2633 if (member.special !== "static") {2634 if (!this.is_global() && !member.isUnforgeable) {2635 assert_inherits(obj, member.name);2636 } else {2637 assert_own_property(obj, member.name);2638 }2639 fn = obj[member.name];2640 }2641 else2642 {2643 assert_own_property(obj.constructor, member.name, "interface object must have static operation as own property");2644 fn = obj.constructor[member.name];2645 }2646 var minLength = minOverloadLength(this.members.filter(function(m) {2647 return m.type == "operation" && m.name == member.name;2648 }));2649 var args = [];2650 var cb = awaitNCallbacks(minLength, a_test.done.bind(a_test));2651 for (var i = 0; i < minLength; i++) {2652 throwOrReject(a_test, member, fn, obj, args, "Called with " + i + " arguments", cb);2653 args.push(create_suitable_object(member.arguments[i].idlType));2654 }2655 if (minLength === 0) {2656 cb();2657 }2658 }.bind(this));2659 }2660 if (member.is_to_json_regular_operation()) {2661 this.test_to_json_operation(desc, obj, member);2662 }2663 }2664};2665IdlInterface.prototype.has_stringifier = function()2666{2667 if (this.name === "DOMException") {2668 // toString is inherited from Error, so don't assume we have the2669 // default stringifer2670 return true;2671 }2672 if (this.members.some(function(member) { return member.special === "stringifier"; })) {2673 return true;2674 }2675 if (this.base &&2676 this.array.members[this.base].has_stringifier()) {2677 return true;2678 }2679 return false;2680};2681IdlInterface.prototype.do_interface_attribute_asserts = function(obj, member, a_test)2682{2683 // This function tests WebIDL as of 2015-01-27.2684 // TODO: Consider [Exposed].2685 // This is called by test_member_attribute() with the prototype as obj if2686 // it is not a global, and the global otherwise, and by test_interface_of()2687 // with the object as obj.2688 var pendingPromises = [];2689 // "The name of the property is the identifier of the attribute."2690 assert_own_property(obj, member.name);2691 // "The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:2692 // true, [[Configurable]]: configurable }, where:2693 // "configurable is false if the attribute was declared with the2694 // [LegacyUnforgeable] extended attribute and true otherwise;2695 // "G is the attribute getter, defined below; and2696 // "S is the attribute setter, also defined below."2697 var desc = Object.getOwnPropertyDescriptor(obj, member.name);2698 assert_false("value" in desc, 'property descriptor should not have a "value" field');2699 assert_false("writable" in desc, 'property descriptor should not have a "writable" field');2700 assert_true(desc.enumerable, "property should be enumerable");2701 if (member.isUnforgeable)2702 {2703 assert_false(desc.configurable, "[LegacyUnforgeable] property must not be configurable");2704 }2705 else2706 {2707 assert_true(desc.configurable, "property must be configurable");2708 }2709 // "The attribute getter is a Function object whose behavior when invoked2710 // is as follows:"2711 assert_equals(typeof desc.get, "function", "getter must be Function");2712 // "If the attribute is a regular attribute, then:"2713 if (member.special !== "static") {2714 // "If O is not a platform object that implements I, then:2715 // "If the attribute was specified with the [LegacyLenientThis] extended2716 // attribute, then return undefined.2717 // "Otherwise, throw a TypeError."2718 if (!member.has_extended_attribute("LegacyLenientThis")) {2719 if (member.idlType.generic !== "Promise") {2720 assert_throws_js(globalOf(desc.get).TypeError, function() {2721 desc.get.call({});2722 }.bind(this), "calling getter on wrong object type must throw TypeError");2723 } else {2724 pendingPromises.push(2725 promise_rejects_js(a_test, TypeError, desc.get.call({}),2726 "calling getter on wrong object type must reject the return promise with TypeError"));2727 }2728 } else {2729 assert_equals(desc.get.call({}), undefined,2730 "calling getter on wrong object type must return undefined");2731 }2732 }2733 // "The value of the Function object’s “length” property is the Number2734 // value 0."2735 assert_equals(desc.get.length, 0, "getter length must be 0");2736 // "Let name be the string "get " prepended to attribute’s identifier."2737 // "Perform ! SetFunctionName(F, name)."2738 assert_equals(desc.get.name, "get " + member.name,2739 "getter must have the name 'get " + member.name + "'");2740 // TODO: Test calling setter on the interface prototype (should throw2741 // TypeError in most cases).2742 if (member.readonly2743 && !member.has_extended_attribute("LegacyLenientSetter")2744 && !member.has_extended_attribute("PutForwards")2745 && !member.has_extended_attribute("Replaceable"))2746 {2747 // "The attribute setter is undefined if the attribute is declared2748 // readonly and has neither a [PutForwards] nor a [Replaceable]2749 // extended attribute declared on it."2750 assert_equals(desc.set, undefined, "setter must be undefined for readonly attributes");2751 }2752 else2753 {2754 // "Otherwise, it is a Function object whose behavior when2755 // invoked is as follows:"2756 assert_equals(typeof desc.set, "function", "setter must be function for PutForwards, Replaceable, or non-readonly attributes");2757 // "If the attribute is a regular attribute, then:"2758 if (member.special !== "static") {2759 // "If /validThis/ is false and the attribute was not specified2760 // with the [LegacyLenientThis] extended attribute, then throw a2761 // TypeError."2762 // "If the attribute is declared with a [Replaceable] extended2763 // attribute, then: ..."2764 // "If validThis is false, then return."2765 if (!member.has_extended_attribute("LegacyLenientThis")) {2766 assert_throws_js(globalOf(desc.set).TypeError, function() {2767 desc.set.call({});2768 }.bind(this), "calling setter on wrong object type must throw TypeError");2769 } else {2770 assert_equals(desc.set.call({}), undefined,2771 "calling setter on wrong object type must return undefined");2772 }2773 }2774 // "The value of the Function object’s “length” property is the Number2775 // value 1."2776 assert_equals(desc.set.length, 1, "setter length must be 1");2777 // "Let name be the string "set " prepended to id."2778 // "Perform ! SetFunctionName(F, name)."2779 assert_equals(desc.set.name, "set " + member.name,2780 "The attribute setter must have the name 'set " + member.name + "'");2781 }2782 Promise.all(pendingPromises).then(a_test.done.bind(a_test));2783}2784/// IdlInterfaceMember ///2785function IdlInterfaceMember(obj)2786{2787 /**2788 * obj is an object produced by the WebIDLParser.js "ifMember" production.2789 * We just forward all properties to this object without modification,2790 * except for special extAttrs handling.2791 */2792 for (var k in obj.toJSON())2793 {2794 this[k] = obj[k];2795 }2796 if (!("extAttrs" in this))2797 {2798 this.extAttrs = [];2799 }2800 this.isUnforgeable = this.has_extended_attribute("LegacyUnforgeable");2801 this.isUnscopable = this.has_extended_attribute("Unscopable");2802}2803IdlInterfaceMember.prototype = Object.create(IdlObject.prototype);2804IdlInterfaceMember.prototype.toJSON = function() {2805 return this;2806};2807IdlInterfaceMember.prototype.is_to_json_regular_operation = function() {2808 return this.type == "operation" && this.special !== "static" && this.name == "toJSON";2809};2810IdlInterfaceMember.prototype.toString = function() {2811 function formatType(type) {2812 var result;2813 if (type.generic) {2814 result = type.generic + "<" + type.idlType.map(formatType).join(", ") + ">";2815 } else if (type.union) {2816 result = "(" + type.subtype.map(formatType).join(" or ") + ")";2817 } else {2818 result = type.idlType;2819 }2820 if (type.nullable) {2821 result += "?"2822 }2823 return result;2824 }2825 if (this.type === "operation") {2826 var args = this.arguments.map(function(m) {2827 return [2828 m.optional ? "optional " : "",2829 formatType(m.idlType),2830 m.variadic ? "..." : "",2831 ].join("");2832 }).join(", ");2833 return this.name + "(" + args + ")";2834 }2835 return this.name;2836}2837/// Internal helper functions ///2838function create_suitable_object(type)2839{2840 /**2841 * type is an object produced by the WebIDLParser.js "type" production. We2842 * return a JavaScript value that matches the type, if we can figure out2843 * how.2844 */2845 if (type.nullable)2846 {2847 return null;2848 }2849 switch (type.idlType)2850 {2851 case "any":2852 case "boolean":2853 return true;2854 case "byte": case "octet": case "short": case "unsigned short":2855 case "long": case "unsigned long": case "long long":2856 case "unsigned long long": case "float": case "double":2857 case "unrestricted float": case "unrestricted double":2858 return 7;2859 case "DOMString":2860 case "ByteString":2861 case "USVString":2862 return "foo";2863 case "object":2864 return {a: "b"};2865 case "Node":2866 return document.createTextNode("abc");2867 }2868 return null;2869}2870/// IdlEnum ///2871// Used for IdlArray.prototype.assert_type_is2872function IdlEnum(obj)2873{2874 /**2875 * obj is an object produced by the WebIDLParser.js "dictionary"2876 * production.2877 */2878 /** Self-explanatory. */2879 this.name = obj.name;2880 /** An array of values produced by the "enum" production. */2881 this.values = obj.values;2882}2883IdlEnum.prototype = Object.create(IdlObject.prototype);2884/// IdlCallback ///2885// Used for IdlArray.prototype.assert_type_is2886function IdlCallback(obj)2887{2888 /**2889 * obj is an object produced by the WebIDLParser.js "callback"2890 * production.2891 */2892 /** Self-explanatory. */2893 this.name = obj.name;2894 /** Arguments for the callback. */2895 this.arguments = obj.arguments;2896}2897IdlCallback.prototype = Object.create(IdlObject.prototype);2898/// IdlTypedef ///2899// Used for IdlArray.prototype.assert_type_is2900function IdlTypedef(obj)2901{2902 /**2903 * obj is an object produced by the WebIDLParser.js "typedef"2904 * production.2905 */2906 /** Self-explanatory. */2907 this.name = obj.name;2908 /** The idlType that we are supposed to be typedeffing to. */2909 this.idlType = obj.idlType;2910}2911IdlTypedef.prototype = Object.create(IdlObject.prototype);2912/// IdlNamespace ///2913function IdlNamespace(obj)2914{2915 this.name = obj.name;2916 this.extAttrs = obj.extAttrs;2917 this.untested = obj.untested;2918 /** A back-reference to our IdlArray. */2919 this.array = obj.array;2920 /** An array of IdlInterfaceMembers. */2921 this.members = obj.members.map(m => new IdlInterfaceMember(m));2922}2923IdlNamespace.prototype = Object.create(IdlObject.prototype);2924IdlNamespace.prototype.do_member_operation_asserts = function (memberHolderObject, member, a_test)2925{2926 var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);2927 assert_false("get" in desc, "property should not have a getter");2928 assert_false("set" in desc, "property should not have a setter");2929 assert_equals(2930 desc.writable,2931 !member.isUnforgeable,2932 "property should be writable if and only if not unforgeable");2933 assert_true(desc.enumerable, "property should be enumerable");2934 assert_equals(2935 desc.configurable,2936 !member.isUnforgeable,2937 "property should be configurable if and only if not unforgeable");2938 assert_equals(2939 typeof memberHolderObject[member.name],2940 "function",2941 "property must be a function");2942 assert_equals(2943 memberHolderObject[member.name].length,2944 minOverloadLength(this.members.filter(function(m) {2945 return m.type == "operation" && m.name == member.name;2946 })),2947 "operation has wrong .length");2948 a_test.done();2949}2950IdlNamespace.prototype.test_member_operation = function(member)2951{2952 if (!shouldRunSubTest(this.name)) {2953 return;2954 }2955 var a_test = subsetTestByKey(2956 this.name,2957 async_test,2958 this.name + ' namespace: operation ' + member);2959 a_test.step(function() {2960 assert_own_property(2961 self[this.name],2962 member.name,2963 'namespace object missing operation ' + format_value(member.name));2964 this.do_member_operation_asserts(self[this.name], member, a_test);2965 }.bind(this));2966};2967IdlNamespace.prototype.test_member_attribute = function (member)2968{2969 if (!shouldRunSubTest(this.name)) {2970 return;2971 }2972 var a_test = subsetTestByKey(2973 this.name,2974 async_test,2975 this.name + ' namespace: attribute ' + member.name);2976 a_test.step(function()2977 {2978 assert_own_property(2979 self[this.name],2980 member.name,2981 this.name + ' does not have property ' + format_value(member.name));2982 var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);2983 assert_equals(desc.set, undefined, "setter must be undefined for namespace members");2984 a_test.done();2985 }.bind(this));2986};2987IdlNamespace.prototype.test_self = function ()2988{2989 /**2990 * TODO(lukebjerring): Assert:2991 * - "Note that unlike interfaces or dictionaries, namespaces do not create types."2992 */2993 subsetTestByKey(this.name, test, () => {2994 assert_true(this.extAttrs.every(o => o.name === "Exposed" || o.name === "SecureContext"),2995 "Only the [Exposed] and [SecureContext] extended attributes are applicable to namespaces");2996 assert_true(this.has_extended_attribute("Exposed"),2997 "Namespaces must be annotated with the [Exposed] extended attribute");2998 }, `${this.name} namespace: extended attributes`);2999 const namespaceObject = self[this.name];3000 subsetTestByKey(this.name, test, () => {3001 const desc = Object.getOwnPropertyDescriptor(self, this.name);3002 assert_equals(desc.value, namespaceObject, `wrong value for ${this.name} namespace object`);3003 assert_true(desc.writable, "namespace object should be writable");3004 assert_false(desc.enumerable, "namespace object should not be enumerable");3005 assert_true(desc.configurable, "namespace object should be configurable");3006 assert_false("get" in desc, "namespace object should not have a getter");3007 assert_false("set" in desc, "namespace object should not have a setter");3008 }, `${this.name} namespace: property descriptor`);3009 subsetTestByKey(this.name, test, () => {3010 assert_true(Object.isExtensible(namespaceObject));3011 }, `${this.name} namespace: [[Extensible]] is true`);3012 subsetTestByKey(this.name, test, () => {3013 assert_true(namespaceObject instanceof Object);3014 if (this.name === "console") {3015 // https://console.spec.whatwg.org/#console-namespace3016 const namespacePrototype = Object.getPrototypeOf(namespaceObject);3017 assert_equals(Reflect.ownKeys(namespacePrototype).length, 0);3018 assert_equals(Object.getPrototypeOf(namespacePrototype), Object.prototype);3019 } else {3020 assert_equals(Object.getPrototypeOf(namespaceObject), Object.prototype);3021 }3022 }, `${this.name} namespace: [[Prototype]] is Object.prototype`);3023 subsetTestByKey(this.name, test, () => {3024 assert_equals(typeof namespaceObject, "object");3025 }, `${this.name} namespace: typeof is "object"`);3026 subsetTestByKey(this.name, test, () => {3027 assert_equals(3028 Object.getOwnPropertyDescriptor(namespaceObject, "length"),3029 undefined,3030 "length property must be undefined"3031 );3032 }, `${this.name} namespace: has no length property`);3033 subsetTestByKey(this.name, test, () => {3034 assert_equals(3035 Object.getOwnPropertyDescriptor(namespaceObject, "name"),3036 undefined,3037 "name property must be undefined"3038 );3039 }, `${this.name} namespace: has no name property`);3040};3041IdlNamespace.prototype.test = function ()3042{3043 if (!this.untested) {3044 this.test_self();3045 }3046 for (const v of Object.values(this.members)) {3047 switch (v.type) {3048 case 'operation':3049 this.test_member_operation(v);3050 break;3051 case 'attribute':3052 this.test_member_attribute(v);3053 break;3054 default:3055 throw 'Invalid namespace member ' + v.name + ': ' + v.type + ' not supported';3056 }3057 };3058};3059}());3060/**3061 * idl_test is a promise_test wrapper that handles the fetching of the IDL,3062 * avoiding repetitive boilerplate.3063 *3064 * @param {String[]} srcs Spec name(s) for source idl files (fetched from3065 * /interfaces/{name}.idl).3066 * @param {String[]} deps Spec name(s) for dependency idl files (fetched3067 * from /interfaces/{name}.idl). Order is important - dependencies from3068 * each source will only be included if they're already know to be a3069 * dependency (i.e. have already been seen).3070 * @param {Function} setup_func Function for extra setup of the idl_array, such3071 * as adding objects. Do not call idl_array.test() in the setup; it is3072 * called by this function (idl_test).3073 */3074function idl_test(srcs, deps, idl_setup_func) {3075 return promise_test(function (t) {3076 var idl_array = new IdlArray();3077 var setup_error = null;3078 const validationIgnored = [3079 "constructor-member",3080 "dict-arg-default",3081 "require-exposed"3082 ];3083 return Promise.all(3084 srcs.concat(deps).map(fetch_spec))3085 .then(function(results) {3086 const astArray = results.map(result =>3087 WebIDL2.parse(result.idl, { sourceName: result.spec })3088 );3089 test(() => {3090 const validations = WebIDL2.validate(astArray)3091 .filter(v => !validationIgnored.includes(v.ruleName));3092 if (validations.length) {3093 const message = validations.map(v => v.message).join("\n\n");3094 throw new Error(message);3095 }3096 }, "idl_test validation");3097 for (var i = 0; i < srcs.length; i++) {3098 idl_array.internal_add_idls(astArray[i]);3099 }3100 for (var i = srcs.length; i < srcs.length + deps.length; i++) {3101 idl_array.internal_add_dependency_idls(astArray[i]);3102 }3103 })3104 .then(function() {3105 if (idl_setup_func) {3106 return idl_setup_func(idl_array, t);3107 }3108 })3109 .catch(function(e) { setup_error = e || 'IDL setup failed.'; })3110 .then(function () {3111 var error = setup_error;3112 try {3113 idl_array.test(); // Test what we can.3114 } catch (e) {3115 // If testing fails hard here, the original setup error3116 // is more likely to be the real cause.3117 error = error || e;3118 }3119 if (error) {3120 throw error;3121 }3122 });3123 }, 'idl_test setup');3124}3125/**3126 * fetch_spec is a shorthand for a Promise that fetches the spec's content.3127 */3128function fetch_spec(spec) {3129 var url = '/interfaces/' + spec + '.idl';3130 return fetch(url).then(function (r) {3131 if (!r.ok) {3132 throw new IdlHarnessError("Error fetching " + url + ".");3133 }3134 return r.text();3135 }).then(idl => ({ spec, idl }));3136}...

Full Screen

Full Screen

main.component.ts

Source:main.component.ts Github

copy

Full Screen

1import { Component, OnInit } from '@angular/core';2import { FormBuilder, FormGroup, Validators } from '@angular/forms';3import { ToastrService } from 'ngx-toastr';4import { IMain } from 'src/app/interface/main.interface';5import { MainServiceService } from 'src/app/service/main-service.service';6@Component({7 selector: 'app-main',8 templateUrl: './main.component.html',9 styleUrls: ['./main.component.scss']10})11export class MainComponent implements OnInit {12 AdvertisementForm: FormGroup;13 EditForm: FormGroup;14 getTitle:string;15 titleDetails:string;16 descriptionDetails:string;17 dateDetails:string;18 showModalAdd: boolean = false;19 showModalEdit: boolean = false;20 showDetails:boolean = false;21 showSearch:boolean = true22 checkAds:boolean = true23 myData:any;24 searchArray:object[];25 setSimilarAnnouncement:string[]26 date: Date = new Date();27 id: number;28 constructor(29 private FormBuilder: FormBuilder,30 private mainService: MainServiceService,31 private toastr: ToastrService32 ) { }33 ngOnInit(): void {34 this.getData()35 this.initFormAdd()36 this.initEditForm()37 }38 getData(): void {39 this.mainService.get().subscribe(data => {40 this.myData = data;41 console.log(data);42 43 if(this.myData.length <=0){44 this.checkAds = true45 }46 else{47 this.checkAds = false48 }49 })50 }51 initFormAdd(): void {52 this.AdvertisementForm = this.FormBuilder.group({53 title: [null, Validators.required],54 description: [null, Validators.required]55 })56 }57 initEditForm(): void {58 this.EditForm = this.FormBuilder.group({59 title: [null, Validators.required],60 description: [null, Validators.required]61 })62 }63 addAnnouncement(): void {64 this.showModalAdd = true;65 document.body.style.background = 'rgba(0, 0, 0, 0.05)';66 }67 saveAnnouncment(): void {68 if (this.AdvertisementForm.value.title && this.AdvertisementForm.value.description) {69 let getDate:any = this.date.getDate();70 let getMonth:any = this.date.getMonth();71 let getMinutes:any = this.date.getMinutes();72 if(getDate < 10){73 getDate = '0'+ getDate;74 }75 if(getMonth < 10){76 getMonth = '0'+ getMonth;77 }78 if(getMinutes < 10){79 getMinutes = '0'+ getMinutes;80 }81 else if(getDate >=10){82 getDate;83 }84 else if(getMonth >=10){85 getDate;86 }87 else if(getMinutes >=10){88 getMinutes;89 }90 const item = {91 ...this.AdvertisementForm.value,92 date: `${getDate}.${getMonth}.${this.date.getFullYear()} | ${this.date.getHours()}:${getMinutes}`93 }94 this.mainService.post(item).subscribe(() => {95 this.getData()96 })97 this.AdvertisementForm.reset();98 this.showModalAdd = false;99 this.success('Announcement created');100 document.body.style.background = 'none';101 }102 else {103 this.error('Please , fill all of the fields ');104 }105 }106 editAnnouncement(item): void {107 this.EditForm.patchValue({108 title: item.title,109 description: item.description110 });111 this.showModalEdit = true;112 this.id = item.id;113 document.body.style.background = 'rgba(0, 0, 0, 0.05)';114 }115 saveEdit(): void {116 if (this.EditForm.value.title && this.EditForm.value.description) {117 let getDate:any = this.date.getDate();118 let getMonth:any = this.date.getMonth();119 let getMinutes:any = this.date.getMinutes();120 if(getDate < 10){121 getDate = '0'+ getDate;122 }123 if(getMonth < 10){124 getMonth = '0'+ getMonth;125 }126 if(getMinutes < 10){127 getMinutes = '0'+ getMinutes;128 }129 else if(getDate >=10){130 getDate;131 }132 else if(getMonth >=10){133 getDate;134 }135 else if(getMinutes >=10){136 getMinutes;137 }138 const editItem = {139 ...this.EditForm.value,140 date: `${getDate}.${getMonth}.${this.date.getFullYear()} | ${this.date.getHours()}:${getMinutes}`141 }142 this.mainService.update(editItem, this.id).subscribe(() => {143 this.getData();144 })145 this.showModalEdit = false;146 document.body.style.background = 'none';147 this.success('Successfully edited');148 this.showSearch = true149 this.searchArray = []150 }151 else {152 this.error('Please , fill all of the fields ');153 }154 }155 deleteAnnouncement(id): void {156 this.mainService.delete(id).subscribe(() => {157 this.getData();158 this.success('Successfully deleted');159 })160 this.showSearch = true161 this.searchArray = []162 }163 infoAnnouncement(item):void{164 this.titleDetails= item.title165 this.descriptionDetails=item.description166 this.dateDetails=item.date167 this.showDetails = true;168 document.body.style.background = 'rgba(0, 0, 0, 0.05)';169 const splitTitle = item.title.split(' ')170 const splitDescription = item.description.split(' ')171 let similarAnnouncement = []172 for (const iteratorTitle of splitTitle) {173 for (const iteratorDesc of splitDescription) {174 this.myData.filter(function(announcement){175 if(announcement.title.includes(iteratorTitle) && announcement.description.includes(iteratorDesc)){176 if(similarAnnouncement.length <3){177 if(!similarAnnouncement.includes(announcement)){178 similarAnnouncement.push(announcement)179 }180 }181 }182 })183 }184 }185 this.setSimilarAnnouncement = similarAnnouncement186 }187 search():void{188 let getValue = document.querySelector('.search') as HTMLInputElement 189 if(this.getTitle){190 const filterArray = this.myData.filter(function(item){191 if(item.title == getValue.value.replace(/\s{2,}/g,"")){192 return {item}193 }194 })195 this.searchArray = filterArray196 if(this.searchArray.length > 0){197 this.showSearch = false198 199 }200 else{201 this.error('There is no such title')202 this.showSearch = true203 }204 }205 else{206 this.warning('Please , enter the title')207 }208 209 210 211 this.getTitle = '' 212 }213 backToAll():void{214 this.showSearch = true215 this.searchArray = []216 }217 closeAdd(): void {218 this.showModalAdd = false;219 this.showModalEdit = false;220 this.showDetails = false;221 document.body.style.background = 'none';222 }223 224 success(messege): void {225 this.toastr.success(messege);226 }227 error(messege): void {228 this.toastr.error(messege);229 }230 warning(messege): void {231 this.toastr.warning(messege);232 }...

Full Screen

Full Screen

getEntries.js

Source:getEntries.js Github

copy

Full Screen

1// @flow2import type { EntriesDescriptor, RemoteObjectId } from './types';3import { getObject } from './remoteObject';4import serialize from './serialize';5export type GetEntriesConfig = {6 limit?: number;7}8type ObjectIteratorDescriptor = {9 iterator: Iterator<*>;10 consumedCount: number;11}12type ObjectIterators = Map<number, ObjectIteratorDescriptor>;13const iteratorsByObject:WeakMap<Object, ObjectIterators> = new WeakMap();14function acquireIterator(object: Object, iteratorId) : [boolean, Iterator<any>] {15 if (iteratorId != null && iteratorsByObject.has(object)) {16 const iteratorDescriptor = iteratorsByObject.get(object).get(iteratorId);17 if (iteratorDescriptor) {18 return [false, iteratorDescriptor.iterator];19 }20 }21 return [true, object[Symbol.iterator]()];22}23export default function getEntries(24 objectId: RemoteObjectId,25 iteratorId: ?number = null,26 config:GetEntriesConfig = {}27) : EntriesDescriptor {28 const object = getObject(objectId);29 if (!object) {30 throw new Error('Object does not exist');31 }32 if (!object[Symbol.iterator]) {33 throw new Error('Object is not iterable');34 }35 const objectDescriptor = serialize(object);36 if (objectDescriptor.type !== 'object') {37 throw new Error('Invalid object found; was not serialized to expected type');38 }39 let totalEntries = null;40 const limit = config.limit;41 let size;42 // This it to appease flow - doing it in one condition below didn't work43 if (objectDescriptor.size != null) {44 size = objectDescriptor.size;45 }46 if (size && size !== 'Infinity') {47 totalEntries = objectDescriptor.size;48 } else if (!limit) {49 // TODO: Alternatively just iterate to fixed 'safe' limit and throw?50 throw new Error('Potentially infinite collection; you must specify a limit');51 }52 const [isNewIterator, it] = acquireIterator(object, iteratorId);53 let n = it.next();54 const values = [];55 while (!n.done) {56 let subType = null;57 // This is to appease flow - doing it in one condition below didn't58 // work for some reason59 if (objectDescriptor.subType != null) {60 subType = objectDescriptor.subType;61 }62 if (subType === 'map') {63 values.push([serialize(n.value[0]), serialize(n.value[1])]);64 } else {65 values.push(serialize(n.value));66 }67 if (limit && values.length >= limit) {68 break;69 }70 n = it.next();71 }72 let iteratorData;73 let done = n.done;74 if (!done) {75 if (!iteratorsByObject.has(object)) {76 iteratorsByObject.set(object, new Map());77 }78 const iterators = iteratorsByObject.get(object);79 let id = iteratorId;80 let iteratorDesc = id != null && iterators.get(id);81 if (!iteratorDesc) {82 id = iterators.size;83 iteratorDesc = {84 iterator: it,85 consumedCount: 0,86 };87 iterators.set(id, iteratorDesc);88 }89 iteratorDesc.consumedCount += values.length;90 iteratorData = { iteratorId: id };91 // If we know the size of the iterator check if we have actually consumed it all92 if (totalEntries && totalEntries === iteratorDesc.consumedCount) {93 done = true;94 iteratorData = null;95 }96 }97 return {98 objectId,99 isNewIterator,100 result: values,101 done,102 ...iteratorData,103 };...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var WPTree = require('./wptree.js');2var fs = require('fs');3var path = require('path');4var dir = process.argv[2];5var ext = process.argv[3];6var tree = new WPTree(dir);7tree.iteratorDesc(function (file) {8 if (path.extname(file) === '.' + ext) {9 console.log(file);10 }11});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptree = require('wptree');2var tree = wptree.createTree();3var data = [1,2,3,4,5,6,7,8,9,10];4tree.init(data);5var iter = tree.iteratorDesc();6while(iter.hasNext()) {7 console.log(iter.next());8}9var wptree = require('wptree');10var tree = wptree.createTree();11var data = [1,2,3,4,5,6,7,8,9,10];12tree.init(data);13var iter = tree.iteratorAsc();14while(iter.hasNext()) {15 console.log(iter.next());16}17var wptree = require('wptree');18var tree = wptree.createTree();19var data = [1,2,3,4,5,6,7,8,9,10];20tree.init(data);21var iter = tree.iteratorAscFrom(3);22while(iter.hasNext()) {23 console.log(iter.next());24}25var wptree = require('wptree');26var tree = wptree.createTree();27var data = [1,2,3,4,5,6,7,8,9,10];28tree.init(data);29var iter = tree.iteratorDescFrom(7);30while(iter.hasNext()) {31 console.log(iter.next());32}

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptree = require('./wptree');2var fs = require('fs');3var path = require('path');4var dirPath = process.argv[2];5var depth = process.argv[3];6var tree = new wptree(dirPath, depth);7var iterator = tree.iteratorDesc();8var next = iterator.next();9while(!next.done) {10 console.log(next.value);11 next = iterator.next();12}

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptree = require('wptree');2var path = require('path');3var tree = wptree.create();4tree.add('a');5tree.add('a/b');6tree.add('a/c');7tree.add('a/c/d');8tree.add('a/c/e');9tree.add('a/c/f');10tree.add('a/c/g');11tree.add('a/c/h');12tree.add('a/c/i');13tree.add('a/c/j');14tree.add('a/c/k');15tree.add('a/c/l');16tree.add('a/c/m');17tree.add('a/c/n');18tree.add('a/c/o');19tree.add('a/c/p');20tree.add('a/c/q');21tree.add('a/c/r');22tree.add('a/c/s');23tree.add('a/c/t');24tree.add('a/c/u');25tree.add('a/c/v');26tree.add('a/c/w');27tree.add('a/c/x');28tree.add('a/c/y');29tree.add('a/c/z');30tree.add('a/c/aa');31tree.add('a/c/ab');32tree.add('a/c/ac');33tree.add('a/c/ad');34tree.add('a/c/ae');35tree.add('a/c/af');36tree.add('a/c/ag');37tree.add('a/c/ah');38tree.add('a/c/ai');39tree.add('a/c/aj');40tree.add('a/c/ak');41tree.add('a/c/al');42tree.add('a/c/am');43tree.add('a/c/an');44tree.add('a/c/ao');45tree.add('a/c/ap');46tree.add('a/c/aq');47tree.add('a/c/ar');48tree.add('a/c/as');49tree.add('a/c/at');50tree.add('a/c/au');51tree.add('a/c/av');52tree.add('a/c/aw');53tree.add('a/c/ax');54tree.add('a/c/ay');55tree.add('a/c/az');56tree.add('a/c/ba');57tree.add('a/c/bb');58tree.add('a/c/bc');59tree.add('a/c/bd');60tree.add('a/c/be');61tree.add('a/c/bf');62tree.add('a/c/bg');63tree.add('a/c/bh');64tree.add('a/c/bi');65tree.add('a/c/bj');66tree.add('a/c/bk');67tree.add('a/c/bl');68tree.add('

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptree = require('./wptree.js');2var tree = new wptree({value: 1, left: {value: 2, left: {value:4}, right: {value:5}}, right: {value: 3, left: {value:6}, right: {value:7}}});3var it = tree.iteratorDesc();4var node = it.next();5while(!node.done){6 console.log(node.value);7 node = it.next();8}

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptree = require('wptree');2var tree = new wptree();3var iter = tree.iteratorDesc();4var node = iter.next();5while(node != null){6 console.log(node);7 node = iter.next();8}

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptree = require('./wptree');2var fs = require('fs');3var data = fs.readFileSync("data.json");4var obj = JSON.parse(data);5var tree = new wptree(obj);6var iterator = tree.iteratorDesc("A");7var next = iterator.next();8while(!next.done) {9 console.log(next.value);10 next = iterator.next();11}

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful