diff --git a/packages/plugin-vite/src/plugins/patches.ts b/packages/plugin-vite/src/plugins/patches.ts index 841295df5fa..e3c96b3280f 100644 --- a/packages/plugin-vite/src/plugins/patches.ts +++ b/packages/plugin-vite/src/plugins/patches.ts @@ -4,6 +4,7 @@ import { cjsPlugin } from "./patches/commonjs.ts"; import { jsxComments } from "./patches/jsx_comment.ts"; import babelReact from "@babel/preset-react"; import { inlineEnvVarsPlugin } from "./patches/inline_env_vars.ts"; +import { removePolyfills } from "./patches/remove_polyfills.ts"; export function patches(): Plugin { let isDev = false; @@ -33,6 +34,7 @@ export function patches(): Plugin { babelrc: false, plugins: [ cjsPlugin, + removePolyfills, jsxComments, inlineEnvVarsPlugin( isDev ? "development" : "production", diff --git a/packages/plugin-vite/src/plugins/patches/remove_polyfills.ts b/packages/plugin-vite/src/plugins/patches/remove_polyfills.ts new file mode 100644 index 00000000000..879b1ec0979 --- /dev/null +++ b/packages/plugin-vite/src/plugins/patches/remove_polyfills.ts @@ -0,0 +1,32 @@ +import type { PluginObj, types } from "@babel/core"; + +export function removePolyfills( + { types: t }: { types: typeof types }, +): PluginObj { + return { + name: "fresh-remove-polyfills", + visitor: { + IfStatement(path) { + if ( + t.isUnaryExpression(path.node.test) && + path.node.test.operator === "!" && + t.isMemberExpression(path.node.test.argument) && + t.isIdentifier(path.node.test.argument.object) && + ((path.node.test.argument.object.name === "String" && + t.isIdentifier(path.node.test.argument.property) && + path.node.test.argument.property.name === "fromCodePoint") || + (path.node.test.argument.object.name === "Object" && + t.isIdentifier(path.node.test.argument.property) && + (path.node.test.argument.property.name === "keys" || + path.node.test.argument.property.name === "create"))) + ) { + if (path.node.alternate) { + path.replaceWith(t.cloneNode(path.node.alternate, true)); + } else { + path.remove(); + } + } + }, + }, + }; +} diff --git a/packages/plugin-vite/src/plugins/patches/remove_polyfills_test.ts b/packages/plugin-vite/src/plugins/patches/remove_polyfills_test.ts new file mode 100644 index 00000000000..097af1d66e7 --- /dev/null +++ b/packages/plugin-vite/src/plugins/patches/remove_polyfills_test.ts @@ -0,0 +1,87 @@ +import { expect } from "@std/expect/expect"; +import * as babel from "@babel/core"; +import { removePolyfills } from "./remove_polyfills.ts"; + +function runTest(options: { input: string; expected: string }) { + const res = babel.transformSync(options.input, { + filename: "foo.js", + babelrc: false, + plugins: [removePolyfills], + }); + + const output = res?.code ?? ""; + expect(output).toEqual(options.expected); +} + +Deno.test("remove polyfills - Object.keys", () => { + runTest({ + input: `if (!Object.keys) { + Object.keys = function (o) { + var a = [] + for (var i in o) if (o.hasOwnProperty(i)) a.push(i) + return a + } +} + +Object.keys({ foo: "bar" });`, + expected: `Object.keys({ + foo: "bar" +});`, + }); +}); + +Deno.test("remove polyfills - Object.create", () => { + runTest({ + input: `if (!Object.create) { + Object.create = function (o) { + function F () {} + F.prototype = o + var newf = new F() + return newf + } +} + +Object.create({});`, + expected: `Object.create({});`, + }); +}); + +Deno.test("remove polyfills - keep alternate", () => { + runTest({ + input: `if (!Object.create) { + Object.create = function (o) { + function F () {} + F.prototype = o + var newf = new F() + return newf + } +} else { + console.log("foo") +}`, + expected: `{ + console.log("foo"); +}`, + }); +}); + +Deno.test("remove polyfills - String.fromCodePoint", () => { + runTest({ + input: `if (!String.fromCodePoint) { + foo +} + +String.fromCodePoint(42);`, + expected: `String.fromCodePoint(42);`, + }); +}); + +Deno.test("remove polyfills - Keep unrelated unary statements", () => { + runTest({ + input: `if (+String.fromCodePoint) { + foo; +}`, + expected: `if (+String.fromCodePoint) { + foo; +}`, + }); +});