Skip to content

Commit

Permalink
remove eval calls introduced by depd wrapped functions
Browse files Browse the repository at this point in the history
  • Loading branch information
dario-piotrowicz committed Feb 25, 2025
1 parent 12d385d commit 76b6a44
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .changeset/long-items-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@opennextjs/cloudflare": patch
---

remove `eval` calls introduced by `depd` wrapped functions

Some dependencies of Next.js (`raw-body` and `send`) use `depd` to deprecate some of their functions,
`depd` uses `eval` to generate a deprecated version of such functions, this causes `eval` warnings in
the terminal even if these functions are never called, the changes here by patching the depd `wrapfunction`
function so that it still retains the same type of behavior but without using `eval`
2 changes: 2 additions & 0 deletions packages/cloudflare/src/cli/build/bundle-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { inlineFindDir } from "./patches/plugins/find-dir.js";
import { patchLoadInstrumentation } from "./patches/plugins/load-instrumentation.js";
import { inlineLoadManifest } from "./patches/plugins/load-manifest.js";
import { handleOptionalDependencies } from "./patches/plugins/optional-deps.js";
import { patchDepdDeprecations } from "./patches/plugins/patch-depd-deprecations.js";
import { fixRequire } from "./patches/plugins/require.js";
import { shimRequireHook } from "./patches/plugins/require-hook.js";
import { inlineRequirePage } from "./patches/plugins/require-page.js";
Expand Down Expand Up @@ -97,6 +98,7 @@ export async function bundleServer(buildOpts: BuildOptions): Promise<void> {
inlineFindDir(updater, buildOpts),
inlineLoadManifest(updater, buildOpts),
inlineBuildId(updater),
patchDepdDeprecations(updater),
// Apply updater updaters, must be the last plugin
updater.plugin,
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, expect, test } from "vitest";

import { patchCode } from "../ast/util.js";
import { rule } from "./patch-depd-deprecations.js";

describe("patchDepdDeprecations", () => {
test("patch", () => {
const code = `
function prepareObjectStackTrace(e,t){
return t
}
function wrapfunction(fn,message){
if(typeof fn!=="function"){
throw new TypeError("argument fn must be a function")
}
var args=createArgumentsString(fn.length);
var deprecate=this;
var stack=getStack();
var site=callSiteLocation(stack[1]);
site.name=fn.name;
var deprecatedfn=eval("(function ("+args+") {\\n"+'"use strict"\\n'+"log.call(deprecate, message, site)\\n"+"return fn.apply(this, arguments)\\n"+"})");
return deprecatedfn;
}`;

expect(patchCode(code, rule)).toMatchInlineSnapshot(`
"function prepareObjectStackTrace(e,t){
return t
}
function wrapfunction(fn, message) { if(typeof fn !== 'function') throw new Error("argument fn must be a function"); return (...args) => { console.warn(message); return fn(...args); } }"
`);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { patchCode } from "../ast/util.js";
import type { ContentUpdater } from "./content-updater.js";

/**
* Some dependencies of Next.js use depd to deprecate some of their functions, depd uses `eval` to generate
* a deprecated version of such functions, this causes `eval` warnings in the terminal even if these functions
* are never called, this function fixes that by patching the depd `wrapfunction` function so that it still
* retains the same type of behavior but without using `eval`
*/
export function patchDepdDeprecations(updater: ContentUpdater) {
return updater.updateContent(
"patch-depd-deprecations",
{ filter: /\.(js|mjs|cjs|jsx|ts|tsx)$/, contentFilter: /argument fn must be a function/ },
({ contents }) => patchCode(contents, rule)
);
}

export const rule = `
rule:
kind: function_declaration
pattern: function wrapfunction($FN, $MESSAGE) { $$$ }
all:
- has:
kind: variable_declarator
stopBy: end
has:
field: name
pattern: deprecatedfn
- has:
kind: call_expression
stopBy: end
has:
kind: identifier
pattern: eval
fix:
function wrapfunction($FN, $MESSAGE) {
if(typeof $FN !== 'function') throw new Error("argument fn must be a function");
return (...args) => {
console.warn($MESSAGE);
return $FN(...args);
}
}
`;

0 comments on commit 76b6a44

Please sign in to comment.