{"record":{"id":"5ef11bc51a656555","repo":"denoland/deno","slug":"messageevent-constructor-expected-eventinitdict-s","errorCode":null,"errorMessage":"MessageEvent constructor: Expected eventInitDict.source (${formatForBranded(source)}) to be an instance of MessagePort.","messagePattern":"MessageEvent constructor: Expected eventInitDict\\.source \\((.+?)\\) to be an instance of MessagePort\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/web/02_event.js","lineNumber":1415,"sourceCode":"      // ServiceWorker brand to gate against, so accept anything except\n      // primitives (which the node_compat tests expect to throw on,\n      // e.g. `source: 1`) and plain `Object` instances like `{}` (also\n      // checked by Node). MessagePort, Window-like globals, and\n      // user-defined classes all pass through unchanged -- matching both\n      // the WPT `messageevent-constructor.https.html` test (which\n      // assigns `window` to `source`) and node_compat\n      // `test-worker-message-event`.\n      const t = typeof source;\n      const isPrimitive = t !== \"object\" && t !== \"function\";\n      // Treat values whose prototype is exactly Object.prototype (i.e.\n      // plain object literals like `{}`) as invalid sources. Using the\n      // prototype chain rather than `.constructor` avoids the\n      // prefer-primordials lint and is more reliable since user code\n      // can override `constructor`.\n      const isPlainObject = !isPrimitive &&\n        ObjectGetPrototypeOf(source) === ObjectPrototype;\n      if (isPrimitive || isPlainObject) {\n        throw new TypeError(\n          `MessageEvent constructor: Expected eventInitDict.source (${\n            formatForBranded(source)\n          }) to be an instance of MessagePort.`,\n        );\n      }\n      this.#source = source;\n    } else {\n      this.#source = null;\n    }\n  }\n\n  [SymbolFor(\"Deno.privateCustomInspect\")](inspect, inspectOptions) {\n    return inspect(\n      getCreateFilteredInspectProxy()({\n        object: this,\n        evaluate: ObjectPrototypeIsPrototypeOf(MessageEventPrototype, this),\n        keys: [\n          ...new SafeArrayIterator(EVENT_PROPS),","sourceCodeStart":1397,"sourceCodeEnd":1433,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/02_event.js#L1397-L1433","documentation":"eventInitDict.source is typed in the spec as MessagePort | ServiceWorker | WindowProxy, but Deno has no JS-level brand for Window or ServiceWorker. The constructor therefore accepts anything except primitives and values whose prototype is exactly Object.prototype (ext/web/02_event.js:1405-1420): numbers, strings, booleans, and plain {} literals throw TypeError 'Expected eventInitDict.source ... to be an instance of MessagePort'. Real MessagePorts, the global object, and user-defined class instances pass through unchanged — a deliberate compromise to satisfy both WPT and Node's worker tests.","triggerScenarios":"new MessageEvent('message', { data, source: 1 }), { source: 'worker' }, or { source: {} } — primitives and plain object literals. source: null/undefined omitted, source: channel.port2, or source: globalThis are fine.","commonSituations":"Worker test fixtures setting source to a literal or a number (copied from Node test suites that assert the throw); forwarding a received event's source field that is actually plain data; TypeScript code assuming any object is accepted because the message mentions only MessagePort.","solutions":["Set source to a real MessagePort (e.g. channel.port2) or omit it / pass null.","Primitives and {} are rejected by design — delete the source field from fixtures instead of stubbing it.","For window-like targets pass the global object itself (WPT assigns window), never a literal stand-in."],"exampleFix":"// before\nnew MessageEvent('message', { data, source: {} });\n// TypeError: Expected eventInitDict.source ([object Object]) to be an instance of MessagePort.\n\n// after\nnew MessageEvent('message', { data, source: channel.port2 });","handlingStrategy":"type-guard","validationCode":"const s = eventInit.source;\nconst ok = s == null ||\n  ((typeof s === 'object' || typeof s === 'function') &&\n    Object.getPrototypeOf(s) !== Object.prototype);\nif (!ok) delete eventInit.source;\nnew MessageEvent('message', eventInit);","typeGuard":"function isMessageEventSource(v) {\n  if (v == null) return true;\n  if (typeof v !== 'object' && typeof v !== 'function') return false;\n  return Object.getPrototypeOf(v) !== Object.prototype; // plain {} rejected\n}","tryCatchPattern":null,"preventionTips":["Use channel.port1/port2 as source","Omit source instead of stubbing it with {} or a number in tests","Remember the real rule: primitives and plain objects are rejected, class instances pass"],"tags":["messageevent","messageport","worker","validation"],"backgroundTag":"invalid-eventinit-type","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}