mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
1c4f519e36
## What Ports the Relay `graphql` tagged template transform (babel-plugin-relay / swc_relay) as an individual napi transform, per #24914: - **`crates/oxc_relay`** — the core transform as its own crate (modeled on `oxc_react_compiler`): replaces `graphql` tagged templates with references to relay-compiler artifacts. Definition names are extracted textually like `swc_relay` (equivalent to `\b(fragment|mutation|query|subscription)\s+(\w+)` with `#` comments stripped; hand-rolled scanner, no regex dependency). - **`napi/transform-relay`** (`oxc-transform-relay`) — standalone napi package copied from the `napi/transform-react` template: parse → semantic → relay traverse → codegen. Only `graphql` tags are rewritten; TypeScript/JSX syntax is preserved untouched, so the output composes with any downstream toolchain. ## Options | option | default | behavior | |---|---|---| | `artifactDirectory` | unset | when set, the import path is computed lexically relative to the transformed file (babel-plugin-relay `getRelativeImportPath` semantics — swc emits absolute paths instead); unset → `./__generated__/` next to the file | | `language` | `javascript` | `typescript` imports `Name.graphql.ts`, otherwise `Name.graphql.js` | | `eagerEsModules` | `true` | hoisted default imports (babel-plugin-relay ≥ v17 parity); `false` emits inline `require()` (`@swc/plugin-relay` / Next.js behavior) | A `graphql` tag with no extractable definition name produces an error diagnostic (babel throws; swc silently skips). Not supported, documented in both READMEs: dev-mode artifact hash validation, `jsModuleFormat: "haste"`, `isDevVariableName`, swc's Next.js-specific `projects`/`pagesDir`, and GraphQL document validation. closes #24914 --- Implemented with Claude Code.
75 lines
1.8 KiB
JavaScript
75 lines
1.8 KiB
JavaScript
import fs from "node:fs";
|
|
import { createRequire } from "node:module";
|
|
import { parse } from "node:path";
|
|
import { WASI } from "node:wasi";
|
|
import { parentPort, Worker } from "node:worker_threads";
|
|
|
|
const require = createRequire(import.meta.url);
|
|
|
|
const {
|
|
instantiateNapiModuleSync,
|
|
MessageHandler,
|
|
getDefaultContext,
|
|
emnapiAsyncWorkPlugin,
|
|
emnapiTSFNPlugin,
|
|
} = require("@napi-rs/wasm-runtime");
|
|
|
|
if (parentPort) {
|
|
parentPort.on("message", (data) => {
|
|
globalThis.onmessage({ data });
|
|
});
|
|
}
|
|
|
|
Object.assign(globalThis, {
|
|
self: globalThis,
|
|
require,
|
|
Worker,
|
|
importScripts: function (f) {
|
|
;(0, eval)(fs.readFileSync(f, "utf8") + "//# sourceURL=" + f);
|
|
},
|
|
postMessage: function (msg) {
|
|
if (parentPort) {
|
|
parentPort.postMessage(msg);
|
|
}
|
|
},
|
|
});
|
|
|
|
const emnapiContext = getDefaultContext();
|
|
|
|
const __rootDir = parse(process.cwd()).root;
|
|
|
|
const handler = new MessageHandler({
|
|
onLoad({ wasmModule, wasmMemory }) {
|
|
const wasi = new WASI({
|
|
version: 'preview1',
|
|
env: process.env,
|
|
preopens: {
|
|
[__rootDir]: __rootDir,
|
|
},
|
|
});
|
|
|
|
return instantiateNapiModuleSync(wasmModule, {
|
|
childThread: true,
|
|
wasi,
|
|
context: emnapiContext,
|
|
// The wasm links a "basic" emnapi archive (no C async-work /
|
|
// threadsafe-function implementations), so every thread that
|
|
// instantiates it must provide the JavaScript implementations
|
|
// through the emnapi plugins.
|
|
plugins: [emnapiAsyncWorkPlugin, emnapiTSFNPlugin],
|
|
overwriteImports(importObject) {
|
|
importObject.env = {
|
|
...importObject.env,
|
|
...importObject.napi,
|
|
...importObject.emnapi,
|
|
memory: wasmMemory
|
|
};
|
|
},
|
|
});
|
|
},
|
|
});
|
|
|
|
globalThis.onmessage = function (e) {
|
|
handler.handle(e);
|
|
};
|