aboutsummaryrefslogtreecommitdiff
path: root/src/js/_codegen/builtin-parser.ts
diff options
context:
space:
mode:
authorGravatar dave caruso <me@paperdave.net> 2023-08-02 16:27:36 -0700
committerGravatar GitHub <noreply@github.com> 2023-08-02 16:27:36 -0700
commitc2a77cf7ec9de9eadf938046bdf78e58561c8a6d (patch)
tree0f90f1b323061455875333c9f40592b303585973 /src/js/_codegen/builtin-parser.ts
parent7656b4b17e91f15b58eeab8f45b78c416ec6a045 (diff)
downloadbun-c2a77cf7ec9de9eadf938046bdf78e58561c8a6d.tar.gz
bun-c2a77cf7ec9de9eadf938046bdf78e58561c8a6d.tar.zst
bun-c2a77cf7ec9de9eadf938046bdf78e58561c8a6d.zip
Rewrite built-in modules to use CommonJS over ESM (#3814)
* stfdsafsd sadffdsa stuff finish commonjs stuff asdf not done but work not done but work not done yet but this is how far i am remove files lol update built files uncomment everything in events lol export default stuff * afdsafsd * its not perfect but almost done * okay * cool * remove temp file * finish rebase * revert settings.json * a * ch-ch-ch-ch-changes * okay * remove this check in release for now * sxdcfghnjm, * lkjhgf * fmt * filename can be null * Update NodeModuleModule.h * weee * fmt --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/js/_codegen/builtin-parser.ts')
-rw-r--r--src/js/_codegen/builtin-parser.ts185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/js/_codegen/builtin-parser.ts b/src/js/_codegen/builtin-parser.ts
new file mode 100644
index 000000000..ffd5671c1
--- /dev/null
+++ b/src/js/_codegen/builtin-parser.ts
@@ -0,0 +1,185 @@
+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,
+ replaceRequire?: (specifier: string) => string,
+ endOnComma = false,
+): { result: string; rest: string } {
+ let bracketCount = 0;
+ let i = 0;
+ let result = "";
+ while (contents.length) {
+ const match = contents.match(
+ endOnComma && bracketCount <= 1
+ ? /((?:[(,=;:{]|return|\=\>)\s*)\/[^\/\*]|\/\*|\/\/|['"}`\),]|(?<!\$)\brequire\(|(\$assert\(|\$debug\()/
+ : /((?:[(,=;:{]|return|\=\>)\s*)\/[^\/\*]|\/\*|\/\/|['"}`\)]|(?<!\$)\brequire\(|(\$assert\(|\$debug\()/,
+ );
+ i = match?.index ?? contents.length;
+ if (match?.[2]) {
+ i += match[2].length - 1;
+ }
+ bracketCount += [...contents.slice(0, i).matchAll(/[({]/g)].length;
+ const chunk = replace ? applyReplacements(contents, i) : [contents.slice(0, i), contents.slice(i)];
+ result += chunk[0];
+ contents = chunk[1] as string;
+ if (chunk[2]) {
+ continue;
+ }
+ if (match?.[1]) {
+ if (match[1].startsWith("(") || match[1].startsWith(",")) {
+ bracketCount++;
+ }
+ const { result: result2, rest } = sliceRegularExpressionSourceCode(
+ contents.slice(match?.[1].length + 1),
+ replace,
+ );
+ result += contents.slice(0, match?.[1].length + 1) + result2;
+ contents = rest;
+ continue;
+ }
+ 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 = getEndOfBasicString(contents.slice(1), "'") + 2;
+ } else if (contents.startsWith('"')) {
+ i = getEndOfBasicString(contents.slice(1), '"') + 2;
+ } else if (contents.startsWith("`")) {
+ const { result: result2, rest } = sliceTemplateLiteralSourceCode(contents.slice(1), replace);
+ result += "`" + result2;
+ contents = rest;
+ i = 0;
+ continue;
+ } else if (contents.startsWith("}")) {
+ bracketCount--;
+ if (bracketCount <= 0) {
+ result += "}";
+ contents = contents.slice(1);
+ break;
+ }
+ i = 1;
+ } else if (contents.startsWith(")")) {
+ bracketCount--;
+ if (bracketCount <= 0) {
+ result += ")";
+ contents = contents.slice(1);
+ break;
+ }
+ i = 1;
+ } else if (endOnComma && contents.startsWith(",")) {
+ if (bracketCount <= 1) {
+ result += ",";
+ contents = contents.slice(1);
+ // if the next non-whitespace character is ), also consume
+ let match = contents.match(/^\s*\)/);
+ if (match) {
+ contents = contents.slice(match[0].length);
+ }
+ break;
+ }
+ i = 1;
+ } else if (contents.startsWith("require(")) {
+ if (replaceRequire) {
+ const staticSpecifier = contents.match(/\brequire\(["']([^"']+)["']\)/);
+ if (staticSpecifier) {
+ const specifier = staticSpecifier[1];
+ result += replaceRequire(specifier);
+ contents = contents.slice(staticSpecifier[0].length);
+ continue;
+ } else {
+ throw new Error("Require with dynamic specifier not supported here.");
+ }
+ } else {
+ throw new Error("Require is not supported here.");
+ }
+ } else {
+ console.error(contents.slice(0, 100));
+ throw new Error("TODO");
+ }
+ result += contents.slice(0, i);
+ contents = contents.slice(i);
+ }
+
+ return { result, rest: contents };
+}
+
+function sliceTemplateLiteralSourceCode(contents: string, replace: boolean) {
+ let i = 0;
+ let result = "";
+ 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 } = sliceSourceCode(contents.slice(1), replace);
+ result += "$" + result2;
+ contents = rest;
+ continue;
+ } else {
+ throw new Error("TODO");
+ }
+ }
+
+ return { result, rest: contents };
+}
+
+function sliceRegularExpressionSourceCode(contents: string, replace: boolean) {
+ let i = 0;
+ let result = "";
+ 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("\\")) {
+ result += "\\";
+ contents = contents.slice(1);
+ if (!contents.length) break;
+ result += contents[0];
+ contents = contents.slice(1);
+ continue;
+ } else if (contents.startsWith("[")) {
+ let end = contents.match(/(?<!\\)]/)!.index!;
+ result += contents.slice(0, end + 1);
+ contents = contents.slice(end + 1);
+ continue;
+ } else {
+ throw new Error("TODO");
+ }
+ }
+
+ return { result, rest: contents };
+}
+
+function getEndOfBasicString(str: string, quote: "'" | '"') {
+ let i = 0;
+ while (i < str.length) {
+ if (str[i] === "\\") {
+ i++;
+ } else if (str[i] === quote) {
+ return i;
+ }
+ i++;
+ }
+ throw new Error("String did not end");
+}