diff options
author | 2023-08-02 16:27:36 -0700 | |
---|---|---|
committer | 2023-08-02 16:27:36 -0700 | |
commit | c2a77cf7ec9de9eadf938046bdf78e58561c8a6d (patch) | |
tree | 0f90f1b323061455875333c9f40592b303585973 /src/js/_codegen/builtin-parser.ts | |
parent | 7656b4b17e91f15b58eeab8f45b78c416ec6a045 (diff) | |
download | bun-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.ts | 185 |
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"); +} |