diff options
author | 2023-05-24 02:09:21 -0700 | |
---|---|---|
committer | 2023-05-24 02:09:21 -0700 | |
commit | 2dcf948934e9293fc39243217a3a568f235421f0 (patch) | |
tree | be568c8cefc09d06b37c853233ed07e805502360 | |
parent | c968fc447eaeaf6665a9cd3aa9077c58702944a4 (diff) | |
download | bun-jarred/isolation.tar.gz bun-jarred/isolation.tar.zst bun-jarred/isolation.zip |
[bun:test] Implement `--isolate` flag (first pass at this)jarred/isolation
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 22 | ||||
-rw-r--r-- | src/bun.js/javascript.zig | 10 | ||||
-rw-r--r-- | src/bun.js/test/jest.zig | 1 | ||||
-rw-r--r-- | src/cli.zig | 4 | ||||
-rw-r--r-- | src/cli/test_command.zig | 9 | ||||
-rw-r--r-- | test/js/bun/test/test-isolation-first-2.test.js | 6 | ||||
-rw-r--r-- | test/js/bun/test/test-isolation-first.test.js | 6 |
7 files changed, 57 insertions, 1 deletions
diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index b3da8a98f..a4bd2c54a 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -217,6 +217,7 @@ extern "C" void JSCInitialize(const char* envp[], size_t envc, void (*onCrash)(c JSC::Options::useResizableArrayBuffer() = true; JSC::Options::showPrivateScriptsInStackTraces() = true; JSC::Options::useSetMethods() = true; + JSC::Options::useCodeCache() = true; if (LIKELY(envc > 0)) { while (envc--) { @@ -423,6 +424,26 @@ const JSC::ClassInfo GlobalObject::s_info = { "GlobalObject"_s, &Base::s_info, n extern "C" JSClassRef* Zig__getAPIGlobals(size_t* count); extern "C" const JSC__JSValue* Zig__getAPIConstructors(size_t* count, JSC__JSGlobalObject*); +extern "C" Zig::GlobalObject* GlobalObject__createNewDefault(Zig::GlobalObject* currentDefault, Zig::GlobalObject* initialDefault) +{ + auto& vm = currentDefault->vm(); + auto* prototype = JSC::JSGlobalObject::create(vm, initialDefault->globalObjectStructure()); + Zig::GlobalObject* newDefault = Zig::GlobalObject::create(vm, Zig::GlobalObject::createStructure(vm, prototype, jsNull())); + newDefault->setConsole(newDefault); + size_t count = 0; + JSClassRef* globalObjectClass = Zig__getAPIGlobals(&count); + + if (count > 0) { + newDefault->installAPIGlobals(globalObjectClass, count, vm); + } + + if (initialDefault != currentDefault) { + gcUnprotect(currentDefault); + } + + return newDefault; +} + static JSGlobalObject* deriveShadowRealmGlobalObject(JSGlobalObject* globalObject) { auto& vm = globalObject->vm(); @@ -503,7 +524,6 @@ GlobalObject::~GlobalObject() finalizer(toNapi(this), napiInstanceData, napiInstanceDataFinalizerHint); } - delete crypto; scriptExecutionContext()->removeFromContextsMap(); } diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 4a1fcbcb1..4b95bc992 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -362,6 +362,7 @@ pub const VirtualMachine = struct { preload: []const string = &[_][]const u8{}, unhandled_pending_rejection_to_capture: ?*JSC.JSValue = null, standalone_module_graph: ?*bun.StandaloneModuleGraph = null, + initial_global_object: *JSC.JSGlobalObject, hot_reload: bun.CLI.Command.HotReload = .none, @@ -683,6 +684,7 @@ pub const VirtualMachine = struct { const is_first = !VirtualMachine.get().has_loaded_constructors; if (is_first) { VirtualMachine.get().global = globalObject; + VirtualMachine.get().initial_global_object = globalObject; VirtualMachine.get().has_loaded_constructors = true; } @@ -746,6 +748,7 @@ pub const VirtualMachine = struct { vm.* = VirtualMachine{ .global = undefined, + .initial_global_object = undefined, .allocator = allocator, .entry_point = ServerEntryPoint{}, .event_listeners = EventListenerMixin.Map.init(allocator), @@ -813,6 +816,12 @@ pub const VirtualMachine = struct { return vm; } + extern fn GlobalObject__createNewDefault(*JSGlobalObject, *JSGlobalObject) *JSGlobalObject; + pub fn resetDefaultGlobalObject(this: *VirtualMachine) void { + this.global = GlobalObject__createNewDefault(this.global, this.initial_global_object); + this.event_loop.global = this.global; + } + pub fn init( allocator: std.mem.Allocator, _args: Api.TransformOptions, @@ -843,6 +852,7 @@ pub const VirtualMachine = struct { vm.* = VirtualMachine{ .global = undefined, + .initial_global_object = undefined, .allocator = allocator, .entry_point = ServerEntryPoint{}, .event_listeners = EventListenerMixin.Map.init(allocator), diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index dcc7a8149..aed40f093 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -376,6 +376,7 @@ pub const TestRunner = struct { test_timeout_timer: ?*bun.uws.Timer = null, last_test_timeout_timer_duration: u32 = 0, active_test_for_timeout: ?TestRunner.Test.ID = null, + isolate: bool = false, global_callbacks: struct { beforeAll: std.ArrayListUnmanaged(JSC.JSValue) = .{}, diff --git a/src/cli.zig b/src/cli.zig index 606e0a3cc..d808a2209 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -211,6 +211,7 @@ pub const Arguments = struct { // TODO: update test completions const test_only_params = [_]ParamType{ + clap.parseParam("--isolate Create a new global for each test file") catch unreachable, clap.parseParam("--timeout <NUMBER> Set the per-test timeout in milliseconds, default is 5000.") catch unreachable, clap.parseParam("--update-snapshots Update snapshot files") catch unreachable, clap.parseParam("--rerun-each <NUMBER> Re-run each test file <NUMBER> times, helps catch certain bugs") catch unreachable, @@ -380,6 +381,8 @@ pub const Arguments = struct { }; } } + + ctx.test_options.isolate = args.flag("--isolate"); ctx.test_options.update_snapshots = args.flag("--update-snapshots"); if (args.option("--rerun-each")) |repeat_count| { if (repeat_count.len > 0) { @@ -916,6 +919,7 @@ pub const Command = struct { default_timeout_ms: u32 = 5 * std.time.ms_per_s, update_snapshots: bool = false, repeat_count: u32 = 0, + isolate: bool = false, }; pub const Context = struct { diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index cf5c4fc49..7bdceb3ad 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -436,6 +436,7 @@ pub const TestCommand = struct { reporter.repeat_count = @max(ctx.test_options.repeat_count, 1); reporter.jest.callback = &reporter.callback; jest.Jest.runner = &reporter.jest; + reporter.jest.isolate = ctx.test_options.isolate; js_ast.Expr.Data.Store.create(default_allocator); js_ast.Stmt.Data.Store.create(default_allocator); @@ -721,8 +722,15 @@ pub const TestCommand = struct { vm.main_hash = @truncate(u32, bun.hash(resolution.path_pair.primary.text)); var repeat_count = reporter.repeat_count; var repeat_index: u32 = 0; + const original_preload_len = vm.preload.len; while (repeat_index < repeat_count) : (repeat_index += 1) { var promise = try vm.loadEntryPoint(resolution.path_pair.primary.text); + defer { + if (reporter.jest.isolate) { + vm.preload.len = original_preload_len; + vm.resetDefaultGlobalObject(); + } + } switch (promise.status(vm.global.vm())) { .Rejected => { @@ -772,6 +780,7 @@ pub const TestCommand = struct { prev_unhandled_count = vm.unhandled_error_counter; } } + switch (vm.aggressive_garbage_collection) { .none => {}, .mild => { diff --git a/test/js/bun/test/test-isolation-first-2.test.js b/test/js/bun/test/test-isolation-first-2.test.js new file mode 100644 index 000000000..a59e88bd2 --- /dev/null +++ b/test/js/bun/test/test-isolation-first-2.test.js @@ -0,0 +1,6 @@ +import { test, expect } from "bun:test"; + +test("Object.foo", () => { + expect(Object.foo).toBeUndefined(); + Object.bar = false; +}); diff --git a/test/js/bun/test/test-isolation-first.test.js b/test/js/bun/test/test-isolation-first.test.js new file mode 100644 index 000000000..6c8772825 --- /dev/null +++ b/test/js/bun/test/test-isolation-first.test.js @@ -0,0 +1,6 @@ +import { test, expect } from "bun:test"; + +test("Object.foo", () => { + Object.foo = true; + expect(Object.bar).toBeUndefined(); +}); |