diff options
author | 2021-05-19 19:30:24 -0700 | |
---|---|---|
committer | 2021-05-19 19:30:24 -0700 | |
commit | a58adfcaa2bcbf24d568af3a0175a6a3ab4e1e05 (patch) | |
tree | 23a585cba094f192097422bf2c3e7b78256cadcf | |
parent | 2884b759c3143d7ba1d44ec8c38987566940d050 (diff) | |
download | bun-a58adfcaa2bcbf24d568af3a0175a6a3ab4e1e05.tar.gz bun-a58adfcaa2bcbf24d568af3a0175a6a3ab4e1e05.tar.zst bun-a58adfcaa2bcbf24d568af3a0175a6a3ab4e1e05.zip |
Starting to work on rutnime
Former-commit-id: 23220fd348f86bda50fb4e4a64cce9c4b167499f
-rw-r--r-- | .vscode/launch.json | 49 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | src/ast/base.zig | 4 | ||||
-rw-r--r-- | src/bundler.zig | 116 | ||||
-rw-r--r-- | src/cli.zig | 2 | ||||
-rw-r--r-- | src/js_parser/js_parser.zig | 14 | ||||
-rw-r--r-- | src/lib.zig | 20 | ||||
-rw-r--r-- | src/options.zig | 15 | ||||
-rw-r--r-- | src/renamer.zig | 3 | ||||
-rw-r--r-- | src/resolver/resolver.zig | 36 | ||||
-rw-r--r-- | src/runtime.js | 40 | ||||
-rw-r--r-- | src/runtime.zig | 14 | ||||
-rw-r--r-- | src/test/fixtures/escape-chars.js | 1 | ||||
-rw-r--r-- | src/test/fixtures/simple-component.js | 2 | ||||
-rw-r--r-- | src/test/fixtures/spread-bug.js | 2 |
15 files changed, 267 insertions, 54 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json index 2d2ff211e..82e080d9d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -28,21 +28,6 @@ // "cwd": "${workspaceFolder}", // "console": "internalConsole" // } - { - "type": "lldb", - "request": "launch", - "name": "Dev Launch", - "program": "${workspaceFolder}/build/debug/macos-x86_64/esdev", - "preLaunchTask": "build", - "args": [ - "--resolve=disable", - "--cwd", - "/Users/jarredsumner/Code/esdev/src/test/fixtures", - "defines.js" - ], - "cwd": "${workspaceFolder}", - "console": "internalConsole" - } // { // "type": "lldb", // "request": "launch", @@ -50,14 +35,12 @@ // "program": "${workspaceFolder}/build/debug/macos-x86_64/esdev", // "preLaunchTask": "build", // "args": [ - // "--resolve=dev", + // "--resolve=disable", // "--cwd", - // "/Users/jarredsumner/Builds/esbuild/bench/three/src/", - // "./entry.js", - // "-o", - // "out" + // "/Users/jarredsumner/Code/esdev/src/test/fixtures", + // "escape-chars.js" // ], - // "cwd": "/Users/jarredsumner/Builds/esbuild/bench/three/src", + // "cwd": "${workspaceFolder}", // "console": "internalConsole" // } // { @@ -74,7 +57,7 @@ // "-o", // "out" // ], - // "cwd": "${workspaceFolder}", + // "cwd": "/Users/jarredsumner/Builds/esbuild/bench/three/src", // "console": "internalConsole" // } // { @@ -86,14 +69,32 @@ // "args": [ // "--resolve=dev", // "--cwd", - // "./src/api/demo", - // "pages/index.js", + // "/Users/jarredsumner/Builds/esbuild/bench/three/src/", + // "./entry.js", // "-o", // "out" // ], // "cwd": "${workspaceFolder}", // "console": "internalConsole" // } + { + "type": "lldb", + "request": "launch", + "name": "Dev Launch", + "program": "${workspaceFolder}/build/debug/macos-x86_64/esdev", + "preLaunchTask": "build", + "args": [ + "--resolve=dev", + "--cwd", + "./src/api/demo", + "pages/index.jsx", + "-o", + "out", + "--public-url=https://hello.com/" + ], + "cwd": "${workspaceFolder}", + "console": "internalConsole" + } // { // "type": "lldb", // "request": "launch", @@ -8,6 +8,9 @@ api: speedy-prod-native-macos: zig build -Drelease-fast -Dtarget=x86_64-macos-gnu +speedy-prod-native-macos-lib: + zig build lib -Drelease-fast -Dtarget=x86_64-macos-gnu + speedy-m1: zig build -Drelease-fast -Dtarget=aarch64-macos-gnu diff --git a/src/ast/base.zig b/src/ast/base.zig index 92f15f983..cf08ca780 100644 --- a/src/ast/base.zig +++ b/src/ast/base.zig @@ -33,6 +33,10 @@ pub const Ref = packed struct { .inner_index = std.math.maxInt(Ref.Int), .source_index = std.math.maxInt(Ref.Int), }; + pub const RuntimeRef = Ref{ + .inner_index = std.math.maxInt(Ref.Int), + .source_index = std.math.maxInt(Ref.Int) - 1, + }; pub fn toInt(int: anytype) Int { return @intCast(Int, int); } diff --git a/src/bundler.zig b/src/bundler.zig index e91db985b..6068c3a77 100644 --- a/src/bundler.zig +++ b/src/bundler.zig @@ -20,7 +20,7 @@ const sync = @import("sync.zig"); const ThreadPool = sync.ThreadPool; const ThreadSafeHashMap = @import("./thread_safe_hash_map.zig"); const ImportRecord = @import("./import_record.zig").ImportRecord; -// pub const +const allocators = @import("./allocators.zig"); // const BundleMap = const ResolveResults = ThreadSafeHashMap.ThreadSafeStringHashMap(Resolver.Resolver.Result); pub const Bundler = struct { @@ -35,6 +35,12 @@ pub const Bundler = struct { resolve_results: *ResolveResults, resolve_queue: std.fifo.LinearFifo(Resolver.Resolver.Result, std.fifo.LinearFifoBufferType.Dynamic), elapsed: i128 = 0, + needs_runtime: bool = false, + + runtime_output_path: Fs.Path = undefined, + + pub const RuntimeCode = @embedFile("./runtime.js"); + // to_bundle: // thread_pool: *ThreadPool, @@ -46,6 +52,8 @@ pub const Bundler = struct { ) !Bundler { var fs = try Fs.FileSystem.init1(allocator, opts.absolute_working_dir, opts.watch orelse false); const bundle_options = try options.BundleOptions.fromApi(allocator, fs, log, opts); + + relative_paths_list = ImportPathsList.init(allocator); // var pool = try allocator.create(ThreadPool); // try pool.init(ThreadPool.InitConfig{ // .allocator = allocator, @@ -64,26 +72,75 @@ pub const Bundler = struct { }; } + const ImportPathsList = allocators.BSSStringList(2048, 256); + var relative_paths_list: *ImportPathsList = undefined; + threadlocal var relative_path_allocator: std.heap.FixedBufferAllocator = undefined; + threadlocal var relative_path_allocator_buf: [4096]u8 = undefined; + threadlocal var relative_path_allocator_buf_loaded: bool = false; + + pub fn generateImportPath(bundler: *Bundler, source_dir: string, source_path: string) !Fs.Path { + if (!relative_path_allocator_buf_loaded) { + relative_path_allocator_buf_loaded = true; + relative_path_allocator = std.heap.FixedBufferAllocator.init(&relative_path_allocator_buf); + } + defer relative_path_allocator.reset(); + + switch (bundler.options.import_path_format) { + .relative => { + const relative_path_temp = try std.fs.path.relative(&relative_path_allocator.allocator, source_dir, source_path); + const relative_path = try relative_paths_list.append(relative_path_temp); + + return Fs.Path.init(relative_path); + }, + .absolute_url => { + if (!relative_path_allocator_buf_loaded) { + relative_path_allocator_buf_loaded = true; + relative_path_allocator = std.heap.FixedBufferAllocator.init(&relative_path_allocator_buf); + } + const relative_path_temp = try std.fs.path.relative(&relative_path_allocator.allocator, bundler.fs.top_level_dir, source_path); + const relative_path = try relative_paths_list.append(try std.fmt.allocPrint(&relative_path_allocator.allocator, "{s}{s}", .{ bundler.options.public_url, relative_path_temp })); + + return Fs.Path.init(relative_path); + }, + } + } + pub fn processImportRecord(bundler: *Bundler, source_dir: string, import_record: *ImportRecord) !void { var resolve_result = (bundler.resolver.resolve(source_dir, import_record.path.text, import_record.kind) catch null) orelse return; - if (!bundler.resolve_results.contains(resolve_result.path_pair.primary.text)) { - try bundler.resolve_results.put(resolve_result.path_pair.primary.text, resolve_result); - try bundler.resolve_queue.writeItem(resolve_result); + // extremely naive. + resolve_result.is_from_node_modules = strings.contains(resolve_result.path_pair.primary.text, "/node_modules"); + + if (resolve_result.shouldAssumeCommonJS()) { + import_record.wrap_with_to_module = true; + if (!bundler.needs_runtime) { + bundler.runtime_output_path = Fs.Path.init(try std.fmt.allocPrint(bundler.allocator, "{s}/__runtime.js", .{bundler.fs.top_level_dir})); + } + bundler.needs_runtime = true; + } + + // lazy means: + // Run the resolver + // Don't parse/print automatically. + if (bundler.options.resolve_mode != .lazy) { + if (!bundler.resolve_results.contains(resolve_result.path_pair.primary.text)) { + try bundler.resolve_results.put(resolve_result.path_pair.primary.text, resolve_result); + try bundler.resolve_queue.writeItem(resolve_result); + } } if (!strings.eql(import_record.path.text, resolve_result.path_pair.primary.text)) { - import_record.path = Fs.Path.init(resolve_result.path_pair.primary.text); + import_record.path = try bundler.generateImportPath(source_dir, resolve_result.path_pair.primary.text); } } - pub fn buildWithResolveResult(bundler: *Bundler, resolve_result: Resolver.Resolver.Result) !void { + pub fn buildWithResolveResult(bundler: *Bundler, resolve_result: Resolver.Resolver.Result) !?options.OutputFile { if (resolve_result.is_external) { - return; + return null; } // Step 1. Parse & scan - const result = bundler.parse(resolve_result.path_pair.primary) orelse return; + const result = bundler.parse(resolve_result.path_pair.primary) orelse return null; switch (result.loader) { .jsx, .js, .ts, .tsx => { @@ -99,7 +156,7 @@ pub const Bundler = struct { else => {}, } - try bundler.print( + return try bundler.print( result, ); } @@ -107,7 +164,7 @@ pub const Bundler = struct { pub fn print( bundler: *Bundler, result: ParseResult, - ) !void { + ) !options.OutputFile { var allocator = bundler.allocator; const relative_path = try std.fs.path.relative(bundler.allocator, bundler.fs.top_level_dir, result.source.path.text); var out_parts = [_]string{ bundler.options.output_dir, relative_path }; @@ -124,13 +181,13 @@ pub const Bundler = struct { js_ast.Symbol.Map.initList(symbols), &result.source, false, - js_printer.Options{ .to_module_ref = ast.module_ref orelse js_ast.Ref{ .inner_index = 0 } }, + js_printer.Options{ .to_module_ref = Ref.RuntimeRef }, &_linker, ); - try bundler.output_files.append(options.OutputFile{ + return options.OutputFile{ .path = out_path, .contents = print_result.js, - }); + }; } pub const ParseResult = struct { @@ -192,6 +249,24 @@ pub const Bundler = struct { return null; } + pub fn buildFile( + bundler: *Bundler, + allocator: *std.mem.Allocator, + relative_path: string, + ) !options.TransformResult { + var log = logger.Log.init(bundler.allocator); + var original_resolver_logger = bundler.resolver.log; + var original_bundler_logger = bundler.log; + defer bundler.log = original_bundler_logger; + defer bundler.resolver.log = original_resolver_logger; + bundler.log = log; + bundler.resolver.log = log; + const resolved = try bundler.resolver.resolve(bundler.fs.top_level_dir, relative_path, .entry_point); + const output_file = try bundler.buildWithResolveResult(resolved); + var output_files = try allocator.alloc(options.OutputFile, 1); + return try options.TransformResult.init(output_files, log, allocator); + } + pub fn bundle( allocator: *std.mem.Allocator, log: *logger.Log, @@ -263,7 +338,11 @@ pub const Bundler = struct { } try bundler.resolve_results.put(key, result); entry_points[entry_point_i] = result; - Output.print("Resolved {s} => {s}", .{ entry, result.path_pair.primary.text }); + + if (isDebug) { + Output.print("Resolved {s} => {s}", .{ entry, result.path_pair.primary.text }); + } + entry_point_i += 1; bundler.resolve_queue.writeItem(result) catch unreachable; } @@ -276,12 +355,19 @@ pub const Bundler = struct { switch (bundler.options.resolve_mode) { .lazy, .dev, .bundle => { while (bundler.resolve_queue.readItem()) |item| { - bundler.buildWithResolveResult(item) catch continue; + const output_file = bundler.buildWithResolveResult(item) catch continue orelse continue; + bundler.output_files.append(output_file) catch unreachable; } }, else => Global.panic("Unsupported resolve mode: {s}", .{@tagName(bundler.options.resolve_mode)}), } + // if (bundler.needs_runtime) { + // try bundler.output_files.append(options.OutputFile{ + + // }); + // } + if (enableTracing) { Output.print( "\n---Tracing---\nResolve time: {d}\nParsing time: {d}\n---Tracing--\n\n", diff --git a/src/cli.zig b/src/cli.zig index 01240482d..68d2d51b4 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -195,7 +195,7 @@ pub const Cli = struct { else => { diag.name.long = "--resolve"; diag.arg = _resolve; - try diag.report(stderr.writer(), error.InvalidPlatform); + try diag.report(stderr.writer(), error.InvalidResolveOption); std.process.exit(1); }, } diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index 7a859a3a5..d499812e3 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -1425,6 +1425,8 @@ pub const Parser = struct { } }; + var runtime_import_names = []string{ "__markAsModule", "__commonJS", "__reExport", "__toModule" }; + pub fn parse(self: *Parser) !js_ast.Result { if (self.p == null) { self.p = try P.init(self.allocator, self.log, self.source, self.define, self.lexer, self.options); @@ -1696,6 +1698,10 @@ pub const Prefill = struct { pub var JSXFilename = "__jsxFilename"; pub var JSXDevelopmentImportName = "jsxDEV"; pub var JSXImportName = "jsx"; + pub var MarkAsModule = "__markAsModule"; + pub var CommonJS = "__commonJS"; + pub var ReExport = "__reExport"; + pub var ToModule = "__toModule"; }; }; @@ -9110,8 +9116,6 @@ pub const P = struct { e_.expr = p.visitExpr(e_.expr); return p.import_transposer.maybeTransposeIf(e_.expr, state); - - // TODO: maybeTransposeIfExprChain }, .e_call => |e_| { p.call_target = e_.target.data; @@ -11228,11 +11232,11 @@ pub const P = struct { return js_ast.Ast{ .parts = parts, .module_scope = p.module_scope.*, - .symbols = p.symbols.toOwnedSlice(), + .symbols = p.symbols.items, .exports_ref = p.exports_ref, .wrapper_ref = wrapper, - .import_records = p.import_records.toOwnedSlice(), - .export_star_import_records = p.export_star_import_records.toOwnedSlice(), + .import_records = p.import_records.items, + .export_star_import_records = p.export_star_import_records.items, .top_level_symbol_to_parts = p.top_level_symbol_to_parts, .approximate_line_count = p.lexer.approximate_newline_count + 1, .exports_kind = exports_kind, diff --git a/src/lib.zig b/src/lib.zig new file mode 100644 index 000000000..a7612ba28 --- /dev/null +++ b/src/lib.zig @@ -0,0 +1,20 @@ +const std = @import("std"); +const lex = @import("js_lexer.zig"); +const logger = @import("logger.zig"); +const alloc = @import("alloc.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"); +const cli = @import("cli.zig"); +const api = @import("./api/schema.zig"); + +extern const Configuration = struct {}; + +export fn configure(configuration: Configuration) void {} diff --git a/src/options.zig b/src/options.zig index 9d416ad66..f0c2f6f15 100644 --- a/src/options.zig +++ b/src/options.zig @@ -283,7 +283,7 @@ pub const BundleOptions = struct { jsx: JSX.Pragma = JSX.Pragma{}, react_fast_refresh: bool = false, inject: ?[]string = null, - public_url: string = "/", + public_url: string = "", output_dir: string = "", write: bool = false, preserve_symlinks: bool = false, @@ -295,6 +295,12 @@ pub const BundleOptions = struct { external: ExternalModules = ExternalModules{}, entry_points: []const string, extension_order: []const string = &Defaults.ExtensionOrder, + import_path_format: ImportPathFormat = ImportPathFormat.relative, + + pub const ImportPathFormat = enum { + relative, + absolute_url, + }; pub const Defaults = struct { pub var ExtensionOrder = [_]string{ ".tsx", ".ts", ".jsx", ".js", ".json" }; @@ -350,6 +356,11 @@ pub const BundleOptions = struct { .entry_points = transform.entry_points, }; + if (transform.public_url) |public_url| { + opts.import_path_format = ImportPathFormat.absolute_url; + opts.public_url = public_url; + } + if (transform.jsx) |jsx| { opts.jsx = try JSX.Pragma.fromApi(jsx, allocator); } @@ -380,7 +391,7 @@ pub const TransformOptions = struct { jsx: ?JSX.Pragma, react_fast_refresh: bool = false, inject: ?[]string = null, - public_url: string = "/", + public_url: string = "", preserve_symlinks: bool = false, entry_point: Fs.File, resolve_paths: bool = false, diff --git a/src/renamer.zig b/src/renamer.zig index af1a62ef7..c867b71be 100644 --- a/src/renamer.zig +++ b/src/renamer.zig @@ -3,6 +3,9 @@ usingnamespace @import("global.zig"); const std = @import("std"); const logger = @import("logger.zig"); +// This is...poorly named +// It does not rename +// It merely names pub const Renamer = struct { symbols: js_ast.Symbol.Map, source: *const logger.Source, diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 1fcbe99cb..41da0d261 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -250,6 +250,13 @@ pub const Resolver = struct { debug_meta: ?DebugMeta = null, + // Most NPM modules are CommonJS + // If unspecified, assume CommonJS. + // If internal app code, assume ESM. Since this is designed for ESM.` + pub fn shouldAssumeCommonJS(r: *Result) bool { + return r.is_from_node_modules and r.module_type != .esm; + } + pub const DebugMeta = struct { notes: std.ArrayList(logger.Data), suggestion_text: string = "", @@ -416,7 +423,11 @@ pub const Resolver = struct { if (dir_info.tsconfig_json) |tsconfig| { if (tsconfig.paths.count() > 0) { if (r.matchTSConfigPaths(tsconfig, import_path, kind)) |res| { - return Result{ .path_pair = res.path_pair, .diff_case = res.diff_case }; + return Result{ + .path_pair = res.path_pair, + .diff_case = res.diff_case, + .is_from_node_modules = res.is_node_module, + }; } } } @@ -439,7 +450,7 @@ pub const Resolver = struct { // Run node's resolution rules (e.g. adding ".js") if (r.loadAsFileOrDirectory(import_path, kind)) |entry| { - return Result{ .path_pair = entry.path_pair, .diff_case = entry.diff_case }; + return Result{ .path_pair = entry.path_pair, .diff_case = entry.diff_case, .is_from_node_modules = entry.is_node_module }; } return null; @@ -490,7 +501,12 @@ pub const Resolver = struct { } if (r.resolveWithoutRemapping(import_dir_info, remap, kind)) |_result| { - result = Result{ .path_pair = _result.path_pair, .diff_case = _result.diff_case }; + result = Result{ + .path_pair = _result.path_pair, + .diff_case = _result.diff_case, + .is_from_node_modules = _result.is_node_module, + .module_type = pkg.module_type, + }; check_relative = false; check_package = false; } @@ -502,7 +518,11 @@ pub const Resolver = struct { if (check_relative) { if (r.loadAsFileOrDirectory(abs_path, kind)) |res| { check_package = false; - result = Result{ .path_pair = res.path_pair, .diff_case = res.diff_case }; + result = Result{ + .path_pair = res.path_pair, + .diff_case = res.diff_case, + .is_from_node_modules = res.is_node_module, + }; } else if (!check_package) { return null; } @@ -565,7 +585,11 @@ pub const Resolver = struct { } if (r.resolveWithoutRemapping(source_dir_info, import_path, kind)) |res| { - result = Result{ .path_pair = res.path_pair, .diff_case = res.diff_case }; + result = Result{ + .path_pair = res.path_pair, + .diff_case = res.diff_case, + .is_from_node_modules = res.is_node_module, + }; } else { // Note: node's "self references" are not currently supported return null; @@ -579,11 +603,13 @@ pub const Resolver = struct { const dir_info = base_dir_info.getEnclosingBrowserScope() orelse continue; const pkg_json = dir_info.package_json orelse continue; const rel_path = std.fs.path.relative(r.allocator, pkg_json.source.key_path.text, path.text) catch continue; + result.module_type = pkg_json.module_type; if (r.checkBrowserMap(pkg_json, rel_path)) |remapped| { if (remapped.len == 0) { r.allocator.free(rel_path); path.is_disabled = true; } else if (r.resolveWithoutRemapping(dir_info, remapped, kind)) |remapped_result| { + result.is_from_node_modules = remapped_result.is_node_module; switch (iter.index) { 0 => { result.path_pair.primary = remapped_result.path_pair.primary; diff --git a/src/runtime.js b/src/runtime.js new file mode 100644 index 000000000..11d5be083 --- /dev/null +++ b/src/runtime.js @@ -0,0 +1,40 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; + +export var __markAsModule = (target) => + __defProp(target, "__esModule", { value: true }); +export var __commonJS = (cb, mod) => () => { + return mod || cb((mod = { exports: {} }).exports, mod), mod.exports; +}; + +export var __reExport = (target, module, desc) => { + if ((module && typeof module === "object") || typeof module === "function") { + for (let key of __getOwnPropNames(module)) + if (!__hasOwnProp.call(target, key) && key !== "default") + __defProp(target, key, { + get: () => module[key], + enumerable: + !(desc = __getOwnPropDesc(module, key)) || desc.enumerable, + }); + } + return target; +}; + +export var __toModule = (module) => { + return __reExport( + __markAsModule( + __defProp( + module != null ? __create(__getProtoOf(module)) : {}, + "default", + module && module.__esModule && "default" in module + ? { get: () => module.default, enumerable: true } + : { value: module, enumerable: true } + ) + ), + module + ); +}; diff --git a/src/runtime.zig b/src/runtime.zig new file mode 100644 index 000000000..e6fd44d2f --- /dev/null +++ b/src/runtime.zig @@ -0,0 +1,14 @@ +pub const Runtime = struct { + pub const Features = packed struct { + react_fast_refresh: bool = false, + hot_module_reloading: bool = false, + keep_names_for_arrow_functions: bool = true, + }; + + pub const Functions = enum { + KeepNames, + CommonJSToESModule, + TypeScriptDecorateClass, + TypeScriptDecorateParam, + }; +}; diff --git a/src/test/fixtures/escape-chars.js b/src/test/fixtures/escape-chars.js new file mode 100644 index 000000000..cff9b60a2 --- /dev/null +++ b/src/test/fixtures/escape-chars.js @@ -0,0 +1 @@ +console.log("\u2028"); diff --git a/src/test/fixtures/simple-component.js b/src/test/fixtures/simple-component.js index b59f9f667..cf16715f1 100644 --- a/src/test/fixtures/simple-component.js +++ b/src/test/fixtures/simple-component.js @@ -1,5 +1,3 @@ -import * as React from "react"; - export function Welcome() { return <div>Hi.</div>; } diff --git a/src/test/fixtures/spread-bug.js b/src/test/fixtures/spread-bug.js new file mode 100644 index 000000000..1b77bd7b2 --- /dev/null +++ b/src/test/fixtures/spread-bug.js @@ -0,0 +1,2 @@ +// spread +const { currentUserId } = cookies(ctx); |