diff options
Diffstat (limited to 'src/main_javascript.zig')
-rw-r--r-- | src/main_javascript.zig | 422 |
1 files changed, 0 insertions, 422 deletions
diff --git a/src/main_javascript.zig b/src/main_javascript.zig deleted file mode 100644 index 8cf3e959f..000000000 --- a/src/main_javascript.zig +++ /dev/null @@ -1,422 +0,0 @@ -const std = @import("std"); -const lex = @import("js_lexer.zig"); -const logger = @import("logger.zig"); -const options = @import("options.zig"); -const js_parser = @import("js_parser.zig"); -const json_parser = @import("json_parser.zig"); -const js_printer = @import("js_printer.zig"); -const js_ast = @import("js_ast.zig"); -const linker = @import("linker.zig"); -usingnamespace @import("ast/base.zig"); -usingnamespace @import("defines.zig"); -usingnamespace @import("global.zig"); -const panicky = @import("panic_handler.zig"); -pub const MainPanicHandler = panicky.NewPanicHandler(panicky.default_panic); -const Api = @import("api/schema.zig").Api; -const resolve_path = @import("./resolver/resolve_path.zig"); -const clap = @import("clap"); -const bundler = @import("bundler.zig"); -const fs = @import("fs.zig"); -const NodeModuleBundle = @import("./node_module_bundle.zig").NodeModuleBundle; -const js = @import("javascript/jsc/bindings/bindings.zig"); -usingnamespace @import("javascript/jsc/javascript.zig"); -const allocators = @import("allocators.zig"); -pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn { - if (MainPanicHandler.Singleton) |singleton| { - MainPanicHandler.handle_panic(msg, error_return_trace); - } else { - panicky.default_panic(msg, error_return_trace); - } -} - -const constStrToU8 = allocators.constStrToU8; -pub fn main() anyerror!void { - // The memory allocator makes a massive difference. - // std.heap.raw_c_allocator and default_allocator perform similarly. - // std.heap.GeneralPurposeAllocator makes this about 3x _slower_ than esbuild. - // var root_alloc = std.heap.ArenaAllocator.init(std.heap.raw_c_allocator); - // var root_alloc_ = &root_alloc.allocator; - - var stdout = std.io.getStdOut(); - // var stdout = std.io.bufferedWriter(stdout_file.writer()); - var stderr = std.io.getStdErr(); - // var stderr = std.io.bufferedWriter(stderr_file.writer()); - var output_source = Output.Source.init(stdout, stderr); - // defer stdout.flush() catch {}; - // defer stderr.flush() catch {}; - Output.Source.set(&output_source); - - defer Output.flush(); - try Cli.start( - default_allocator, - stdout, - stderr, - ); -} - -pub const Cli = struct { - const LoaderMatcher = strings.ExactSizeMatcher(4); - pub fn ColonListType(comptime t: type, value_resolver: anytype) type { - return struct { - pub fn init(allocator: *std.mem.Allocator, count: usize) !@This() { - var keys = try allocator.alloc(string, count); - var values = try allocator.alloc(t, count); - - return @This(){ .keys = keys, .values = values }; - } - keys: []string, - values: []t, - - pub fn load(self: *@This(), input: []const string) !void { - for (input) |str, i| { - // Support either ":" or "=" as the separator, preferring whichever is first. - // ":" is less confusing IMO because that syntax is used with flags - // but "=" is what esbuild uses and I want this to be somewhat familiar for people using esbuild - const midpoint = std.math.min(strings.indexOfChar(str, ':') orelse std.math.maxInt(usize), strings.indexOfChar(str, '=') orelse std.math.maxInt(usize)); - if (midpoint == std.math.maxInt(usize)) { - return error.InvalidSeparator; - } - - self.keys[i] = str[0..midpoint]; - self.values[i] = try value_resolver(str[midpoint + 1 .. str.len]); - } - } - - pub fn resolve(allocator: *std.mem.Allocator, input: []const string) !@This() { - var list = try init(allocator, input.len); - try list.load(input); - return list; - } - }; - } - pub const LoaderColonList = ColonListType(Api.Loader, Arguments.loader_resolver); - pub const DefineColonList = ColonListType(string, Arguments.noop_resolver); - - pub const Arguments = struct { - pub fn loader_resolver(in: string) !Api.Loader { - const Matcher = strings.ExactSizeMatcher(4); - switch (Matcher.match(in)) { - Matcher.case("jsx") => return Api.Loader.jsx, - Matcher.case("js") => return Api.Loader.js, - Matcher.case("ts") => return Api.Loader.ts, - Matcher.case("tsx") => return Api.Loader.tsx, - Matcher.case("css") => return Api.Loader.css, - Matcher.case("file") => return Api.Loader.file, - Matcher.case("json") => return Api.Loader.json, - else => { - return error.InvalidLoader; - }, - } - } - - pub fn noop_resolver(in: string) !string { - return in; - } - - pub fn fileReadError(err: anyerror, stderr: anytype, filename: string, kind: string) noreturn { - stderr.writer().print("Error reading file \"{s}\" for {s}: {s}", .{ filename, kind, @errorName(err) }) catch {}; - std.process.exit(1); - } - - pub fn readFile( - allocator: *std.mem.Allocator, - cwd: string, - filename: string, - ) ![]u8 { - var paths = [_]string{ cwd, filename }; - const outpath = try std.fs.path.resolve(allocator, &paths); - defer allocator.free(outpath); - var file = try std.fs.openFileAbsolute(outpath, std.fs.File.OpenFlags{ .read = true, .write = false }); - defer file.close(); - const stats = try file.stat(); - return try file.readToEndAlloc(allocator, stats.size); - } - - pub fn parse(allocator: *std.mem.Allocator, stdout: anytype, stderr: anytype) !Api.TransformOptions { - @setEvalBranchQuota(9999); - const params = comptime [_]clap.Param(clap.Help){ - clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, - clap.parseParam("-r, --resolve <STR> Determine import/require behavior. \"disable\" ignores. \"dev\" bundles node_modules and builds everything else as independent entry points") catch unreachable, - clap.parseParam("-d, --define <STR>... Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:development") catch unreachable, - clap.parseParam("-l, --loader <STR>... Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: jsx, js, json, tsx (not implemented yet), ts (not implemented yet), css (not implemented yet)") catch unreachable, - clap.parseParam("-o, --outdir <STR> Save output to directory (default: \"out\" if none provided and multiple entry points passed)") catch unreachable, - clap.parseParam("-e, --external <STR>... Exclude module from transpilation (can use * wildcards). ex: -e react") catch unreachable, - clap.parseParam("-i, --inject <STR>... Inject module at the top of every file") catch unreachable, - clap.parseParam("--cwd <STR> Absolute path to resolve entry points from. Defaults to cwd") catch unreachable, - clap.parseParam("--origin <STR> Rewrite import paths to start with --origin. Useful for web browsers.") catch unreachable, - clap.parseParam("--serve Start a local dev server. This also sets resolve to \"lazy\".") catch unreachable, - clap.parseParam("--public-dir <STR> Top-level directory for .html files, fonts, images, or anything external. Only relevant with --serve. Defaults to \"<cwd>/public\", to match create-react-app and Next.js") catch unreachable, - clap.parseParam("--jsx-factory <STR> Changes the function called when compiling JSX elements using the classic JSX runtime") catch unreachable, - clap.parseParam("--jsx-fragment <STR> Changes the function called when compiling JSX fragments using the classic JSX runtime") catch unreachable, - clap.parseParam("--jsx-import-source <STR> Declares the module specifier to be used for importing the jsx and jsxs factory functions. Default: \"react\"") catch unreachable, - clap.parseParam("--jsx-runtime <STR> \"automatic\" (default) or \"classic\"") catch unreachable, - clap.parseParam("--jsx-production Use jsx instead of jsxDEV (default) for the automatic runtime") catch unreachable, - clap.parseParam("--extension-order <STR>... defaults to: .tsx,.ts,.jsx,.js,.json ") catch unreachable, - clap.parseParam("--disable-react-fast-refresh Disable React Fast Refresh. Enabled if --serve is set and --jsx-production is not set. Otherwise, it's a noop.") catch unreachable, - clap.parseParam("--tsconfig-override <STR> Load tsconfig from path instead of cwd/tsconfig.json") catch unreachable, - clap.parseParam("--platform <STR> \"browser\" or \"node\". Defaults to \"browser\"") catch unreachable, - clap.parseParam("--main-fields <STR>... Main fields to lookup in package.json. Defaults to --platform dependent") catch unreachable, - clap.parseParam("--scan Instead of bundling or transpiling, print a list of every file imported by an entry point, recursively") catch unreachable, - clap.parseParam("--new-jsb Generate a new node_modules.jsb file from node_modules and entry point(s)") catch unreachable, - clap.parseParam("--jsb <STR> Use a Bun JavaScript Bundle (default: \"./node_modules.jsb\" if exists)") catch unreachable, - // clap.parseParam("--no-jsb Use a Bun JavaScript Bundle (default: \"./node_modules.jsb\" if exists)") catch unreachable, - clap.parseParam("<POS>... Entry points to use") catch unreachable, - }; - - var diag = clap.Diagnostic{}; - - var args = clap.parse(clap.Help, ¶ms, .{ .diagnostic = &diag, .allocator = allocator }) catch |err| { - // Report useful error and exit - diag.report(stderr.writer(), err) catch {}; - return err; - }; - - if (args.flag("--help")) { - try clap.help(stderr.writer(), ¶ms); - std.process.exit(1); - } - - var cwd_paths = [_]string{args.option("--cwd") orelse try std.process.getCwdAlloc(allocator)}; - var cwd = try std.fs.path.resolve(allocator, &cwd_paths); - var tsconfig_override = if (args.option("--tsconfig-override")) |ts| (Arguments.readFile(allocator, cwd, ts) catch |err| fileReadError(err, stderr, ts, "tsconfig.json")) else null; - var origin = args.option("--origin"); - var defines_tuple = try DefineColonList.resolve(allocator, args.options("--define")); - var loader_tuple = try LoaderColonList.resolve(allocator, args.options("--define")); - - var define_keys = defines_tuple.keys; - var define_values = defines_tuple.values; - var loader_keys = loader_tuple.keys; - var loader_values = loader_tuple.values; - var entry_points = args.positionals(); - var inject = args.options("--inject"); - var output_dir = args.option("--outdir"); - const serve = false; - - var write = entry_points.len > 1 or output_dir != null; - if (write and output_dir == null) { - var _paths = [_]string{ cwd, "out" }; - output_dir = try std.fs.path.resolve(allocator, &_paths); - } - var externals = std.mem.zeroes([][]u8); - if (args.options("--external").len > 0) { - externals = try allocator.alloc([]u8, args.options("--external").len); - for (args.options("--external")) |external, i| { - externals[i] = constStrToU8(external); - } - } - - var jsx_factory = args.option("--jsx-factory"); - var jsx_fragment = args.option("--jsx-fragment"); - var jsx_import_source = args.option("--jsx-import-source"); - var jsx_runtime = args.option("--jsx-runtime"); - var jsx_production = args.flag("--jsx-production"); - var react_fast_refresh = false; - - if (serve or args.flag("--new-bun")) { - react_fast_refresh = true; - if (args.flag("--disable-react-fast-refresh") or jsx_production) { - react_fast_refresh = false; - } - } - - var main_fields = args.options("--main-fields"); - - var node_modules_bundle_path = args.option("--bun") orelse brk: { - if (args.flag("--new-bun")) { - break :brk null; - } - - const node_modules_bundle_path_absolute = resolve_path.joinAbs(cwd, .auto, "node_modules.bun"); - std.fs.accessAbsolute(node_modules_bundle_path_absolute, .{}) catch |err| { - break :brk null; - }; - - break :brk node_modules_bundle_path_absolute; - }; - - if (node_modules_bundle_path != null) { - node_modules_bundle_path = try std.fs.realpathAlloc(allocator, node_modules_bundle_path.?); - } - - if (args.flag("--new-bun")) { - node_modules_bundle_path = null; - } - - const PlatformMatcher = strings.ExactSizeMatcher(8); - const ResoveMatcher = strings.ExactSizeMatcher(8); - - var resolve = Api.ResolveMode.lazy; - if (args.option("--resolve")) |_resolve| { - switch (PlatformMatcher.match(_resolve)) { - PlatformMatcher.case("disable") => { - resolve = Api.ResolveMode.disable; - }, - PlatformMatcher.case("bundle") => { - resolve = Api.ResolveMode.bundle; - }, - PlatformMatcher.case("dev") => { - resolve = Api.ResolveMode.dev; - }, - PlatformMatcher.case("lazy") => { - resolve = Api.ResolveMode.lazy; - }, - else => { - diag.name.long = "--resolve"; - diag.arg = _resolve; - try diag.report(stderr.writer(), error.InvalidResolveOption); - std.process.exit(1); - }, - } - } - - var platform: ?Api.Platform = null; - - if (args.option("--platform")) |_platform| { - switch (PlatformMatcher.match(_platform)) { - PlatformMatcher.case("browser") => { - platform = Api.Platform.browser; - }, - PlatformMatcher.case("node") => { - platform = Api.Platform.node; - }, - else => { - diag.name.long = "--platform"; - diag.arg = _platform; - try diag.report(stderr.writer(), error.InvalidPlatform); - std.process.exit(1); - }, - } - } - - var jsx: ?Api.Jsx = null; - if (jsx_factory != null or - jsx_fragment != null or - jsx_import_source != null or - jsx_runtime != null or - jsx_production or react_fast_refresh) - { - var default_factory = "".*; - var default_fragment = "".*; - var default_import_source = "".*; - jsx = Api.Jsx{ - .factory = constStrToU8(jsx_factory orelse &default_factory), - .fragment = constStrToU8(jsx_fragment orelse &default_fragment), - .import_source = constStrToU8(jsx_import_source orelse &default_import_source), - .runtime = if (jsx_runtime != null) try resolve_jsx_runtime(jsx_runtime.?) else Api.JsxRuntime.automatic, - .development = !jsx_production, - .react_fast_refresh = react_fast_refresh, - }; - } - - if (entry_points.len == 0) { - try clap.help(stderr.writer(), ¶ms); - try diag.report(stderr.writer(), error.MissingEntryPoint); - std.process.exit(1); - } - - return Api.TransformOptions{ - .jsx = jsx, - .output_dir = output_dir, - .resolve = resolve, - .external = externals, - .absolute_working_dir = cwd, - .tsconfig_override = tsconfig_override, - .origin = origin, - .define = .{ - .keys = define_keys, - .values = define_values, - }, - .loaders = .{ - .extensions = loader_keys, - .loaders = loader_values, - }, - .node_modules_bundle_path = node_modules_bundle_path, - .public_dir = if (args.option("--public-dir")) |public_dir| allocator.dupe(u8, public_dir) catch unreachable else null, - .write = write, - .platform = .bun, - .serve = serve, - .inject = inject, - .entry_points = entry_points, - .extension_order = args.options("--extension-order"), - .main_fields = args.options("--main-fields"), - .generate_node_module_bundle = if (args.flag("--new-bun")) true else false, - }; - } - }; - pub fn resolve_jsx_runtime(str: string) !Api.JsxRuntime { - if (strings.eql(str, "automatic")) { - return Api.JsxRuntime.automatic; - } else if (strings.eql(str, "fallback")) { - return Api.JsxRuntime.classic; - } else { - return error.InvalidJSXRuntime; - } - } - pub fn printScanResults(scan_results: bundler.ScanResult.Summary, allocator: *std.mem.Allocator) !void { - var stdout = std.io.getStdOut(); - const print_start = std.time.nanoTimestamp(); - try std.json.stringify(scan_results.list(), .{}, stdout.writer()); - Output.printError("\nJSON printing took: {d}\n", .{std.time.nanoTimestamp() - print_start}); - } - pub fn startTransform(allocator: *std.mem.Allocator, args: Api.TransformOptions, log: *logger.Log) anyerror!void {} - const StringS = struct { - pub const src = "var headers = new Headers(); headers.set(\"hey\", \"hi\"); console.log(headers.get(\"hey\")); \"HELLO\";"; - }; - - pub fn Threader(comptime Stdout: type, comptime Stderr: type) type { - return struct { - allocator: *std.mem.Allocator, - stdout: Stdout, - stderr: Stderr, - args: Api.TransformOptions, - pub fn spawn(this: @This()) !void { - var stdout = std.io.getStdOut(); - // var stdout = std.io.bufferedWriter(stdout_file.writer()); - var stderr = std.io.getStdErr(); - // var stderr = std.io.bufferedWriter(stderr_file.writer()); - var output_source = Output.Source.init(stdout, stderr); - // defer stdout.flush() catch {}; - // defer stderr.flush() catch {}; - Output.Source.set(&output_source); - - var log = logger.Log.init(this.allocator); - - var vm = try VirtualMachine.init(this.allocator, this.args, null, &log); - var promise = try vm.loadEntryPoint( - vm.bundler.options.entry_points[0], - ); - if (promise.status(vm.global.vm()) == js.JSPromise.Status.Rejected) { - vm.defaultErrorHandler(promise.result(vm.global.vm())); - } - } - }; - } - - pub fn start(allocator: *std.mem.Allocator, stdout: anytype, stderr: anytype) anyerror!void { - const start_time = std.time.nanoTimestamp(); - var log = logger.Log.init(allocator); - var panicker = MainPanicHandler.init(&log); - MainPanicHandler.Singleton = &panicker; - - var args = try Arguments.parse(default_allocator, stdout, stderr); - // var serve_bundler = try bundler.ServeBundler.init(allocator, &log, args); - // var res = try serve_bundler.buildFile(&log, allocator, args.entry_points[0], std.fs.path.extension(args.entry_points[0])); - - // var results = try bundler.Bundler.bundle(allocator, &log, args); - // var file = results.output_files[0]; - - // var resolved_entry_point = try vm.bundler.resolver.resolve( - // vm.bundler.fs.top_level_dir, - // vm.bundler.normalizeEntryPointPath(vm.bundler.options.entry_points[0]), - // .entry_point, - // ); - const Threadable = Threader(@TypeOf(stdout), @TypeOf(stderr)); - const runner = Threadable{ .allocator = allocator, .stdout = stdout, .stderr = stderr, .args = args }; - var thread = try std.Thread.spawn(.{}, Threadable.spawn, .{runner}); - thread.join(); - } -}; - -pub const JavaScript = struct {}; - -pub const JavaScriptVirtualMachine = VirtualMachine; |