aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/builtins/codegen
diff options
context:
space:
mode:
authorGravatar dave caruso <me@paperdave.net> 2023-06-01 21:16:47 -0400
committerGravatar GitHub <noreply@github.com> 2023-06-01 18:16:47 -0700
commit4df1d37ddc54242c339765f22fb90ba2e9e3a99a (patch)
treed63ede76463e7ecba78a4d4b31e5e8158193552f /src/bun.js/builtins/codegen
parent03ffd1c732aaaa30b5481f197221ce96da559e63 (diff)
downloadbun-4df1d37ddc54242c339765f22fb90ba2e9e3a99a.tar.gz
bun-4df1d37ddc54242c339765f22fb90ba2e9e3a99a.tar.zst
bun-4df1d37ddc54242c339765f22fb90ba2e9e3a99a.zip
Bundle and minify `.exports.js` files. (#3036)
* move all exports.js into src/js * finalize the sort of this * and it works * add test.ts to gitignore * okay * convert some to ts just to show * finish up * fixup makefile * minify syntax in dev * finish rebase * dont minify all modules * merge * finish rebase merge * flaky test that hangs
Diffstat (limited to 'src/bun.js/builtins/codegen')
-rw-r--r--src/bun.js/builtins/codegen/builtin-parser.ts89
-rw-r--r--src/bun.js/builtins/codegen/helpers.ts25
-rw-r--r--src/bun.js/builtins/codegen/index.ts624
-rw-r--r--src/bun.js/builtins/codegen/replacements.ts100
4 files changed, 0 insertions, 838 deletions
diff --git a/src/bun.js/builtins/codegen/builtin-parser.ts b/src/bun.js/builtins/codegen/builtin-parser.ts
deleted file mode 100644
index e96d79c63..000000000
--- a/src/bun.js/builtins/codegen/builtin-parser.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import { applyReplacements } from "./replacements";
-
-/**
- * Slices a string until it hits a }, but keeping in mind JS comments,
- * regex, template literals, comments, and matching {
- *
- * Used to extract function bodies without parsing the code.
- *
- * If you pass replace=true, it will run replacements on the code
- */
-export function sliceSourceCode(
- contents: string,
- replace: boolean,
-): { result: string; rest: string; usesThis: boolean } {
- let bracketCount = 0;
- let i = 0;
- let result = "";
- let usesThis = false;
- while (contents.length) {
- // TODO: template literal, regexp
- // these are important because our replacement logic would replace intrinsics
- // within these, when it should remain as the literal dollar.
- // but this isn't used in the codebase
- i = contents.match(/\/\*|\/\/|'|"|{|}|`/)?.index ?? contents.length;
- const chunk = replace ? applyReplacements(contents.slice(0, i)) : contents.slice(0, i);
- if (chunk.includes("this")) usesThis = true;
- result += chunk;
- contents = contents.slice(i);
- if (!contents.length) break;
- if (contents.startsWith("/*")) {
- i = contents.slice(2).indexOf("*/") + 2;
- } else if (contents.startsWith("//")) {
- i = contents.slice(2).indexOf("\n") + 2;
- } else if (contents.startsWith("'")) {
- i = contents.slice(1).match(/(?<!\\)'/)!.index! + 2;
- } else if (contents.startsWith('"')) {
- i = contents.slice(1).match(/(?<!\\)"/)!.index! + 2;
- } else if (contents.startsWith("`")) {
- const { result: result2, rest } = sliceTemplateLiteralSourceCode(contents.slice(1), replace);
- result += "`" + result2;
- contents = rest;
- continue;
- } else if (contents.startsWith("{")) {
- bracketCount++;
- i = 1;
- } else if (contents.startsWith("}")) {
- bracketCount--;
- if (bracketCount <= 0) {
- result += "}";
- contents = contents.slice(1);
- break;
- }
- i = 1;
- } else {
- throw new Error("TODO");
- }
- result += contents.slice(0, i);
- contents = contents.slice(i);
- }
-
- return { result, rest: contents, usesThis };
-}
-
-function sliceTemplateLiteralSourceCode(contents: string, replace: boolean) {
- let i = 0;
- let result = "";
- let usesThis = false;
- while (contents.length) {
- i = contents.match(/`|\${/)!.index!;
- result += contents.slice(0, i);
- contents = contents.slice(i);
- if (!contents.length) break;
- if (contents.startsWith("`")) {
- result += "`";
- contents = contents.slice(1);
- break;
- } else if (contents.startsWith("$")) {
- const { result: result2, rest, usesThis: usesThisVal } = sliceSourceCode(contents.slice(1), replace);
- result += "$" + result2;
- contents = rest;
- usesThis ||= usesThisVal;
- continue;
- } else {
- throw new Error("TODO");
- }
- }
-
- return { result, rest: contents, usesThis };
-}
diff --git a/src/bun.js/builtins/codegen/helpers.ts b/src/bun.js/builtins/codegen/helpers.ts
deleted file mode 100644
index 6345f8ffa..000000000
--- a/src/bun.js/builtins/codegen/helpers.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export function fmtCPPString(str: string) {
- return (
- '"' +
- str
- .replace(/\\/g, "\\\\")
- .replace(/"/g, '\\"')
- .replace(/\n/g, "\\n")
- .replace(/\r/g, "\\r")
- .replace(/\t/g, "\\t")
- .replace(/\?/g, "\\?") + // https://stackoverflow.com/questions/1234582
- '"'
- );
-}
-
-export function cap(str: string) {
- return str[0].toUpperCase() + str.slice(1);
-}
-
-export function low(str: string) {
- if (str.startsWith("JS")) {
- return "js" + str.slice(2);
- }
-
- return str[0].toLowerCase() + str.slice(1);
-}
diff --git a/src/bun.js/builtins/codegen/index.ts b/src/bun.js/builtins/codegen/index.ts
deleted file mode 100644
index c9e44ec06..000000000
--- a/src/bun.js/builtins/codegen/index.ts
+++ /dev/null
@@ -1,624 +0,0 @@
-import { existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from "fs";
-import path from "path";
-import { sliceSourceCode } from "./builtin-parser";
-import { applyGlobalReplacements, enums, globalsToPrefix } from "./replacements";
-import { cap, fmtCPPString, low } from "./helpers";
-
-console.log("Bundling Bun builtins...");
-
-const MINIFY = process.argv.includes("--minify") || process.argv.includes("-m");
-const PARALLEL = process.argv.includes("--parallel") || process.argv.includes("-p");
-const KEEP_TMP = process.argv.includes("--keep-tmp") || process.argv.includes("-k");
-
-const SRC_DIR = path.join(import.meta.dir, "../ts");
-const OUT_DIR = path.join(import.meta.dir, "../");
-const TMP_DIR = path.join(import.meta.dir, "../out");
-
-if (existsSync(TMP_DIR)) rmSync(TMP_DIR, { recursive: true });
-mkdirSync(TMP_DIR);
-
-const define = {
- "process.env.NODE_ENV": "development",
- "process.platform": process.platform,
- "process.arch": process.arch,
-};
-
-for (const name in enums) {
- const value = enums[name];
- if (typeof value !== "object") throw new Error("Invalid enum object " + name + " defined in " + import.meta.file);
- if (typeof value === null) throw new Error("Invalid enum object " + name + " defined in " + import.meta.file);
- const keys = Array.isArray(value) ? value : Object.keys(value).filter(k => !k.match(/^[0-9]+$/));
- define[`__intrinsic__${name}IdToLabel`] = "[" + keys.map(k => `"${k}"`).join(", ") + "]";
- define[`__intrinsic__${name}LabelToId`] = "{" + keys.map(k => `"${k}": ${keys.indexOf(k)}`).join(", ") + "}";
-}
-
-for (const name of globalsToPrefix) {
- define[name] = "__intrinsic__" + name;
-}
-
-interface ParsedBuiltin {
- name: string;
- params: string[];
- directives: Record<string, any>;
- source: string;
- async: boolean;
-}
-interface BundledBuiltin {
- name: string;
- directives: Record<string, any>;
- isGetter: boolean;
- isConstructor: boolean;
- isLinkTimeConstant: boolean;
- isNakedConstructor: boolean;
- intrinsic: string;
- overriddenName: string;
- source: string;
- params: string[];
- visibility: string;
-}
-
-/**
- * Source .ts file --> Array<bundled js function code>
- */
-async function processFileSplit(filename: string): Promise<{ functions: BundledBuiltin[]; internal: boolean }> {
- const basename = path.basename(filename, ".ts");
- let contents = await Bun.file(filename).text();
-
- contents = applyGlobalReplacements(contents);
-
- // first approach doesnt work perfectly because we actually need to split each function declaration
- // and then compile those separately
-
- const consumeWhitespace = /^\s*/;
- const consumeTopLevelContent = /^(\/\*|\/\/|type|import|interface|\$|export (?:async )?function|(?:async )?function)/;
- const consumeEndOfType = /;|.(?=export|type|interface|\$|\/\/|\/\*|function)/;
-
- const functions: ParsedBuiltin[] = [];
- let directives: Record<string, any> = {};
- const bundledFunctions: BundledBuiltin[] = [];
- let internal = false;
-
- while (contents.length) {
- contents = contents.replace(consumeWhitespace, "");
- if (!contents.length) break;
- const match = contents.match(consumeTopLevelContent);
- if (!match) {
- throw new SyntaxError("Could not process input:\n" + contents.slice(0, contents.indexOf("\n")));
- }
- contents = contents.slice(match.index!);
- if (match[1] === "import") {
- // TODO: we may want to do stuff with these
- const i = contents.indexOf(";");
- contents = contents.slice(i + 1);
- } else if (match[1] === "/*") {
- const i = contents.indexOf("*/") + 2;
- internal ||= contents.slice(0, i).includes("@internal");
- contents = contents.slice(i);
- } else if (match[1] === "//") {
- const i = contents.indexOf("\n") + 1;
- internal ||= contents.slice(0, i).includes("@internal");
- contents = contents.slice(i);
- } else if (match[1] === "type" || match[1] === "export type") {
- const i = contents.search(consumeEndOfType);
- contents = contents.slice(i + 1);
- } else if (match[1] === "interface") {
- contents = sliceSourceCode(contents, false).rest;
- } else if (match[1] === "$") {
- const directive = contents.match(/^\$([a-zA-Z0-9]+)(?:\s*=\s*([^\n]+?))?\s*;?\n/);
- if (!directive) {
- throw new SyntaxError("Could not parse directive:\n" + contents.slice(0, contents.indexOf("\n")));
- }
- const name = directive[1];
- let value;
- try {
- value = directive[2] ? JSON.parse(directive[2]) : true;
- } catch (error) {
- throw new SyntaxError("Could not parse directive value " + directive[2] + " (must be JSON parsable)");
- }
- if (name === "constructor") {
- throw new SyntaxError("$constructor not implemented");
- }
- if (name === "nakedConstructor") {
- throw new SyntaxError("$nakedConstructor not implemented");
- }
- directives[name] = value;
- contents = contents.slice(directive[0].length);
- } else if (match[1] === "export function" || match[1] === "export async function") {
- const declaration = contents.match(
- /^export\s+(async\s+)?function\s+([a-zA-Z0-9]+)\s*\(([^)]*)\)(?:\s*:\s*([^{\n]+))?\s*{?/,
- );
- if (!declaration)
- throw new SyntaxError("Could not parse function declaration:\n" + contents.slice(0, contents.indexOf("\n")));
-
- const async = !!declaration[1];
- const name = declaration[2];
- const paramString = declaration[3];
- const params =
- paramString.trim().length === 0 ? [] : paramString.split(",").map(x => x.replace(/:.+$/, "").trim());
- if (params[0] === "this") {
- params.shift();
- }
-
- const { result, rest } = sliceSourceCode(contents.slice(declaration[0].length - 1), true);
- functions.push({
- name,
- params,
- directives,
- source: result.trim().slice(1, -1),
- async,
- });
- contents = rest;
- directives = {};
- } else if (match[1] === "function" || match[1] === "async function") {
- const fnname = contents.match(/^function ([a-zA-Z0-9]+)\(([^)]*)\)(?:\s*:\s*([^{\n]+))?\s*{?/)![1];
- throw new SyntaxError("All top level functions must be exported: " + fnname);
- } else {
- throw new Error("TODO: parse " + match[1]);
- }
- }
-
- for (const fn of functions) {
- const tmpFile = path.join(TMP_DIR, `${basename}.${fn.name}.ts`);
-
- // not sure if this optimization works properly in jsc builtins
- // const useThis = fn.usesThis;
- const useThis = true;
-
- // TODO: we should use format=IIFE so we could bundle imports and extra functions.
- await Bun.write(
- tmpFile,
- `// @ts-nocheck
-// GENERATED TEMP FILE - DO NOT EDIT
-// Sourced from ${path.relative(TMP_DIR, filename)}
-
-// do not allow the bundler to rename a symbol to $
-($);
-
-$$capture_start$$(${fn.async ? "async " : ""}${
- useThis
- ? `function(${fn.params.join(",")})`
- : `${fn.params.length === 1 ? fn.params[0] : `(${fn.params.join(",")})`}=>`
- } {${fn.source}}).$$capture_end$$;
-`,
- );
- await Bun.sleep(1);
- const build = await Bun.build({
- entrypoints: [tmpFile],
- define,
- minify: true,
- });
- if (!build.success) {
- throw new AggregateError(build.logs, "Failed bundling builtin function " + fn.name + " from " + basename + ".ts");
- }
- if (build.outputs.length !== 1) {
- throw new Error("expected one output");
- }
- const output = await build.outputs[0].text();
- const captured = output.match(/\$\$capture_start\$\$([\s\S]+)\.\$\$capture_end\$\$/)![1];
- const finalReplacement =
- (fn.directives.sloppy ? captured : captured.replace(/function\s*\(.*?\)\s*{/, '$&"use strict";'))
- .replace(/^\((async )?function\(/, "($1function (")
- .replace(/__intrinsic__/g, "@") + "\n";
-
- bundledFunctions.push({
- name: fn.name,
- directives: fn.directives,
- source: finalReplacement,
- params: fn.params,
- visibility: fn.directives.visibility ?? (fn.directives.linkTimeConstant ? "Private" : "Public"),
- isGetter: !!fn.directives.getter,
- isConstructor: !!fn.directives.constructor,
- isLinkTimeConstant: !!fn.directives.linkTimeConstant,
- isNakedConstructor: !!fn.directives.nakedConstructor,
- intrinsic: fn.directives.intrinsic ?? "NoIntrinsic",
- overriddenName: fn.directives.getter
- ? `"get ${fn.name}"_s`
- : fn.directives.overriddenName
- ? `"${fn.directives.overriddenName}"_s`
- : "ASCIILiteral()",
- });
- }
-
- return {
- functions: bundledFunctions,
- internal,
- };
-}
-
-const filesToProcess = readdirSync(SRC_DIR).filter(x => x.endsWith(".ts"));
-
-const files: Array<{ basename: string; functions: BundledBuiltin[]; internal: boolean }> = [];
-async function processFile(x: string) {
- const basename = path.basename(x, ".ts");
- try {
- files.push({
- basename,
- ...(await processFileSplit(path.join(SRC_DIR, x))),
- });
- } catch (error) {
- console.error("Failed to process file: " + basename + ".ts");
- console.error(error);
- process.exit(1);
- }
-}
-
-// Bun seems to crash if this is parallelized, :(
-if (PARALLEL) {
- await Promise.all(filesToProcess.map(processFile));
-} else {
- for (const x of filesToProcess) {
- await processFile(x);
- }
-}
-
-// C++ codegen
-let bundledCPP = `// Generated by \`bun src/bun.js/builtins/codegen/index.js\`
-// Do not edit by hand.
-namespace Zig { class GlobalObject; }
-#include "root.h"
-#include "config.h"
-#include "JSDOMGlobalObject.h"
-#include "WebCoreJSClientData.h"
-#include <JavaScriptCore/JSObjectInlines.h>
-
-namespace WebCore {
-
-`;
-
-for (const { basename, functions } of files) {
- bundledCPP += `/* ${basename}.ts */\n`;
- const lowerBasename = low(basename);
- for (const fn of functions) {
- const name = `${lowerBasename}${cap(fn.name)}Code`;
- bundledCPP += `// ${fn.name}
-const JSC::ConstructAbility s_${name}ConstructAbility = JSC::ConstructAbility::CannotConstruct;
-const JSC::ConstructorKind s_${name}ConstructorKind = JSC::ConstructorKind::None;
-const JSC::ImplementationVisibility s_${name}ImplementationVisibility = JSC::ImplementationVisibility::${fn.visibility};
-const int s_${name}Length = ${fn.source.length};
-static const JSC::Intrinsic s_${name}Intrinsic = JSC::NoIntrinsic;
-const char* const s_${name} = ${fmtCPPString(fn.source)};
-
-`;
- }
- bundledCPP += `#define DEFINE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\
-JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \\
-{\\
- JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \\
- return clientData->builtinFunctions().${lowerBasename}Builtins().codeName##Executable()->link(vm, nullptr, clientData->builtinFunctions().${lowerBasename}Builtins().codeName##Source(), std::nullopt, s_##codeName##Intrinsic); \\
-}
-WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
-#undef DEFINE_BUILTIN_GENERATOR
-
-`;
-}
-
-bundledCPP += `
-
-JSBuiltinInternalFunctions::JSBuiltinInternalFunctions(JSC::VM& vm)
- : m_vm(vm)
-`;
-
-for (const { basename, internal } of files) {
- if (internal) {
- bundledCPP += ` , m_${low(basename)}(vm)\n`;
- }
-}
-
-bundledCPP += `
-{
- UNUSED_PARAM(vm);
-}
-
-template<typename Visitor>
-void JSBuiltinInternalFunctions::visit(Visitor& visitor)
-{
-`;
-for (const { basename, internal } of files) {
- if (internal) bundledCPP += ` m_${low(basename)}.visit(visitor);\n`;
-}
-
-bundledCPP += `
- UNUSED_PARAM(visitor);
-}
-
-template void JSBuiltinInternalFunctions::visit(AbstractSlotVisitor&);
-template void JSBuiltinInternalFunctions::visit(SlotVisitor&);
-
-SUPPRESS_ASAN void JSBuiltinInternalFunctions::initialize(Zig::GlobalObject& globalObject)
-{
- UNUSED_PARAM(globalObject);
-`;
-
-for (const { basename, internal } of files) {
- if (internal) {
- bundledCPP += ` m_${low(basename)}.init(globalObject);\n`;
- }
-}
-
-bundledCPP += `
- JSVMClientData& clientData = *static_cast<JSVMClientData*>(m_vm.clientData);
- Zig::GlobalObject::GlobalPropertyInfo staticGlobals[] = {
-`;
-
-for (const { basename, internal } of files) {
- if (internal) {
- bundledCPP += `#define DECLARE_GLOBAL_STATIC(name) \\
- Zig::GlobalObject::GlobalPropertyInfo( \\
- clientData.builtinFunctions().${low(basename)}Builtins().name##PrivateName(), ${low(
- basename,
- )}().m_##name##Function.get() , JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly),
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(DECLARE_GLOBAL_STATIC)
- #undef DECLARE_GLOBAL_STATIC
- `;
- }
-}
-
-bundledCPP += `
- };
- globalObject.addStaticGlobals(staticGlobals, std::size(staticGlobals));
- UNUSED_PARAM(clientData);
-}
-
-} // namespace WebCore
-`;
-
-// C++ Header codegen
-let bundledHeader = `// Generated by \`bun src/bun.js/builtins/codegen/index.js\`
-// Do not edit by hand.
-#pragma once
-namespace Zig { class GlobalObject; }
-#include "root.h"
-#include <JavaScriptCore/BuiltinUtils.h>
-#include <JavaScriptCore/Identifier.h>
-#include <JavaScriptCore/JSFunction.h>
-#include <JavaScriptCore/UnlinkedFunctionExecutable.h>
-#include <JavaScriptCore/VM.h>
-#include <JavaScriptCore/WeakInlines.h>
-
-namespace JSC {
-class FunctionExecutable;
-}
-
-namespace WebCore {
-`;
-for (const { basename, functions, internal } of files) {
- bundledHeader += `/* ${basename}.ts */
-`;
- const lowerBasename = low(basename);
-
- for (const fn of functions) {
- const name = `${lowerBasename}${cap(fn.name)}Code`;
- bundledHeader += `// ${fn.name}
-#define WEBCORE_BUILTIN_${basename.toUpperCase()}_${fn.name.toUpperCase()} 1
-extern const char* const s_${name};
-extern const int s_${name}Length;
-extern const JSC::ConstructAbility s_${name}ConstructAbility;
-extern const JSC::ConstructorKind s_${name}ConstructorKind;
-extern const JSC::ImplementationVisibility s_${name}ImplementationVisibility;
-
-`;
- }
- bundledHeader += `#define WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_DATA(macro) \\\n`;
- for (const fn of functions) {
- bundledHeader += ` macro(${fn.name}, ${lowerBasename}${cap(fn.name)}, ${fn.params.length}) \\\n`;
- }
- bundledHeader += "\n";
- bundledHeader += `#define WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(macro) \\\n`;
- for (const fn of functions) {
- const name = `${lowerBasename}${cap(fn.name)}Code`;
- bundledHeader += ` macro(${name}, ${fn.name}, ${fn.overriddenName}, s_${name}Length) \\\n`;
- }
- bundledHeader += "\n";
- bundledHeader += `#define WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(macro) \\\n`;
- for (const fn of functions) {
- bundledHeader += ` macro(${fn.name}) \\\n`;
- }
- bundledHeader += `
-#define DECLARE_BUILTIN_GENERATOR(codeName, functionName, overriddenName, argumentCount) \\
- JSC::FunctionExecutable* codeName##Generator(JSC::VM&);
-
-WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(DECLARE_BUILTIN_GENERATOR)
-#undef DECLARE_BUILTIN_GENERATOR
-
-class ${basename}BuiltinsWrapper : private JSC::WeakHandleOwner {
-public:
- explicit ${basename}BuiltinsWrapper(JSC::VM& vm)
- : m_vm(vm)
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(INITIALIZE_BUILTIN_NAMES)
-#define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length) , m_##name##Source(JSC::makeSource(StringImpl::createWithoutCopying(s_##name, length), { }))
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(INITIALIZE_BUILTIN_SOURCE_MEMBERS)
-#undef INITIALIZE_BUILTIN_SOURCE_MEMBERS
- {
- }
-
-#define EXPOSE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \\
- JSC::UnlinkedFunctionExecutable* name##Executable(); \\
- const JSC::SourceCode& name##Source() const { return m_##name##Source; }
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(EXPOSE_BUILTIN_EXECUTABLES)
-#undef EXPOSE_BUILTIN_EXECUTABLES
-
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_IDENTIFIER_ACCESSOR)
-
- void exportNames();
-
-private:
- JSC::VM& m_vm;
-
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_NAMES)
-
-#define DECLARE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length) \\
- JSC::SourceCode m_##name##Source;\\
- JSC::Weak<JSC::UnlinkedFunctionExecutable> m_##name##Executable;
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(DECLARE_BUILTIN_SOURCE_MEMBERS)
-#undef DECLARE_BUILTIN_SOURCE_MEMBERS
-
-};
-
-#define DEFINE_BUILTIN_EXECUTABLES(name, functionName, overriddenName, length) \\
-inline JSC::UnlinkedFunctionExecutable* ${basename}BuiltinsWrapper::name##Executable() \\
-{\\
- if (!m_##name##Executable) {\\
- JSC::Identifier executableName = functionName##PublicName();\\
- if (overriddenName)\\
- executableName = JSC::Identifier::fromString(m_vm, overriddenName);\\
- m_##name##Executable = JSC::Weak<JSC::UnlinkedFunctionExecutable>(JSC::createBuiltinExecutable(m_vm, m_##name##Source, executableName, s_##name##ImplementationVisibility, s_##name##ConstructorKind, s_##name##ConstructAbility), this, &m_##name##Executable);\\
- }\\
- return m_##name##Executable.get();\\
-}
-WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(DEFINE_BUILTIN_EXECUTABLES)
-#undef DEFINE_BUILTIN_EXECUTABLES
-
-inline void ${basename}BuiltinsWrapper::exportNames()
-{
-#define EXPORT_FUNCTION_NAME(name) m_vm.propertyNames->appendExternalName(name##PublicName(), name##PrivateName());
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(EXPORT_FUNCTION_NAME)
-#undef EXPORT_FUNCTION_NAME
-}
-`;
-
- if (internal) {
- bundledHeader += `class ${basename}BuiltinFunctions {
-public:
- explicit ${basename}BuiltinFunctions(JSC::VM& vm) : m_vm(vm) { }
-
- void init(JSC::JSGlobalObject&);
- template<typename Visitor> void visit(Visitor&);
-
-public:
- JSC::VM& m_vm;
-
-#define DECLARE_BUILTIN_SOURCE_MEMBERS(functionName) \\
- JSC::WriteBarrier<JSC::JSFunction> m_##functionName##Function;
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_SOURCE_MEMBERS)
-#undef DECLARE_BUILTIN_SOURCE_MEMBERS
-};
-
-inline void ${basename}BuiltinFunctions::init(JSC::JSGlobalObject& globalObject)
-{
-#define EXPORT_FUNCTION(codeName, functionName, overriddenName, length) \\
- m_##functionName##Function.set(m_vm, &globalObject, JSC::JSFunction::create(m_vm, codeName##Generator(m_vm), &globalObject));
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(EXPORT_FUNCTION)
-#undef EXPORT_FUNCTION
-}
-
-template<typename Visitor>
-inline void ${basename}BuiltinFunctions::visit(Visitor& visitor)
-{
-#define VISIT_FUNCTION(name) visitor.append(m_##name##Function);
- WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(VISIT_FUNCTION)
-#undef VISIT_FUNCTION
-}
-
-template void ${basename}BuiltinFunctions::visit(JSC::AbstractSlotVisitor&);
-template void ${basename}BuiltinFunctions::visit(JSC::SlotVisitor&);
- `;
- }
-}
-bundledHeader += `class JSBuiltinFunctions {
-public:
- explicit JSBuiltinFunctions(JSC::VM& vm)
- : m_vm(vm)
-`;
-
-for (const { basename } of files) {
- bundledHeader += ` , m_${low(basename)}Builtins(m_vm)\n`;
-}
-
-bundledHeader += `
- {
-`;
-
-for (const { basename, internal } of files) {
- if (internal) {
- bundledHeader += ` m_${low(basename)}Builtins.exportNames();\n`;
- }
-}
-
-bundledHeader += ` }
-`;
-
-for (const { basename } of files) {
- bundledHeader += ` ${basename}BuiltinsWrapper& ${low(basename)}Builtins() { return m_${low(
- basename,
- )}Builtins; }\n`;
-}
-
-bundledHeader += `
-private:
- JSC::VM& m_vm;
-`;
-
-for (const { basename } of files) {
- bundledHeader += ` ${basename}BuiltinsWrapper m_${low(basename)}Builtins;\n`;
-}
-
-bundledHeader += `;
-};
-
-class JSBuiltinInternalFunctions {
-public:
- explicit JSBuiltinInternalFunctions(JSC::VM&);
-
- template<typename Visitor> void visit(Visitor&);
- void initialize(Zig::GlobalObject&);
-`;
-
-for (const { basename, internal } of files) {
- if (internal) {
- bundledHeader += ` ${basename}BuiltinFunctions& ${low(basename)}() { return m_${low(basename)}; }\n`;
- }
-}
-
-bundledHeader += `
-private:
- JSC::VM& m_vm;
-`;
-
-for (const { basename, internal } of files) {
- if (internal) {
- bundledHeader += ` ${basename}BuiltinFunctions m_${low(basename)};\n`;
- }
-}
-
-bundledHeader += `
-};
-
-} // namespace WebCore
-`;
-
-await Bun.write(path.join(OUT_DIR, "WebCoreJSBuiltins.h"), bundledHeader);
-await Bun.write(path.join(OUT_DIR, "WebCoreJSBuiltins.cpp"), bundledCPP);
-
-// Generate TS types
-let dts = `// Generated by \`bun src/bun.js/builtins/codegen/index.js\`
-// Do not edit by hand.
-type RemoveThis<F> = F extends (this: infer T, ...args: infer A) => infer R ? (...args: A) => R : F;
-`;
-
-for (const { basename, functions, internal } of files) {
- if (internal) {
- dts += `\n// ${basename}.ts\n`;
- for (const fn of functions) {
- dts += `declare const \$${fn.name}: RemoveThis<typeof import("./ts/${basename}")[${JSON.stringify(fn.name)}]>;\n`;
- }
- }
-}
-
-await Bun.write(path.join(OUT_DIR, "WebCoreJSBuiltins.d.ts"), dts);
-
-const totalJSSize = files.reduce(
- (acc, { functions }) => acc + functions.reduce((acc, fn) => acc + fn.source.length, 0),
- 0,
-);
-
-if (!KEEP_TMP) {
- await rmSync(TMP_DIR, { recursive: true });
-}
-
-console.log(
- `Embedded JS size: %s bytes (across %s functions, %s files)`,
- totalJSSize,
- files.reduce((acc, { functions }) => acc + functions.length, 0),
- files.length,
-);
-console.log(`[${performance.now().toFixed(1)}ms]`);
diff --git a/src/bun.js/builtins/codegen/replacements.ts b/src/bun.js/builtins/codegen/replacements.ts
deleted file mode 100644
index 05c81b901..000000000
--- a/src/bun.js/builtins/codegen/replacements.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-import { LoaderKeys } from "../../../api/schema";
-
-// This is a list of extra syntax replacements to do. Kind of like macros
-// These are only run on code itself, not string contents or comments.
-export const replacements: ReplacementRule[] = [
- { from: /\bthrow new TypeError\b/g, to: "$throwTypeError" },
- { from: /\bthrow new RangeError\b/g, to: "$throwRangeError" },
- { from: /\bthrow new OutOfMemoryError\b/g, to: "$throwOutOfMemoryError" },
- { from: /\bnew TypeError\b/g, to: "$makeTypeError" },
-];
-
-// These rules are run on the entire file, including within strings.
-export const globalReplacements: ReplacementRule[] = [
- {
- from: /\bnotImplementedIssue\(\s*([0-9]+)\s*,\s*((?:"[^"]*"|'[^']+'))\s*\)/g,
- to: "new TypeError(`${$2} is not implemented yet. See https://github.com/oven-sh/bun/issues/$1`)",
- },
- {
- from: /\bnotImplementedIssueFn\(\s*([0-9]+)\s*,\s*((?:"[^"]*"|'[^']+'))\s*\)/g,
- to: "() => $throwTypeError(`${$2} is not implemented yet. See https://github.com/oven-sh/bun/issues/$1`)",
- },
-];
-
-// This is a list of globals we should access using @ notation
-// undefined -> __intrinsic__undefined -> @undefined
-export const globalsToPrefix = [
- "AbortSignal",
- "Array",
- "ArrayBuffer",
- "Buffer",
- "Bun",
- "Infinity",
- "Loader",
- "Promise",
- "ReadableByteStreamController",
- "ReadableStream",
- "ReadableStreamBYOBReader",
- "ReadableStreamBYOBRequest",
- "ReadableStreamDefaultController",
- "ReadableStreamDefaultReader",
- "TransformStream",
- "TransformStreamDefaultController",
- "Uint8Array",
- "WritableStream",
- "WritableStreamDefaultController",
- "WritableStreamDefaultWriter",
- "isFinite",
- "isNaN",
- "undefined",
-];
-
-// These enums map to $<enum>IdToLabel and $<enum>LabelToId
-// Make sure to define in ./builtins.d.ts
-export const enums = {
- Loader: LoaderKeys,
- ImportKind: [
- "entry-point",
- "import-statement",
- "require-call",
- "dynamic-import",
- "require-resolve",
- "import-rule",
- "url-token",
- "internal",
- ],
-};
-
-// These identifiers have typedef but not present at runtime (converted with replacements)
-// If they are present in the bundle after runtime, we warn at the user.
-// TODO: implement this check.
-export const warnOnIdentifiersNotPresentAtRuntime = [
- //
- "OutOfMemoryError",
- "notImplementedIssue",
- "notImplementedIssueFn",
-];
-
-export interface ReplacementRule {
- from: RegExp;
- to: string;
- global?: boolean;
-}
-
-/** Applies source code replacements as defined in `replacements` */
-export function applyReplacements(src: string) {
- let result = src.replace(/\$([a-zA-Z0-9_]+)\b/gm, `__intrinsic__$1`);
- for (const replacement of replacements) {
- result = result.replace(replacement.from, replacement.to.replaceAll("$", "__intrinsic__"));
- }
- return result;
-}
-
-/** Applies source code replacements as defined in `globalReplacements` */
-export function applyGlobalReplacements(src: string) {
- let result = src;
- for (const replacement of globalReplacements) {
- result = result.replace(replacement.from, replacement.to.replaceAll("$", "__intrinsic__"));
- }
- return result;
-}