diff --git a/moli-benchmark/wpt-cross-current/passed-cases.txt b/moli-benchmark/wpt-cross-current/passed-cases.txt index dd2807ebbe..1895f591ba 100644 --- a/moli-benchmark/wpt-cross-current/passed-cases.txt +++ b/moli-benchmark/wpt-cross-current/passed-cases.txt @@ -4556,6 +4556,7 @@ dom/observable/tentative/observable-first.any.js?moli-wpt-any=window dom/observable/tentative/observable-forEach.any.js?moli-wpt-any=dedicatedworker dom/observable/tentative/observable-forEach.any.js?moli-wpt-any=window dom/observable/tentative/observable-forEach.window.js?moli-wpt-script=window +dom/observable/tentative/observable-inspect.any.js?moli-wpt-any=dedicatedworker dom/observable/tentative/observable-inspect.any.js?moli-wpt-any=window dom/observable/tentative/observable-last.any.js?moli-wpt-any=dedicatedworker dom/observable/tentative/observable-last.any.js?moli-wpt-any=window @@ -10020,6 +10021,7 @@ webidl/ecmascript-binding/constructors.html webidl/ecmascript-binding/default-iterator-object.html webidl/ecmascript-binding/default-toJSON-cross-realm.html webidl/ecmascript-binding/es-exceptions/exceptions.html +webidl/ecmascript-binding/global-immutable-prototype.any.js?moli-wpt-any=dedicatedworker webidl/ecmascript-binding/global-object-implicit-this-value-cross-realm.html webidl/ecmascript-binding/has-instance.html webidl/ecmascript-binding/interface-object-set-receiver.html diff --git a/moli-renderer-v8/src/worker/thread/tests/lifecycle.rs b/moli-renderer-v8/src/worker/thread/tests/lifecycle.rs index b283d4e263..a781816a5d 100644 --- a/moli-renderer-v8/src/worker/thread/tests/lifecycle.rs +++ b/moli-renderer-v8/src/worker/thread/tests/lifecycle.rs @@ -276,7 +276,7 @@ async fn worker_global_prototype_chains_inherit_event_target_and_are_immutable() format!( r#" const result = ({fixture})({interface:?}); - if (result.checks !== 46 || result.failures.length) {{ + if (result.checks !== 61 || result.failures.length) {{ throw new Error(JSON.stringify(result)); }} "# diff --git a/moli-renderer-v8/tests/fixtures/worker-global-prototypes.js b/moli-renderer-v8/tests/fixtures/worker-global-prototypes.js index 003b9ce845..768205377e 100644 --- a/moli-renderer-v8/tests/fixtures/worker-global-prototypes.js +++ b/moli-renderer-v8/tests/fixtures/worker-global-prototypes.js @@ -38,6 +38,11 @@ check(Object.prototype.toString.call(WorkerGlobalScope.prototype) === '[object WorkerGlobalScope]', 'worker tag'); check(throwsTypeError(() => new scopeConstructor()), 'specific illegal constructor'); check(throwsTypeError(() => new WorkerGlobalScope()), 'worker illegal constructor'); + check(typeof self.when === 'function', 'inherited when exposed'); + check(self.when === eventTarget.prototype.when, 'inherited when identity'); + for (const value of chain.slice(0, 3)) { + check(!Object.hasOwn(value, 'when'), 'when is inherited'); + } test('prototype extension', () => { const key = Symbol('EventTarget extension'); eventTarget.prototype[key] = 17; @@ -56,6 +61,33 @@ self.dispatchEvent(new Event('worker-prototype-probe')); check(values.length === 1, 'global listener removal still works'); }); + test('inherited observable events', () => { + const controller = new AbortController(); + const values = []; + const observable = self.when('worker-prototype-probe'); + check(observable instanceof Observable, 'when returns Observable'); + observable.subscribe(event => values.push(event), {signal: controller.signal}); + const first = new Event('worker-prototype-probe'); + self.dispatchEvent(first); + check(values.length === 1 && values[0] === first, 'when receives global dispatch'); + check(first.target === self, 'dispatched event target is global'); + controller.abort(); + self.dispatchEvent(new Event('worker-prototype-probe')); + check(values.length === 1, 'abort removes global listener'); + }); + test('global error reporting', () => { + const errors = []; + const marker = new Error('inspector abort'); + const controller = new AbortController(); + self.when('error').take(1).subscribe(event => { + errors.push(event.error); + event.preventDefault(); + }); + new Observable(subscriber => subscriber.next(1)) + .inspect({abort() { throw marker; }}) + .subscribe(() => controller.abort(), {signal: controller.signal}); + check(errors.length === 1 && errors[0] === marker, 'when receives reported callback error'); + }); test('receiver branding', () => { let conversions = 0; let traps = 0; @@ -67,6 +99,7 @@ getPrototypeOf() { traps++; throw new Error('author proxy trap'); } }), revoked.proxy]) { check(throwsTypeError(() => eventTarget.prototype.addEventListener.call(receiver, type, () => {})), 'addEventListener rejects forged/proxy receiver'); + check(throwsTypeError(() => eventTarget.prototype.when.call(receiver, type)), 'when rejects forged/proxy receiver'); } check(conversions === 0, 'brand checked before conversion'); check(traps === 0, 'brand checked without proxy traps'); @@ -76,6 +109,7 @@ try { check(Object.getPrototypeOf(WorkerGlobalScope.prototype) === eventTarget.prototype, 'prototype keeps intrinsic EventTarget'); check(Object.getPrototypeOf(WorkerGlobalScope) === eventTarget, 'constructor keeps intrinsic EventTarget'); + check(self.when === eventTarget.prototype.when, 'when keeps intrinsic method'); } finally { self.EventTarget = eventTarget; } }); return {checks, failures};