pub const FOREIGN_JS: &str = "// The lifecycle of a `foreign \u{2026} gives view` \u{2014} spec \u{a7}14E.1, \u{a7}14E.3.\n//\n// **Its own module, and that is a size decision rather than a tidiness\n// one.** A DOM-owning foreign is the one construct here that a program\n// can go its whole life without writing, and \u{a7}16.3.1 promises a bundle\n// ships nothing it does not use. Left in `dom.js` these bytes were\n// downloaded by every page ever served, including one with no FFI in it,\n// which is a fixed cost paid for an optional feature. `Bundle::runtime`\n// already computes a transitive import closure \u{2014} `rpc.js`, `store.js` and\n// `wire.js` are linked only when the split finds a crossing or a durable\n// key \u{2014} so this is that existing mechanism applied once more, and not a\n// new exemption from the size gate. `zdc-bench` charges this file to the\n// programs that link it and to no others, and a test pins both halves of\n// that: a null program must not reach it, and a program with a `gives\n// view` foreign must.\n//\n// Nothing here touches the DOM. The node is handed in \u{2014} the template\n// already carries it \u{2014} so this module needs the reactivity core and\n// nothing else, which is why it does not import `dom.js` and why linking\n// it costs a program `signal.js` it already had.\n//\n// **The contract is checked here because here is the only place that can\n// see it (#239).** `mount(node, props) -> { update(props), destroy() }` is\n// a shape no type in the language describes, so `from \"three\" as \"Scene\"`\n// compiles \u{2014} a `foreign` declaration gives the compiler nothing to check\n// it against \u{2014} and used to fail on the first render with an engine\n// `TypeError` raised inside this file, naming a local the reader never\n// wrote and no part of the declaration that caused it.\n//\n// It is not cheap: the check nearly trebles this file, almost all of it\n// the refusals\' own prose, and the module is downloaded whole by every\n// program that writes one of these. BENCHMARKS.md charges it there and\n// records what it did to the margin, because a size argument that quietly\n// stops applying to the file it was made about is worse than the bytes.\n// What it buys is the sentence that turns a trace through a runtime into\n// the name of a declaration to open.\n\nimport { effect, onCleanup } from \'./signal.js\';\n\n/** The contract, spelled once and quoted verbatim in every refusal. */\nconst CONTRACT = \'mount(node, props) -> { update(props), destroy() }\';\n\n/** The claim both refusals of the imported binding open with. */\nconst NOT_A_MOUNT = \'gives a view, so what its `as` clause names must be a mount function; \';\n\n/**\n * Hand an element to a `foreign \u{2026} gives view` (\u{a7}14E.1, \u{a7}14E.3).\n *\n * `node` is a `<div>` the template already carries, so a foreign is a\n * static-markup hole bound like an attribute rather than an anchor pair\n * like `each`, keeping it inside \u{a7}16.2 R2\'s cloning model. `props` is a\n * thunk giving a plain object, one property per `takes` argument in\n * order, read inside an effect. `declared` is the declaration\'s own name\n * in the program, carried here for no reason but the refusals: nothing\n * else in this file reads it, and without it a breach of the contract can\n * only be reported against a runtime the reader did not write.\n *\n * Reactivity is `update`, never re-invocation: re-running `create` would\n * rebuild whatever the module owns \u{2014} a WebGL context, an animation \u{2014} on\n * every write, the failure this form prevents. Nothing crosses back, and\n * the handle\'s *types* are still asserted rather than verified (\u{a7}14E.4) \u{2014}\n * what is checked here is that there is a handle with the two methods,\n * which is the part that has an answer at mount.\n */\nexport function foreign(node, create, props, declared) {\n let handle = null;\n let disposed = false;\n\n effect(() => {\n // Above the guard, so the edge exists on a run that bails.\n const next = props();\n // Disposal cannot retract a run the flush has already queued:\n // `clearSources` unsubscribes for the future, and a pending run is\n // still in the drain list. Without this, removing an `each` row in\n // the same batch as a write that row read calls `update` on a\n // destroyed handle \u{2014} a fault with no visible symptom.\n if (disposed) return;\n if (handle === null) {\n handle = mounted(create, node, next, declared);\n return;\n }\n handle.update(next);\n });\n\n // `owned` disposes **last-registered-first**, so this runs *before* the\n // effect above is unsubscribed \u{2014} `destroy()` lands while the binding is\n // still live. That is the opposite of what this form was first written\n // against, when `owned` disposed in registration order, and it is why\n // the ordering is not what makes it safe: the `disposed` flag is. Set\n // it before `destroy()`, and a run the flush had already queued finds\n // the guard rather than a destroyed handle, whichever order the two\n // cleanups happen to run in.\n //\n // Stated because the alternative is a comment that is true only of a\n // disposal order nothing here enforces.\n onCleanup(() => {\n disposed = true;\n if (handle !== null) handle.destroy();\n });\n}\n\n/**\n * Call `create` and return its handle, or refuse in the declaration\'s name.\n *\n * Checked at mount and nowhere afterwards. A handle that answered once\n * cannot stop answering \u{2014} the module would have to replace its own return\n * value, which it no longer holds \u{2014} so re-checking on every write would\n * charge every signal write for a mistake that can only be made once.\n */\nfunction mounted(create, node, props, declared) {\n if (typeof create !== \'function\') {\n refuse(\n declared,\n NOT_A_MOUNT + \'this one is \' + describe(create) + \'.\',\n \'Point it at an export of that shape, or at a module of your own that wraps the library\'\n );\n }\n // A class passes `typeof create === \'function\'`, and a class is what\n // every visual library exports \u{2014} three.js\'s `Scene`, chart.js\'s `Chart`,\n // maplibre\'s `Map` \u{2014} so this is the case the check exists for rather\n // than an edge of it. Calling one raises `Class constructor \u{2026} cannot be\n // invoked without \'new\'`, from this file, about a name the reader never\n // wrote. That report is what #239 was filed about.\n if (isClass(create)) {\n refuse(\n declared,\n NOT_A_MOUNT + \'this one is a class, and a class cannot be called without `new`.\',\n \"A library\'s class is not a mount function: give `\" +\n declared +\n \'` a module of your own that constructs it, hands it the node, and returns the handle\'\n );\n }\n\n const handle = create(node, props);\n if (!conforms(handle)) {\n refuse(\n declared,\n \'gives a view, so mounting it must return a handle; this \' + returned(handle) + \'.\',\n \'`update` is how a write reaches the module \u{2014} re-invoking mount would rebuild whatever it \' +\n \'owns, a WebGL context or an animation in flight \u{2014} and `destroy` is how the module gives \' +\n \'back a frame loop or a context when the node goes. Return both\'\n );\n }\n return handle;\n}\n\n/**\n * Throw the one shape of refusal this file has: claim, contract, repair.\n *\n * One function rather than three literals so that the declaration is named\n * the same way every time and the spec reference cannot drift between\n * them \u{2014} a reader who has seen one of these has seen all three.\n *\n * `repair` carries no closing full stop: this adds one after the spec\n * reference, which is the sentence\'s real end.\n */\nfunction refuse(declared, claim, repair) {\n throw new Error(\n \'`\' + declared + \'` \' + claim + \' The contract is \' + CONTRACT + \'. \' + repair + \' (spec \u{a7}14E.1).\'\n );\n}\n\n/** Whether a handle is one: an object carrying both halves of the contract. */\nfunction conforms(handle) {\n return (\n handle !== null &&\n typeof handle === \'object\' &&\n typeof handle.update === \'function\' &&\n typeof handle.destroy === \'function\'\n );\n}\n\n/** What was imported, as a noun phrase: `a number`, `an object`, `null`. */\nfunction describe(value) {\n if (value === null) return \'null\';\n const what = typeof value;\n if (what === \'undefined\') return \'undefined\';\n return (\'aeiou\'.includes(what[0]) ? \'an \' : \'a \') + what;\n}\n\n/** What mounting produced, as the tail of \"this \u{2026}\". */\nfunction returned(handle) {\n if (handle === null || typeof handle !== \'object\') return `returned ${describe(handle)}`;\n const missing =\n typeof handle.update === \'function\'\n ? \'no `destroy`\'\n : typeof handle.destroy === \'function\'\n ? \'no `update`\'\n : \'neither `update` nor `destroy`\';\n return `returned an object with ${missing}`;\n}\n\n/**\n * Whether `fn` is a class rather than an ordinary function.\n *\n * ECMAScript\'s own distinction rather than a guess at source text: a class\n * constructor\'s `prototype` is non-writable, an ordinary function\'s is\n * writable, and a method or arrow has none at all. Reading the descriptor\n * separates the three without `Function.prototype.toString`, which a\n * minifier, a bound function and a native class can each make lie.\n *\n * A class transpiled down to a plain function \u{2014} what a bundler targeting\n * ES5 emits \u{2014} is not detectable here and does not need to be: it is\n * callable, so it is called, and it is the handle check that refuses it.\n */\nfunction isClass(fn) {\n const prototype = Object.getOwnPropertyDescriptor(fn, \'prototype\');\n return prototype !== undefined && prototype.writable === false;\n}\n";Expand description
The lifecycle of a foreign … gives view: create, update, destroy.
Its own module rather than part of dom.js because a DOM-owning
foreign is optional and its machinery is not small: a program that
writes none must not download it (§16.3.1). It imports signal.js and
nothing else — the node is handed in, so there is no DOM dependency.