diff --git a/packages/rollup-plugin-ephemeral/LICENSE b/packages/rollup-plugin-ephemeral/LICENSE new file mode 100644 index 0000000..257e767 --- /dev/null +++ b/packages/rollup-plugin-ephemeral/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2024 Oleksii Raspopov + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/packages/rollup-plugin-ephemeral/README.md b/packages/rollup-plugin-ephemeral/README.md new file mode 100644 index 0000000..1004537 --- /dev/null +++ b/packages/rollup-plugin-ephemeral/README.md @@ -0,0 +1,3 @@ +# rollup-plugin-ephemeral + +Like `@rollup/plugin-virtual` but sometimes you need virtual modules to behave like real files. diff --git a/packages/rollup-plugin-ephemeral/package.json b/packages/rollup-plugin-ephemeral/package.json new file mode 100644 index 0000000..fe63d97 --- /dev/null +++ b/packages/rollup-plugin-ephemeral/package.json @@ -0,0 +1,14 @@ +{ + "name": "rollup-plugin-ephemeral", + "version": "0.0.1", + "type": "module", + "main": "./plugin.js", + "module": "./plugin.js", + "types": "./plugin.d.ts", + "keywords": [ + "rollup-plugin" + ], + "scripts": { + "test": "node --test --experimental-test-coverage" + } +} diff --git a/packages/rollup-plugin-ephemeral/plugin.d.ts b/packages/rollup-plugin-ephemeral/plugin.d.ts new file mode 100644 index 0000000..772a2ea --- /dev/null +++ b/packages/rollup-plugin-ephemeral/plugin.d.ts @@ -0,0 +1,4 @@ +import { Plugin } from "rollup"; + +export function ephemeral(name: string, code: string): Plugin; +export default ephemeral; diff --git a/packages/rollup-plugin-ephemeral/plugin.js b/packages/rollup-plugin-ephemeral/plugin.js new file mode 100644 index 0000000..b9c949e --- /dev/null +++ b/packages/rollup-plugin-ephemeral/plugin.js @@ -0,0 +1,21 @@ +import { resolve, dirname } from "node:path"; + +export function ephemeral(name, code) { + let resolvedId = resolve(name); + return { + name: `ephemeral_${name}`, + resolveId(id, importer) { + if (id === name) return name; + if (importer != null) { + let resolvedImporterId = resolve(dirname(importer), id); + if (resolvedImporterId === resolvedId) return resolvedId; + } + return null; + }, + load(id) { + return id === name || id === resolvedId ? code : null; + }, + }; +} + +export default ephemeral; diff --git a/packages/rollup-plugin-ephemeral/test.js b/packages/rollup-plugin-ephemeral/test.js new file mode 100644 index 0000000..47cac15 --- /dev/null +++ b/packages/rollup-plugin-ephemeral/test.js @@ -0,0 +1,43 @@ +import { test } from "node:test"; +import { equal } from "node:assert/strict"; + +import { resolve } from "node:path"; + +import { rollup } from "rollup"; +import { ephemeral } from "./plugin.js"; + +test("generates as modules", async () => { + let bundle = await rollup({ + input: "./index.js", + treeshake: false, + plugins: [ + ephemeral( + "./index.js", + ` import { num } from '../branch/index.js'; + console.log(num); `, + ), + ephemeral("../branch/module.js", "export let num = 13;"), + ephemeral( + "../branch/index.js", + ` import { num as base } from './module.js'; + export let num = base * 2;`, + ), + ], + }); + let { output } = await bundle.generate({ format: "esm", preserveModules: true }); + equal(output.length, 3); +}); + +test("loads a bare module ID from memory", () => { + let plugin = ephemeral("foo", "export default 42"); + let resolved = plugin.resolveId("foo"); + equal(resolved, "foo"); + equal(plugin.load(resolved), "export default 42"); +}); + +test("loads an absolute path from memory", () => { + let plugin = ephemeral("src/foo.js", "export default 42"); + let resolved = plugin.resolveId("./foo.js", "src/main.js"); + equal(resolved, resolve("src/foo.js")); + equal(plugin.load(resolved), "export default 42"); +}); diff --git a/packages/rollup-plugin-worker-url/plugin.js b/packages/rollup-plugin-worker-url/plugin.js index 6a98c1b..04e95c5 100644 --- a/packages/rollup-plugin-worker-url/plugin.js +++ b/packages/rollup-plugin-worker-url/plugin.js @@ -29,7 +29,7 @@ export function worker() { if (arg.type === "Literal") { // TODO import.meta.url -> id, otherwise the value let { id: fileId } = await this.resolve(arg.value, id); - let chunkId = this.emitFile({ type: "chunk", id: fileId }); + let chunkId = this.emitFile({ type: "chunk", id: fileId, importer: id }); ms.overwrite(url.start, url.end, `import.meta.ROLLUP_FILE_URL_${chunkId}`); } } diff --git a/packages/rollup-plugin-worker-url/test.js b/packages/rollup-plugin-worker-url/test.js index 445e571..c78f1d4 100644 --- a/packages/rollup-plugin-worker-url/test.js +++ b/packages/rollup-plugin-worker-url/test.js @@ -2,7 +2,7 @@ import { test } from "node:test"; import { equal } from "node:assert/strict"; import { rollup } from "rollup"; -import { ephemeral } from "../rollwright/ephemeral.js"; +import { ephemeral } from "../rollup-plugin-ephemeral/plugin.js"; import worker from "./plugin.js"; test("simple worker import", async () => { diff --git a/packages/rollwright/ephemeral.js b/packages/rollwright/ephemeral.js deleted file mode 100644 index d2bcf2e..0000000 --- a/packages/rollwright/ephemeral.js +++ /dev/null @@ -1,21 +0,0 @@ -import { basename } from "node:path"; - -/** - * @param {string} filename - * @param {string} code - * @returns {import("rollup").Plugin} - */ -export function ephemeral(filename, code) { - let name = basename(filename); - return { - name: "ephemeral_" + name, - resolveId(id, importer) { - if (id === name) return id; - if (importer === name) return this.resolve(id, filename); - return null; - }, - load(id) { - return id === name ? code : null; - }, - }; -} diff --git a/packages/rollwright/fixture.js b/packages/rollwright/fixture.js index 70fcb1f..0fc360e 100644 --- a/packages/rollwright/fixture.js +++ b/packages/rollwright/fixture.js @@ -1,9 +1,9 @@ -import { resolve, relative, dirname, basename } from "node:path"; +import { resolve, dirname, basename } from "node:path"; import { test as base } from "@playwright/test"; import { rollup } from "rollup"; -import { ephemeral } from "./ephemeral.js"; +import { ephemeral } from "../rollup-plugin-ephemeral/plugin.js"; import { createCoverageCollector } from "./coverage-collector.js"; import { nodeResolve } from "@rollup/plugin-node-resolve"; @@ -49,11 +49,9 @@ async function execute({ page, rlcache, plugins, template, extensions, coverage let server = new Hono(); let connect = null; - let pageContent = template.html ?? template; - server.get("/", (ctx) => ctx.html(pageContent)); + server.get("/", (ctx) => ctx.html(template.html ?? template)); - let root = template.root ?? relative(process.cwd(), dirname(testInfo.file)); - let statics = serveStatic({ root }); + let statics = serveStatic({ root: template.root ?? resolve(dirname(testInfo.file)) }); server.notFound(async (ctx) => { let response = await statics(ctx, () => Promise.resolve(null)); return response != null ? response : ctx.body(null, 404); @@ -68,10 +66,10 @@ async function execute({ page, rlcache, plugins, template, extensions, coverage async function evaluate(fn, ...args) { let hash = `step_${++id}`; let code = `window.${hash} = ${fn.toString()};`; - let filename = resolve(dirname(testInfo.file), `${hash}_${basename(testInfo.file)}`); - let input = basename(filename); + let rootDir = dirname(testInfo.file); + let input = `${hash}_${basename(testInfo.file)}`; inputs.push(input); - files.push(ephemeral(filename, code)); + files.push(ephemeral(input, code)); let bundle = await rollup({ cache: rlcache.load(), input: inputs, @@ -91,7 +89,7 @@ async function execute({ page, rlcache, plugins, template, extensions, coverage ], }) : [], - nodeResolve({ browser: true, rootDir: dirname(filename), extensions }), + nodeResolve({ browser: true, rootDir, extensions }), ...files, ], logLevel: "silent", @@ -101,7 +99,7 @@ async function execute({ page, rlcache, plugins, template, extensions, coverage format: "esm", generatedCode: "es2015", preserveModules: true, - dir: dirname(filename), + dir: rootDir, minifyInternalExports: false, }); rlcache.save(bundle.cache);