Skip to content
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
5 changes: 5 additions & 0 deletions .changeset/native-stream-wrap-module.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudflare/unenv-preset": minor
---

Add support for native `node:_stream_wrap` module when the `enable_nodejs_stream_wrap_module` compatibility flag is enabled. This feature is currently experimental and requires `nodejs_compat`, `experimental`, and `enable_nodejs_stream_wrap_module` compatibility flags to be set.
1 change: 1 addition & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ updates:
- "c3"
- "dependencies"
- "skip-pr-description-validation"
- "skip-changeset-review"

# Check for workerd & workers-types updates for Miniflare
- package-ecosystem: "npm"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/changeset-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ jobs:
1. **Version Type**: Correct patch/minor/major (major forbidden for wrangler)
2. **Changelog Quality**: Meaningful descriptions with examples for features
3. **Markdown Headers**: No h1/h2/h3 headers (breaks changelog formatting)
4. **Analytics**: If the change collects more analytics, it should be a minor even though there is no user-visible change
5. **Dependabot**: Do not validate dependency update changesets for create-cloudflare
If all changesets pass, just output "✅ All changesets look good" - no need for a detailed checklist.
Expand Down
39 changes: 39 additions & 0 deletions packages/unenv-preset/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export function getCloudflarePreset({
const inspectorOverrides = getInspectorOverrides(compat);
const sqliteOverrides = getSqliteOverrides(compat);
const dgramOverrides = getDgramOverrides(compat);
const streamWrapOverrides = getStreamWrapOverrides(compat);

// "dynamic" as they depend on the compatibility date and flags
const dynamicNativeModules = [
Expand All @@ -100,6 +101,7 @@ export function getCloudflarePreset({
...inspectorOverrides.nativeModules,
...sqliteOverrides.nativeModules,
...dgramOverrides.nativeModules,
...streamWrapOverrides.nativeModules,
];

// "dynamic" as they depend on the compatibility date and flags
Expand All @@ -119,6 +121,7 @@ export function getCloudflarePreset({
...inspectorOverrides.hybridModules,
...sqliteOverrides.hybridModules,
...dgramOverrides.hybridModules,
...streamWrapOverrides.hybridModules,
];

return {
Expand Down Expand Up @@ -713,3 +716,39 @@ function getDgramOverrides({
hybridModules: [],
};
}

/**
* Returns the overrides for `node:_stream_wrap` (unenv or workerd)
*
* The native _stream_wrap implementation:
* - is experimental and has no default enable date
* - can be enabled with the "enable_nodejs_stream_wrap_module" flag
* - can be disabled with the "disable_nodejs_stream_wrap_module" flag
*/
function getStreamWrapOverrides({
compatibilityFlags,
}: {
compatibilityDate: string;
compatibilityFlags: string[];
}): { nativeModules: string[]; hybridModules: string[] } {
const disabledByFlag = compatibilityFlags.includes(
"disable_nodejs_stream_wrap_module"
);

const enabledByFlag =
compatibilityFlags.includes("enable_nodejs_stream_wrap_module") &&
compatibilityFlags.includes("experimental");

const enabled = enabledByFlag && !disabledByFlag;

// When enabled, use the native `_stream_wrap` module from workerd
return enabled
? {
nativeModules: ["_stream_wrap"],
hybridModules: [],
}
: {
nativeModules: [],
hybridModules: [],
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ const testCases: TestCase[] = [
}),
expectFetchToMatch: [expect.stringContaining(`image/avif`)],
},
// TODO: re-enable when Media binding is stable again
// (this is an unreleased feature that temporarily broke in the course of development)
// {
// name: "Media",
// scriptPath: "media.js",
Expand Down
125 changes: 103 additions & 22 deletions packages/wrangler/e2e/unenv-preset/preset.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,21 @@ const localTestConfigs: TestConfig[] = [
],
// node:punycode
[
// TODO: add test for disabled by date (2025-12-04)
// TODO: add test for enabled by date (2025-12-04)
{
name: "punycode enabled by date",
compatibilityDate: "2025-12-04",
compatibilityFlags: ["enable_nodejs_punycode_module"],
expectRuntimeFlags: {
enable_nodejs_punycode_module: true,
},
},
{
name: "punycode disabled by date",
compatibilityDate: "2024-09-23",
expectRuntimeFlags: {
enable_nodejs_punycode_module: false,
},
},
{
name: "punycode enabled by flag",
compatibilityDate: "2024-09-23",
Expand All @@ -279,10 +292,9 @@ const localTestConfigs: TestConfig[] = [
enable_nodejs_punycode_module: true,
},
},
// TODO: update the date past the default enable date (2025-12-04)
{
name: "punycode disabled by flag",
compatibilityDate: "2024-09-23",
compatibilityDate: "2025-12-04",
compatibilityFlags: ["disable_nodejs_punycode_module"],
expectRuntimeFlags: {
enable_nodejs_punycode_module: false,
Expand All @@ -291,8 +303,20 @@ const localTestConfigs: TestConfig[] = [
],
// node:cluster
[
// TODO: add test for disabled by date (2025-12-04)
// TODO: add test for enabled by date (2025-12-04)
{
name: "cluster enabled by date",
compatibilityDate: "2025-12-04",
expectRuntimeFlags: {
enable_nodejs_cluster_module: true,
},
},
{
name: "cluster disabled by date",
compatibilityDate: "2024-09-23",
expectRuntimeFlags: {
enable_nodejs_cluster_module: false,
},
},
{
name: "cluster enabled by flag",
compatibilityDate: "2024-09-23",
Expand All @@ -301,10 +325,9 @@ const localTestConfigs: TestConfig[] = [
enable_nodejs_cluster_module: true,
},
},
// TODO: update the date past the default enable date (2025-12-04)
{
name: "cluster disabled by flag",
compatibilityDate: "2024-09-23",
compatibilityDate: "2025-12-04",
compatibilityFlags: ["disable_nodejs_cluster_module"],
expectRuntimeFlags: {
enable_nodejs_cluster_module: false,
Expand All @@ -313,8 +336,20 @@ const localTestConfigs: TestConfig[] = [
],
// trace_events
[
// TODO: add test for disabled by date (2025-12-04)
// TODO: add test for enabled by date (2025-12-04)
{
name: "trace_events enabled by date",
compatibilityDate: "2025-12-04",
expectRuntimeFlags: {
enable_nodejs_trace_events_module: true,
},
},
{
name: "trace_events disabled by date",
compatibilityDate: "2024-09-23",
expectRuntimeFlags: {
enable_nodejs_trace_events_module: false,
},
},
{
name: "trace_events enabled by flag",
compatibilityDate: "2024-09-23",
Expand All @@ -323,10 +358,9 @@ const localTestConfigs: TestConfig[] = [
enable_nodejs_trace_events_module: true,
},
},
// TODO: update the date past the default enable date (2025-12-04)
{
name: "trace_events disabled by flag",
compatibilityDate: "2024-09-23",
compatibilityDate: "2025-12-04",
compatibilityFlags: ["disable_nodejs_trace_events_module"],
expectRuntimeFlags: {
enable_nodejs_trace_events_module: false,
Expand All @@ -335,8 +369,20 @@ const localTestConfigs: TestConfig[] = [
],
// domain
[
// TODO: add test for disabled by date (2025-12-04)
// TODO: add test for enabled by date (2025-12-04)
{
name: "domain enabled by date",
compatibilityDate: "2025-12-04",
expectRuntimeFlags: {
enable_nodejs_domain_module: true,
},
},
{
name: "domain disabled by date",
compatibilityDate: "2024-09-23",
expectRuntimeFlags: {
enable_nodejs_domain_module: false,
},
},
{
name: "domain enabled by flag",
compatibilityDate: "2024-09-23",
Expand All @@ -345,10 +391,9 @@ const localTestConfigs: TestConfig[] = [
enable_nodejs_domain_module: true,
},
},
// TODO: update the date past the default enable date (2025-12-04)
{
name: "domain disabled by flag",
compatibilityDate: "2024-09-23",
compatibilityDate: "2025-12-04",
compatibilityFlags: ["disable_nodejs_domain_module"],
expectRuntimeFlags: {
enable_nodejs_domain_module: false,
Expand All @@ -357,21 +402,32 @@ const localTestConfigs: TestConfig[] = [
],
// wasi
[
// TODO: add test for disabled by date (no date defined yet)
// TODO: add test for enabled by date (no date defined yet)
{
name: "wasi enabled by date",
compatibilityDate: "2025-12-04",
expectRuntimeFlags: {
enable_nodejs_wasi_module: true,
},
},
{
name: "wasi disabled by date",
compatibilityDate: "2024-09-23",
expectRuntimeFlags: {
enable_nodejs_wasi_module: false,
},
},
{
name: "wasi enabled by flag",
compatibilityDate: "2024-09-23",
compatibilityFlags: ["enable_nodejs_wasi_module", "experimental"],
compatibilityFlags: ["enable_nodejs_wasi_module"],
expectRuntimeFlags: {
enable_nodejs_wasi_module: true,
},
},
// TODO: update the date past the default enable date (when defined)
{
name: "wasi disabled by flag",
compatibilityDate: "2024-09-23",
compatibilityFlags: ["disable_nodejs_wasi_module", "experimental"],
compatibilityDate: "2025-12-04",
compatibilityFlags: ["disable_nodejs_wasi_module"],
expectRuntimeFlags: {
enable_nodejs_wasi_module: false,
},
Expand Down Expand Up @@ -412,6 +468,8 @@ const localTestConfigs: TestConfig[] = [
],
// node:inspector and node:inspector/promises (experimental, no default enable date)
[
// TODO: add test for disabled by date (no date defined yet)
// TODO: add test for enabled by date (no date defined yet)
{
name: "inspector enabled by flag",
compatibilityDate: "2024-09-23",
Expand All @@ -420,6 +478,7 @@ const localTestConfigs: TestConfig[] = [
enable_nodejs_inspector_module: true,
},
},
// TODO: update the date past the default enable date (when defined)
{
name: "inspector disabled by flag",
compatibilityDate: "2024-09-23",
Expand Down Expand Up @@ -472,6 +531,28 @@ const localTestConfigs: TestConfig[] = [
},
},
],
// node:_stream_wrap (experimental, no default enable date)
[
// TODO: add test for disabled by date (no date defined yet)
// TODO: add test for enabled by date (no date defined yet)
{
name: "_stream_wrap enabled by flag",
compatibilityDate: "2024-09-23",
compatibilityFlags: ["enable_nodejs_stream_wrap_module", "experimental"],
expectRuntimeFlags: {
enable_nodejs_stream_wrap_module: true,
},
},
// TODO: update the date past the default enable date (when defined)
{
name: "_stream_wrap disabled by flag",
compatibilityDate: "2024-09-23",
compatibilityFlags: ["disable_nodejs_stream_wrap_module", "experimental"],
expectRuntimeFlags: {
enable_nodejs_stream_wrap_module: false,
},
},
],
].flat() as TestConfig[];

describe.each(localTestConfigs)(
Expand Down
13 changes: 13 additions & 0 deletions packages/wrangler/e2e/unenv-preset/worker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,19 @@ export const WorkerdTests: Record<string, () => void> = {
Socket: "function",
});
},

async testStreamWrap() {
if (!getRuntimeFlagValue("enable_nodejs_stream_wrap_module")) {
// `node:_stream_wrap` is implemented as a mock in unenv
return;
}

// @ts-expect-error TS2307 - _stream_wrap is an internal Node.js module without type declarations
const streamWrap = await import("node:_stream_wrap");

// `JSStreamSocket` is the default export of `node:_stream_wrap`
assertTypeOf(streamWrap, "default", "function");
},
};

/**
Expand Down
Loading