setup({ explicit_done: true }); test(t => { assert_throws({name: "TypeError"}, function() { new PerformanceObserver(); }, "PerformanceObserver constructor should throw TypeError if no argument is specified."); assert_throws({name: "TypeError"}, function() { new PerformanceObserver({}); }, "PerformanceObserver constructor should throw TypeError if the argument is not a function."); }, "Test that PerformanceObserver constructor throws exception"); test(t => { var observer = new PerformanceObserver(() => { }); assert_throws({name: "TypeError"}, function() { observer.observe(); }, "observe() should throw TypeError exception if no option specified."); assert_throws({name: "TypeError"}, function() { observer.observe({ unsupportedAttribute: "unsupported" }); }, "obsrve() should throw TypeError exception if the option has no 'entryTypes' attribute."); assert_throws({name: "TypeError"}, function() { observer.observe({ entryTypes: [] }); }, "obsrve() should throw TypeError exception if 'entryTypes' attribute is an empty sequence."); assert_throws({name: "TypeError"}, function() { observer.observe({ entryTypes: null }); }, "obsrve() should throw TypeError exception if 'entryTypes' attribute is null."); assert_throws({name: "TypeError"}, function() { observer.observe({ entryTypes: ["invalid"]}); }, "obsrve() should throw TypeError exception if 'entryTypes' attribute value is invalid."); }, "Test that PerformanceObserver.observe throws exception"); function promiseObserve(test, options) { return new Promise(resolve => { performance.clearMarks(); performance.clearMeasures(); var observer = new PerformanceObserver(list => resolve(list)); observer.observe(options); test.add_cleanup(() => observer.disconnect()); }); } promise_test(t => { var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']}); performance.mark("test-start"); performance.mark("test-end"); performance.measure("test-measure", "test-start", "test-end"); return promise.then(list => { assert_equals(list.getEntries().length, 3, "There should be three observed entries."); var markEntries = list.getEntries().filter(entry => { return entry.entryType == "mark"; }); assert_array_equals(markEntries, performance.getEntriesByType("mark"), "Observed 'mark' entries should equal to entries obtained by getEntriesByType."); var measureEntries = list.getEntries().filter(entry => { return entry.entryType == "measure"; }); assert_array_equals(measureEntries, performance.getEntriesByType("measure"), "Observed 'measure' entries should equal to entries obtained by getEntriesByType."); }); }, "Test for user-timing with PerformanceObserver"); promise_test(t => { var promise = new Promise((resolve, reject) => { performance.clearMarks(); performance.clearMeasures(); var observer = new PerformanceObserver(list => reject(list)); observer.observe({entryTypes: ['mark', 'measure']}); observer.disconnect(); t.step_timeout(resolve, 100); }); performance.mark("test-start"); performance.mark("test-end"); performance.measure("test-measure", "test-start", "test-end"); return promise.then(() => { assert_equals(performance.getEntriesByType("mark").length, 2); assert_equals(performance.getEntriesByType("measure").length, 1); }, list => { assert_unreached("Observer callback should never be called."); }); }, "Nothing should be notified after disconnecting observer"); promise_test(t => { var promise = promiseObserve(t, {entryTypes: ['mark']}); performance.mark("test"); return promise.then(list => { assert_array_equals(list.getEntries({"entryType": "mark"}), performance.getEntriesByType("mark"), "getEntries with entryType filter should return correct results."); assert_array_equals(list.getEntries({"name": "test"}), performance.getEntriesByName("test"), "getEntries with name filter should return correct results."); assert_array_equals(list.getEntries({"name": "test", "entryType": "mark"}), performance.getEntriesByName("test"), "getEntries with name and entryType filter should return correct results."); assert_array_equals(list.getEntries({"name": "invalid"}), [], "getEntries with non-existent name filter should return an empty array."); assert_array_equals(list.getEntries({"name": "test", "entryType": "measure"}), [], "getEntries with name filter and non-existent entryType should return an empty array."); assert_array_equals(list.getEntries({"name": "invalid", "entryType": "mark"}), [], "getEntries with non-existent name and entryType filter should return an empty array."); assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}), [], "getEntries with initiatorType filter should return an empty array."); }); }, "Test for PerformanceObserverEntryList.getEntries"); promise_test(t => { var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']}); performance.mark("test"); performance.measure("test-measure", "test", "test"); return promise.then(list => { assert_array_equals(list.getEntriesByType("mark"), performance.getEntriesByType("mark")); assert_array_equals(list.getEntriesByType("measure"), performance.getEntriesByType("measure")); }); }, "Test for PerformanceObserverEntryList.getEntriesByType"); promise_test(t => { var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']}); performance.mark("test"); performance.measure("test-measure", "test", "test"); return promise.then(list => { assert_array_equals(list.getEntriesByName("test"), performance.getEntriesByName("test")); assert_array_equals(list.getEntriesByName("test-measure"), performance.getEntriesByName("test-measure")); }); }, "Test for PerformanceObserverEntryList.getEntriesByName"); promise_test(t => { var promise = new Promise(resolve => { performance.clearMarks(); performance.clearMeasures(); var observer = new PerformanceObserver(list => resolve(list)); observer.observe({entryTypes: ['mark', 'measure']}); observer.observe({entryTypes: ['mark', 'measure']}); t.add_cleanup(() => observer.disconnect()); }); performance.mark("test-start"); performance.mark("test-end"); performance.measure("test-measure", "test-start", "test-end"); return promise.then(list => { assert_equals(list.getEntries().length, 3, "Observed user timing entries should have only three entries."); }); }, "Test that invoking observe method twice affects nothing"); promise_test(t => { var promise = new Promise(resolve => { performance.clearMarks(); performance.clearMeasures(); var observer = new PerformanceObserver(list => resolve(list)); observer.observe({entryTypes: ['mark', 'measure']}); observer.observe({entryTypes: ['mark']}); t.add_cleanup(() => observer.disconnect()); }); performance.mark("test-start"); performance.mark("test-end"); performance.measure("test-measure", "test-start", "test-end"); return promise.then(list => { assert_equals(list.getEntries().length, 2, "Observed user timing entries should have only two entries."); }); }, "Test that observing filter is replaced by a new filter"); promise_test(t => { var promise = new Promise(resolve => { performance.clearMarks(); performance.clearMeasures(); var observer = new PerformanceObserver(list => resolve(list)); observer.observe({entryTypes: ['mark']}); observer.observe({entryTypes: ['measure']}); t.add_cleanup(() => observer.disconnect()); }); performance.mark("test-start"); performance.mark("test-end"); performance.measure("test-measure", "test-start", "test-end"); return promise.then(list => { assert_equals(list.getEntries().length, 1, "Observed user timing entries should have only 1 entries."); }); }, "Test that observing filter is replaced by a new filter");