Skip to content

Commit f29b0b0

Browse files
authored
use the native node:punycode when available (#10882)
1 parent f4a92fd commit f29b0b0

File tree

4 files changed

+87
-0
lines changed

4 files changed

+87
-0
lines changed

.changeset/thirty-windows-own.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@cloudflare/unenv-preset": patch
3+
---
4+
5+
Use the native `node:punycode` module when available.
6+
7+
It is enabled when the `enable_nodejs_punycode_module` compatibility flag is set.

packages/unenv-preset/src/preset.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export function getCloudflarePreset({
7272
const http2Overrides = getHttp2Overrides(compat);
7373
const osOverrides = getOsOverrides(compat);
7474
const fsOverrides = getFsOverrides(compat);
75+
const punycodeOverrides = getPunycodeOverrides(compat);
7576

7677
// "dynamic" as they depend on the compatibility date and flags
7778
const dynamicNativeModules = [
@@ -80,6 +81,7 @@ export function getCloudflarePreset({
8081
...http2Overrides.nativeModules,
8182
...osOverrides.nativeModules,
8283
...fsOverrides.nativeModules,
84+
...punycodeOverrides.nativeModules,
8385
];
8486

8587
// "dynamic" as they depend on the compatibility date and flags
@@ -89,6 +91,7 @@ export function getCloudflarePreset({
8991
...http2Overrides.hybridModules,
9092
...osOverrides.hybridModules,
9193
...fsOverrides.hybridModules,
94+
...punycodeOverrides.hybridModules,
9295
];
9396

9497
return {
@@ -305,3 +308,41 @@ function getFsOverrides({
305308
hybridModules: [],
306309
};
307310
}
311+
312+
/**
313+
* Returns the overrides for `node:punycode` (unenv or workerd)
314+
*
315+
* The native punycode implementation:
316+
* - is experimental
317+
* - can be enabled with the "enable_nodejs_punycode_module" flag
318+
* - can be disabled with the "disable_nodejs_punycode_module" flag
319+
*/
320+
function getPunycodeOverrides({
321+
// eslint-disable-next-line unused-imports/no-unused-vars
322+
compatibilityDate,
323+
compatibilityFlags,
324+
}: {
325+
compatibilityDate: string;
326+
compatibilityFlags: string[];
327+
}): { nativeModules: string[]; hybridModules: string[] } {
328+
const disabledByFlag = compatibilityFlags.includes(
329+
"disable_nodejs_punycode_module"
330+
);
331+
332+
// TODO: add `enabledByDate` when a date is defined in workerd
333+
const enabledByFlag =
334+
compatibilityFlags.includes("enable_nodejs_punycode_module") &&
335+
compatibilityFlags.includes("experimental");
336+
337+
const enabled = enabledByFlag && !disabledByFlag;
338+
339+
return enabled
340+
? {
341+
nativeModules: ["punycode"],
342+
hybridModules: [],
343+
}
344+
: {
345+
nativeModules: [],
346+
hybridModules: [],
347+
};
348+
}

packages/wrangler/e2e/unenv-preset/preset.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,28 @@ const testConfigs: TestConfig[] = [
231231
},
232232
},
233233
],
234+
// node:punycode
235+
[
236+
// TODO: add test for disabled by date (no date defined yet)
237+
// TODO: add test for enabled by date (no date defined yet)
238+
{
239+
name: "punycode enabled by flag",
240+
compatibilityDate: "2024-09-23",
241+
compatibilityFlags: ["enable_nodejs_punycode_module", "experimental"],
242+
expectRuntimeFlags: {
243+
enable_nodejs_punycode_module: true,
244+
},
245+
},
246+
// TODO: update the date past the default enable date (when defined)
247+
{
248+
name: "punycode disabled by flag",
249+
compatibilityDate: "2024-09-23",
250+
compatibilityFlags: ["disable_nodejs_punycode_module", "experimental"],
251+
expectRuntimeFlags: {
252+
enable_nodejs_punycode_module: false,
253+
},
254+
},
255+
],
234256
].flat() as TestConfig[];
235257

236258
describe.each(testConfigs)(

packages/wrangler/e2e/unenv-preset/worker/index.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,4 +544,21 @@ export const WorkerdTests: Record<string, () => void> = {
544544
assert.equal(typeof gProcess.removeListener, "function");
545545
assert.equal(typeof gProcess.setMaxListeners, "function");
546546
},
547+
548+
async testPunycode() {
549+
const punycode = await import("node:punycode");
550+
551+
assert.strictEqual(typeof punycode.decode, "function");
552+
assert.strictEqual(typeof punycode.encode, "function");
553+
assert.strictEqual(typeof punycode.toASCII, "function");
554+
assert.strictEqual(typeof punycode.toUnicode, "function");
555+
assert.strictEqual(
556+
punycode.toASCII("Bücher@日本語.com"),
557+
558+
);
559+
assert.strictEqual(
560+
punycode.toUnicode("Bü[email protected]"),
561+
"Bücher@日本語.com"
562+
);
563+
},
547564
};

0 commit comments

Comments
 (0)