{"record":{"id":"e38751c7e102bcae","repo":"denoland/deno","slug":"messageevent-constructor-eventinitdict-ports-f","errorCode":null,"errorMessage":"MessageEvent constructor: eventInitDict.ports (${formatForRaw(ports)}) is not iterable.","messagePattern":"MessageEvent constructor: eventInitDict\\.ports \\((.+?)\\) is not iterable\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/web/02_event.js","lineNumber":1354,"sourceCode":"      cancelable: eventInitDict?.cancelable ?? false,\n      composed: eventInitDict?.composed ?? false,\n    });\n\n    this.data = eventInitDict?.data ?? null;\n    const ports = eventInitDict?.ports;\n    if (ports == null) {\n      // `ports` is a FrozenArray<MessagePort> per the HTML spec, so the\n      // exposed array must be read-only.\n      this.ports = ObjectFreeze([]);\n    } else {\n      // MessageEvent ports: iterable validation + per-element MessagePort\n      // type check. Matches the messages Node asserts on so the\n      // node_compat tests pass while still being WHATWG-shaped.\n      if (\n        ports === null || typeof ports !== \"object\" ||\n        ports[SymbolIterator] === undefined\n      ) {\n        throw new TypeError(\n          `MessageEvent constructor: eventInitDict.ports (${\n            formatForRaw(ports)\n          }) is not iterable.`,\n        );\n      }\n      const MessagePortProto = getMessagePortPrototype();\n      const arr = [];\n      let i = 0;\n      // Iterate using the user's own iterator so values that aren't real\n      // arrays (e.g. a `RegExp` with a custom `Symbol.iterator` -- covered\n      // by WPT's no-regexp-special-casing test) still produce the\n      // expected `ports` array. SafeArrayIterator can't be used here\n      // because it walks the value as if it were an Array.\n      // deno-lint-ignore deno-internal/prefer-primordials\n      for (const p of ports) {\n        if (\n          p === null || typeof p !== \"object\" ||\n          !ObjectPrototypeIsPrototypeOf(MessagePortProto, p)","sourceCodeStart":1336,"sourceCodeEnd":1372,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/02_event.js#L1336-L1372","documentation":"The MessageEvent constructor validates eventInitDict.ports, typed in the HTML spec as FrozenArray<MessagePort>. Any non-null value must be an object exposing Symbol.iterator (ext/web/02_event.js:1348-1357); anything else throws TypeError '... is not iterable'. The wording deliberately matches Node's assertion messages so node_compat tests pass while the shape stays WHATWG. The classic trigger is passing a single MessagePort instead of an array containing it.","triggerScenarios":"new MessageEvent('message', { data, ports: channel.port1 }) — a single MessagePort is an object but has no Symbol.iterator; also ports: 'abc', ports: 123, or ports: {} (no iterator). ports omitted, null, or an iterable array are accepted.","commonSituations":"Transferring exactly one port and passing it unwrapped; test fixtures for postMessage/messagepassing written by Node developers (Node tolerates different shapes); polyfills that accept either a port or an array and forward verbatim.","solutions":["Wrap ports in an array: new MessageEvent('message', { data, ports: [channel.port1] }).","Omit ports (or pass null/undefined) when no ports were transferred — the constructor freezes an empty array.","Validate third-party payloads before constructing: check ports == null || (typeof ports === 'object' && typeof ports[Symbol.iterator] === 'function')."],"exampleFix":"// before\nnew MessageEvent('message', { data, ports: channel.port1 });\n// TypeError: MessageEvent constructor: eventInitDict.ports ([object MessagePort]) is not iterable.\n\n// after\nnew MessageEvent('message', { data, ports: [channel.port1] });","handlingStrategy":"type-guard","validationCode":"const raw = eventInit.ports;\nif (raw != null && (typeof raw !== 'object' || typeof raw[Symbol.iterator] !== 'function')) {\n  throw new TypeError('eventInitDict.ports must be an array of MessagePort');\n}\nnew MessageEvent('message', { ...eventInit, ports: raw == null ? [] : [...raw] });","typeGuard":"function isPortList(v) {\n  return v == null ||\n    (typeof v === 'object' && typeof v[Symbol.iterator] === 'function');\n}","tryCatchPattern":null,"preventionTips":["Always wrap ports in an array: ports: [port]","Omit ports when none were transferred","Pass only web MessagePorts from MessageChannel or worker onmessage"],"tags":["messageevent","messageport","worker","validation"],"backgroundTag":"argument-not-iterable","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}