Skip to content
Open
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
4 changes: 4 additions & 0 deletions packages/nodejs/src/polyfills.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const WEB_STREAMS_PONYFILL_PATH = require.resolve(

const CUSTOM_POLYFILL_ENTRY_POINTS = new Map([
["crypto", resolveCustomPolyfillSource("crypto.js")],
["path", resolveCustomPolyfillSource("path.js")],
["stream/web", resolveCustomPolyfillSource("stream-web.js")],
["util/types", resolveCustomPolyfillSource("util-types.js")],
["internal/webstreams/util", resolveCustomPolyfillSource("internal-webstreams-util.js")],
Expand Down Expand Up @@ -60,6 +61,9 @@ export async function bundlePolyfill(moduleName: string): Promise<string> {
if (typeof stdLibBrowser.crypto === "string") {
alias.__secure_exec_crypto_browserify__ = stdLibBrowser.crypto;
}
if (typeof stdLibBrowser.path === "string") {
alias.__secure_exec_path_browserify__ = stdLibBrowser.path;
}
alias["web-streams-polyfill/dist/ponyfill.js"] = WEB_STREAMS_PONYFILL_PATH;

// Bundle using esbuild with CommonJS format
Expand Down
74 changes: 74 additions & 0 deletions packages/nodejs/src/polyfills/path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Custom path polyfill wrapper — adds Node.js ERR_* error codes to path-browserify errors
// Fixes https://github.com/rivet-dev/secure-exec/issues/28
//
// path-browserify throws plain TypeError for invalid arguments.
// Real Node.js attaches a `.code` property (e.g., ERR_INVALID_ARG_TYPE).
// This wrapper catches those errors and adds the missing code before re-throwing.

import pathBrowserify from "__secure_exec_path_browserify__";

function wrapPathFn(fn) {
return function () {
try {
return fn.apply(this, arguments);
} catch (err) {
if (err instanceof TypeError && !err.code) {
err.code = "ERR_INVALID_ARG_TYPE";
}
throw err;
}
};
}

// Build wrapped module that mirrors path-browserify's exports
const wrapped = {};
const keys = Object.keys(pathBrowserify);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (typeof pathBrowserify[key] === "function") {
wrapped[key] = wrapPathFn(pathBrowserify[key]);
} else {
wrapped[key] = pathBrowserify[key];
}
}

// Wrap posix sub-object functions too (path.posix.join, etc.)
if (pathBrowserify.posix && typeof pathBrowserify.posix === "object") {
const wrappedPosix = {};
const posixKeys = Object.keys(pathBrowserify.posix);
for (let j = 0; j < posixKeys.length; j++) {
const pk = posixKeys[j];
if (typeof pathBrowserify.posix[pk] === "function") {
wrappedPosix[pk] = wrapPathFn(pathBrowserify.posix[pk]);
} else {
wrappedPosix[pk] = pathBrowserify.posix[pk];
}
}
wrappedPosix.posix = wrappedPosix;
wrapped.posix = wrappedPosix;
} else {
// path-browserify sets posix = module.exports (self-reference)
wrapped.posix = wrapped;
}

// Preserve standard path properties
wrapped.sep = pathBrowserify.sep || "/";
wrapped.delimiter = pathBrowserify.delimiter || ":";

// Named exports for common path functions
export const join = wrapped.join;
export const resolve = wrapped.resolve;
export const normalize = wrapped.normalize;
export const isAbsolute = wrapped.isAbsolute;
export const relative = wrapped.relative;
export const dirname = wrapped.dirname;
export const basename = wrapped.basename;
export const extname = wrapped.extname;
export const parse = wrapped.parse;
export const format = wrapped.format;
export const toNamespacedPath = wrapped.toNamespacedPath;
export const sep = wrapped.sep;
export const delimiter = wrapped.delimiter;
export const posix = wrapped.posix;

export default wrapped;