Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix CommonJS bundling #1012

Merged
merged 3 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,20 @@ export const apis = Object.freeze({
});

const RUNNING_LOCALLY = IS_FS_AVAILABLE && IS_PATH_AVAILABLE;
const dirname__ = RUNNING_LOCALLY
? path.dirname(path.dirname(url.fileURLToPath(import.meta.url)))
: './';

let dirname__ = './';
if (RUNNING_LOCALLY) {
// NOTE: We wrap `import.meta` in a call to `Object` to prevent Webpack from trying to bundle it in CommonJS.
// Although we get the warning: "Accessing import.meta directly is unsupported (only property access or destructuring is supported)",
// it is safe to ignore since the bundled value (`{}`) isn't used for CommonJS environments (we use __dirname instead).
const _import_meta_url = Object(import.meta).url;

if (_import_meta_url) {
dirname__ = path.dirname(path.dirname(url.fileURLToPath(_import_meta_url))) // ESM
} else if (typeof __dirname !== 'undefined') {
dirname__ = path.dirname(__dirname) // CommonJS
}
}

// Only used for environments with access to file system
const DEFAULT_CACHE_DIR = RUNNING_LOCALLY
Expand Down
37 changes: 37 additions & 0 deletions tests/bundles.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { spawnSync } from "child_process";

const MODULE_NAME = "@huggingface/transformers";

const CODE_BODY = `
const model_id = "hf-internal-testing/tiny-random-LlamaForCausalLM";
const generator = await pipeline("text-generation", model_id, { dtype: "fp32" });
const result = await generator("hello", { max_new_tokens: 3, return_full_text: false });
process.stdout.write(result[0].generated_text);
`;

const TARGET_OUTPUT = "erdingsAndroid Load";

const wrap_async_iife = (code) => `(async function() { ${code} })();`;

const check = (code, module = false) => {
const args = ["-e", code];
if (module) args.push("--input-type=module");
const { status, stdout, stderr } = spawnSync("node", args);
expect(stderr.toString()).toBe(""); // No warnings or errors are printed
expect(stdout.toString()).toBe(TARGET_OUTPUT); // The output should match
expect(status).toBe(0); // The process should exit cleanly
};

describe("Testing the bundle", () => {
it("ECMAScript Module (ESM)", () => {
check(`import { pipeline } from "${MODULE_NAME}";${CODE_BODY}`, true);
});

it("CommonJS (CJS) with require", () => {
check(`const { pipeline } = require("${MODULE_NAME}");${wrap_async_iife(CODE_BODY)}`);
});

it("CommonJS (CJS) with dynamic import", () => {
check(`${wrap_async_iife(`const { pipeline } = await import("${MODULE_NAME}");${CODE_BODY}`)}`);
});
});
Loading