diff --git a/packages/bun-polyfills/tools/bun_test_loader.mjs b/packages/bun-polyfills/tools/bun_test_loader.mjs
index 2466157ce7..c5c6941983 100644
--- a/packages/bun-polyfills/tools/bun_test_loader.mjs
+++ b/packages/bun-polyfills/tools/bun_test_loader.mjs
@@ -3,17 +3,27 @@
///
import { fileURLToPath, pathToFileURL } from 'node:url';
import path from 'node:path';
-import util from 'node:util';
import fs from 'node:fs';
import $ from 'chalk';
import bunwasm from 'bun-wasm';
import { TransformResponseStatus } from 'bun-wasm/schema';
+const testRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'test');
+const tsconfigPath = path.resolve(testRoot, 'tsconfig.json');
+/** @type {Record} */
+let tsconfigPaths = {};
+if (fs.existsSync(tsconfigPath)) {
+ const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf-8'));
+ tsconfigPaths = tsconfig.compilerOptions.paths;
+} else {
+ throw new Error('No tsconfig.json found at: ' + tsconfigPath);
+}
+
await bunwasm.init();
const NO_STACK = () => void 0;
const decoder = new TextDecoder('utf-8');
const libRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'dist', 'src');
-const knownBunModules = ['sqlite', 'ffi', 'jsc', 'test'];
+const knownBunModules = ['sqlite', 'ffi', 'jsc', 'test', 'wrap'];
/** @type {string} */
let mainURL;
@@ -24,13 +34,19 @@ export async function resolve(specifier, context, nextResolve) {
if (specifier.startsWith('bun:')) {
const module = specifier.slice(4);
if (!knownBunModules.includes(module)) {
- const err = new Error(`[bun-polyfills] Unknown or unimplemented bun module "${specifier}"`);
+ const err = new Error(`[bun-polyfills] Unknown or unimplemented bun module "${specifier}" imported from "${context.parentURL}"`);
Error.captureStackTrace(err, NO_STACK);
throw err;
}
- if (module === 'sqlite') throw new Error('bun:sqlite polyfill is not implemented yet');
+ if (module === 'wrap') return { url: 'bun:wrap@' + context.parentURL, format: 'module', shortCircuit: true };
return { url: pathToFileURL(path.resolve(libRoot, 'modules', module + '.js')).href, format: 'module', shortCircuit: true };
}
+ // Not the really an accurate way to do this, but it works for the test suite usages
+ if (Object.keys(tsconfigPaths).includes(specifier)) {
+ const paths = tsconfigPaths[specifier];
+ const resolved = paths.map(p => pathToFileURL(path.resolve(testRoot, p)).href);
+ specifier = resolved[0];
+ }
//console.debug('trying to resolve', specifier, 'from', context.parentURL);
/** @type {Resolve.Return | Error} */
let next;
@@ -68,9 +84,27 @@ export async function resolve(specifier, context, nextResolve) {
else return next;
}
+const APPLY_IMPORT_META_POLYFILL = /*js*/`
+ ;(await import("${pathToFileURL(path.resolve(libRoot, 'global', 'importmeta.js')).href}")).default(import.meta);
+`;
/** @type {load} */
export async function load(url, context, nextLoad) {
//console.debug('Loading', url, 'with context', context);
+ if (url.startsWith('bun:wrap@')) {
+ return {
+ shortCircuit: true, format: 'module', source: /*js*/`
+ import { createRequire } from 'node:module';
+ const require = createRequire(import.meta.url.slice(9));
+ export const __require = require;
+ export default new Proxy({
+ __require: require,
+ }, {
+ get(target, prop) {
+ return target[prop];
+ },
+ });`
+ };
+ }
if (context.format === 'tsmodule' || context.format === 'tscommonjs') {
const filepath = fileURLToPath(url);
const src = fs.readFileSync(filepath, 'utf-8');
@@ -87,29 +121,41 @@ export async function load(url, context, nextLoad) {
return {
shortCircuit: true,
format: /** @type {ModuleFormat} */(context.format.slice(2)),
- source: decoder.decode(transform.files[0].data),
+ source: (context.format === 'tsmodule'
+ ? (url.includes('/bun-polyfills/') ? '' : APPLY_IMPORT_META_POLYFILL)
+ : '') + decoder.decode(transform.files[0].data),
};
}
if (context.format === 'json') context.importAssertions.type = 'json';
+
const loaded = await nextLoad(url, context);
if (url.startsWith('file://') && loaded.format === 'module') {
const src = typeof loaded.source === 'string' ? loaded.source : decoder.decode(loaded.source);
- return { shortCircuit: true, format: 'module', source: src };
+ return {
+ shortCircuit: true,
+ format: 'module',
+ source: (url.includes('/bun-polyfills/') ? '' : APPLY_IMPORT_META_POLYFILL) + src
+ };
}
else return loaded;
}
+/** @type {globalPreload} */
+export function globalPreload(ctx) {
+ return /*js*/`process.env.BUN_POLYFILLS_TEST_RUNNER = 1;`;
+}
+
/** @param {import('bun-wasm/schema').Message[]} buildErrors */
function formatBuildErrors(buildErrors) {
const formatted = buildErrors.map(err => {
const loc = err.data.location;
const str = `${$.redBright('error')}${$.gray(':')} ${$.bold(err.data.text)}\n` +
- (loc
- ? `${highlightErrorChar(loc.line_text, loc.column)}\n` +
+ (loc
+ ? `${highlightErrorChar(loc.line_text, loc.column)}\n` +
$.redBright.bold('^'.padStart(loc.column)) + '\n' +
`${$.bold(loc.file)}${$.gray(':')}${$.yellowBright(loc.line)}${$.gray(':')}${$.yellowBright(loc.column)} ${$.gray(loc.offset)}`
- : ''
- );
+ : ''
+ );
const newerr = new Error(str);
newerr.name = 'BuildError';
newerr.stack = str;