Merge branch 'main' of github.com:oven-sh/bun into ali/sql-types

This commit is contained in:
Alistair Smith
2025-07-07 11:37:51 -07:00
55 changed files with 1108 additions and 931 deletions

View File

@@ -1,5 +1,5 @@
{
"snapshot": "snapshot-20250630-a406baa4-6bb1-41d9-a125-85176851e05b",
"snapshot": "snapshot-20250706-71021aff-cc0d-4a7f-a468-d443b16c4bf1",
"install": "bun install",
"terminals": [
{

View File

@@ -1,8 +1,9 @@
---
description: How Zig works with JavaScriptCore bindings generator
globs:
globs:
alwaysApply: false
---
# Bun's JavaScriptCore Class Bindings Generator
This document explains how Bun's class bindings generator works to bridge Zig and JavaScript code through JavaScriptCore (JSC).
@@ -24,7 +25,7 @@ The `.classes.ts` files define the JavaScript API using a declarative approach:
```typescript
// Example: encoding.classes.ts
define({
name: "TextDecoder",
name: "TextDecoder",
constructor: true,
JSType: "object",
finalize: true,
@@ -40,17 +41,18 @@ define({
},
fatal: {
// Read-only property
getter: true,
getter: true,
},
ignoreBOM: {
// Read-only property
getter: true,
}
}
},
},
});
```
Each class definition specifies:
- The class name
- Whether it has a constructor
- JavaScript type (object, function, etc.)
@@ -87,7 +89,7 @@ pub const TextDecoder = struct {
// Fields
});
}
// Prototype methods - note return type includes JSError
pub fn decode(
this: *TextDecoder,
@@ -96,23 +98,23 @@ pub const TextDecoder = struct {
) bun.JSError!JSC.JSValue {
// Implementation
}
// Getters
pub fn getEncoding(this: *TextDecoder, globalObject: *JSGlobalObject) JSC.JSValue {
return JSC.JSValue.createStringFromUTF8(globalObject, this.encoding);
}
pub fn getFatal(this: *TextDecoder, globalObject: *JSGlobalObject) JSC.JSValue {
return JSC.JSValue.jsBoolean(this.fatal);
}
// Cleanup - note standard pattern of using deinit/deref
fn deinit(this: *TextDecoder) void {
// Release any retained resources
// Free the pointer at the end.
bun.destroy(this);
}
// Finalize - called by JS garbage collector. This should call deinit, or deref if reference counted.
pub fn finalize(this: *TextDecoder) void {
this.deinit();
@@ -121,6 +123,7 @@ pub const TextDecoder = struct {
```
Key components in the Zig file:
- The struct containing native state
- `pub const js = JSC.Codegen.JS<ClassName>` to include generated code
- Constructor and methods using `bun.JSError!JSValue` return type for proper error handling
@@ -128,6 +131,7 @@ Key components in the Zig file:
- Methods matching the JavaScript interface
- Getters/setters for properties
- Proper resource cleanup pattern with `deinit()` and `finalize()`
- Update `src/bun.js/bindings/generated_classes_list.zig` to include the new class
## Code Generation System
@@ -140,6 +144,7 @@ The binding generator produces C++ code that connects JavaScript and Zig:
5. **Property Caching**: Implements the caching system for properties
The generated C++ code includes:
- A JSC wrapper class (`JSTextDecoder`)
- A prototype class (`JSTextDecoderPrototype`)
- A constructor function (`JSTextDecoderConstructor`)
@@ -152,28 +157,29 @@ The `CallFrame` object provides access to JavaScript execution context:
```zig
pub fn decode(
this: *TextDecoder,
this: *TextDecoder,
globalObject: *JSGlobalObject,
callFrame: *JSC.CallFrame
) bun.JSError!JSC.JSValue {
// Get arguments
const input = callFrame.argument(0);
const options = callFrame.argument(1);
// Get this value
const thisValue = callFrame.thisValue();
// Implementation with error handling
if (input.isUndefinedOrNull()) {
return globalObject.throw("Input cannot be null or undefined", .{});
}
// Return value or throw error
return JSC.JSValue.jsString(globalObject, "result");
}
```
CallFrame methods include:
- `argument(i)`: Get the i-th argument
- `argumentCount()`: Get the number of arguments
- `thisValue()`: Get the `this` value
@@ -201,17 +207,17 @@ JSC_DEFINE_CUSTOM_GETTER(TextDecoderPrototype__encodingGetterWrap, (...)) {
auto throwScope = DECLARE_THROW_SCOPE(vm);
JSTextDecoder* thisObject = jsCast<JSTextDecoder*>(JSValue::decode(encodedThisValue));
JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject);
// Check for cached value and return if present
if (JSValue cachedValue = thisObject->m_encoding.get())
return JSValue::encode(cachedValue);
// Get value from Zig implementation
JSC::JSValue result = JSC::JSValue::decode(
TextDecoderPrototype__getEncoding(thisObject->wrapped(), globalObject)
);
RETURN_IF_EXCEPTION(throwScope, {});
// Store in cache for future access
thisObject->m_encoding.set(vm, thisObject, result);
RELEASE_AND_RETURN(throwScope, JSValue::encode(result));
@@ -253,7 +259,7 @@ This system provides several key benefits:
1. **Automatic Memory Management**: The JavaScriptCore GC tracks and manages these values
2. **Proper Garbage Collection**: The WriteBarrier ensures values are properly visited during GC
3. **Consistent Access**: Zig code can easily get/set these cached JS values
4. **Performance**: Cached values avoid repeated computation or serialization
4. **Performance**: Cached values avoid repeated computation or serialization
### Use Cases
@@ -281,7 +287,7 @@ Bun uses a consistent pattern for resource cleanup:
pub fn deinit(this: *TextDecoder) void {
// Release resources like strings
this._encoding.deref(); // String deref pattern
// Free any buffers
if (this.buffer) |buffer| {
bun.default_allocator.free(buffer);
@@ -312,7 +318,7 @@ Bun uses `bun.JSError!JSValue` return type for proper error handling:
```zig
pub fn decode(
this: *TextDecoder,
this: *TextDecoder,
globalObject: *JSGlobalObject,
callFrame: *JSC.CallFrame
) bun.JSError!JSC.JSValue {
@@ -320,13 +326,14 @@ pub fn decode(
if (callFrame.argumentCount() < 1) {
return globalObject.throw("Missing required argument", .{});
}
// Or returning a success value
return JSC.JSValue.jsString(globalObject, "Success!");
}
```
This pattern allows Zig functions to:
1. Return JavaScript values on success
2. Throw JavaScript exceptions on error
3. Propagate errors automatically through the call stack
@@ -339,7 +346,7 @@ The binding system includes robust error handling:
// Example of type checking in generated code
JSTextDecoder* thisObject = jsDynamicCast<JSTextDecoder*>(callFrame->thisValue());
if (UNLIKELY(!thisObject)) {
scope.throwException(lexicalGlobalObject,
scope.throwException(lexicalGlobalObject,
Bun::createInvalidThisError(lexicalGlobalObject, callFrame->thisValue(), "TextDecoder"_s));
return {};
}
@@ -351,7 +358,7 @@ The binding system creates proper JavaScript prototype chains:
1. **Constructor**: JSTextDecoderConstructor with standard .prototype property
2. **Prototype**: JSTextDecoderPrototype with methods and properties
3. **Instances**: Each JSTextDecoder instance with __proto__ pointing to prototype
3. **Instances**: Each JSTextDecoder instance with **proto** pointing to prototype
This ensures JavaScript inheritance works as expected:
@@ -360,7 +367,7 @@ This ensures JavaScript inheritance works as expected:
void JSTextDecoderConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSTextDecoderPrototype* prototype)
{
Base::finishCreation(vm, 0, "TextDecoder"_s, PropertyAdditionMode::WithoutStructureTransition);
// Set up the prototype chain
putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
ASSERT(inherits(info()));
@@ -372,7 +379,7 @@ void JSTextDecoderConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* globa
The binding system is optimized for performance:
1. **Direct Pointer Access**: JavaScript objects maintain a direct pointer to Zig objects
2. **Property Caching**: WriteBarrier caching avoids repeated native calls for stable properties
2. **Property Caching**: WriteBarrier caching avoids repeated native calls for stable properties
3. **Memory Management**: JSC garbage collection integrated with Zig memory management
4. **Type Conversion**: Fast paths for common JavaScript/Zig type conversions
@@ -381,6 +388,7 @@ The binding system is optimized for performance:
To create a new class binding in Bun:
1. **Define the class interface** in a `.classes.ts` file:
```typescript
define({
name: "MyClass",
@@ -393,12 +401,13 @@ To create a new class binding in Bun:
myProperty: {
getter: true,
cache: true,
}
}
},
},
});
```
2. **Implement the native functionality** in a `.zig` file:
```zig
pub const MyClass = struct {
// Generated bindings
@@ -409,9 +418,9 @@ To create a new class binding in Bun:
// State
value: []const u8,
pub const new = bun.TrivialNew(@This());
// Constructor
pub fn constructor(
globalObject: *JSGlobalObject,
@@ -420,7 +429,7 @@ To create a new class binding in Bun:
const arg = callFrame.argument(0);
// Implementation
}
// Method
pub fn myMethod(
this: *MyClass,
@@ -429,17 +438,17 @@ To create a new class binding in Bun:
) bun.JSError!JSC.JSValue {
// Implementation
}
// Getter
pub fn getMyProperty(this: *MyClass, globalObject: *JSGlobalObject) JSC.JSValue {
return JSC.JSValue.jsString(globalObject, this.value);
}
// Resource cleanup
pub fn deinit(this: *MyClass) void {
// Clean up resources
}
pub fn finalize(this: *MyClass) void {
this.deinit();
bun.destroy(this);
@@ -474,11 +483,13 @@ For each Zig class, the system generates:
### 3. Zig Bindings
- **External Function Declarations**:
```zig
extern fn TextDecoderPrototype__decode(*TextDecoder, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(JSC.conv) JSC.EncodedJSValue;
```
- **Cached Value Accessors**:
```zig
pub fn encodingGetCached(thisValue: JSC.JSValue) ?JSC.JSValue { ... }
pub fn encodingSetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void { ... }

View File

@@ -175,13 +175,14 @@ Increment:
Options:
--no-git-tag-version Skip git operations
--allow-same-version Prevents throwing error if version is the same
--message=<val>, -m Custom commit message
--preid=<val> Prerelease identifier
--message=<val>, -m Custom commit message, use %s for version substitution
--preid=<val> Prerelease identifier (i.e beta → 1.0.1-beta.0)
--force, -f Bypass dirty git history check
Examples:
$ bun pm version patch
$ bun pm version 1.2.3 --no-git-tag-version
$ bun pm version prerelease --preid beta
$ bun pm version prerelease --preid beta --message "Release beta: %s"
```
To bump the version in `package.json`:

View File

@@ -46,7 +46,7 @@ test
The `snap.test.ts.snap` file is a JavaScript file that exports a serialized version of the value passed into `expect()`. The `{foo: "bar"}` object has been serialized to JSON.
```js
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`snapshot 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`runTests() can run all tests 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`Bun.plugin using { forceSide: 'server' } allows for imported components to be SSR'd: foo.svelte - head 1`] = `""`;

View File

@@ -1184,14 +1184,6 @@ declare module "bun:test" {
* expect(null).toBeInstanceOf(Array); // fail
*/
toBeInstanceOf(value: unknown): void;
/**
* Asserts that the expected value is an instance of value
*
* @example
* expect([]).toBeInstanceOf(Array);
* expect(null).toBeInstanceOf(Array); // fail
*/
toBeInstanceOf(value: unknown): void;
/**
* Asserts that a value is `undefined`.
*

View File

@@ -13,7 +13,7 @@ const VirtualMachine = JSC.VirtualMachine;
const Expect = @import("./expect.zig").Expect;
pub const Snapshots = struct {
const file_header = "// Bun Snapshot v1, https://goo.gl/fbAQLP\n";
const file_header = "// Bun Snapshot v1, https://bun.sh/docs/test/snapshots\n";
const snapshots_dir_name = "__snapshots__" ++ [_]u8{std.fs.path.sep};
pub const ValuesHashMap = std.HashMap(usize, string, bun.IdentityContext(usize), std.hash_map.default_max_load_percentage);

View File

@@ -34,10 +34,6 @@ emit_decorator_metadata: bool = false,
ctx: *BundleV2,
package_version: string = "",
is_entry_point: bool = false,
/// This is set when the file is an entrypoint, and it has an onLoad plugin.
/// In this case we want to defer adding this to additional_files until after
/// the onLoad plugin has finished.
defer_copy_for_bundling: bool = false,
const ParseTaskStage = union(enum) {
needs_source_code: void,

View File

@@ -1964,7 +1964,8 @@ pub const BundleV2 = struct {
this.decrementScanCounter();
},
.success => |code| {
const should_copy_for_bundling = load.parse_task.defer_copy_for_bundling and code.loader.shouldCopyForBundling();
// When a plugin returns a file loader, we always need to populate additional_files
const should_copy_for_bundling = code.loader.shouldCopyForBundling();
if (should_copy_for_bundling) {
const source_index = load.source_index;
var additional_files: *BabyList(AdditionalFile) = &this.graph.input_files.items(.additional_files)[source_index.get()];
@@ -2619,9 +2620,6 @@ pub const BundleV2 = struct {
pub fn enqueueOnLoadPluginIfNeededImpl(this: *BundleV2, parse: *ParseTask) bool {
if (this.plugins) |plugins| {
if (plugins.hasAnyMatches(&parse.path, true)) {
if (parse.is_entry_point and parse.loader != null and parse.loader.?.shouldCopyForBundling()) {
parse.defer_copy_for_bundling = true;
}
// This is where onLoad plugins are enqueued
debug("enqueue onLoad: {s}:{s}", .{
parse.path.namespace,

View File

@@ -11,6 +11,7 @@ const logger = bun.logger;
const JSON = bun.JSON;
const RunCommand = bun.RunCommand;
const Environment = bun.Environment;
const JSPrinter = bun.js_printer;
pub const PmVersionCommand = struct {
const VersionType = enum {
@@ -59,30 +60,45 @@ pub const PmVersionCommand = struct {
defer ctx.allocator.free(package_json_contents);
const package_json_source = logger.Source.initPathString(package_json_path, package_json_contents);
const json = JSON.parsePackageJSONUTF8(&package_json_source, ctx.log, ctx.allocator) catch |err| {
const json_result = JSON.parsePackageJSONUTF8WithOpts(
&package_json_source,
ctx.log,
ctx.allocator,
.{
.is_json = true,
.allow_comments = true,
.allow_trailing_commas = true,
.guess_indentation = true,
},
) catch |err| {
Output.errGeneric("Failed to parse package.json: {s}", .{@errorName(err)});
Global.exit(1);
};
const scripts = json.asProperty("scripts");
var json = json_result.root;
if (json.data != .e_object) {
Output.errGeneric("Failed to parse package.json: root must be an object", .{});
Global.exit(1);
}
const scripts = if (pm.options.do.run_scripts) json.asProperty("scripts") else null;
const scripts_obj = if (scripts) |s| if (s.expr.data == .e_object) s.expr else null else null;
if (pm.options.do.run_scripts) {
if (scripts_obj) |s| {
if (s.get("preversion")) |script| {
if (script.asString(ctx.allocator)) |script_command| {
try RunCommand.runPackageScriptForeground(
ctx,
ctx.allocator,
script_command,
"preversion",
package_json_dir,
pm.env,
&.{},
pm.options.log_level == .silent,
ctx.debug.use_system_shell,
);
}
if (scripts_obj) |s| {
if (s.get("preversion")) |script| {
if (script.asString(ctx.allocator)) |script_command| {
try RunCommand.runPackageScriptForeground(
ctx,
ctx.allocator,
script_command,
"preversion",
package_json_dir,
pm.env,
&.{},
pm.options.log_level == .silent,
ctx.debug.use_system_shell,
);
}
}
}
@@ -96,49 +112,63 @@ pub const PmVersionCommand = struct {
else => {},
}
}
Output.errGeneric("No version field found in package.json", .{});
Global.exit(1);
break :brk_version null;
};
const new_version_str = try calculateNewVersion(ctx.allocator, current_version, version_type, new_version, pm.options.preid, package_json_dir);
const new_version_str = try calculateNewVersion(ctx.allocator, current_version orelse "0.0.0", version_type, new_version, pm.options.preid, package_json_dir);
defer ctx.allocator.free(new_version_str);
if (!pm.options.allow_same_version and strings.eql(current_version, new_version_str)) {
Output.errGeneric("Version not changed", .{});
Global.exit(1);
if (current_version) |version| {
if (!pm.options.allow_same_version and strings.eql(version, new_version_str)) {
Output.errGeneric("Version not changed", .{});
Global.exit(1);
}
}
{
const updated_contents = try updateVersionString(ctx.allocator, package_json_contents, current_version, new_version_str);
defer ctx.allocator.free(updated_contents);
try json.data.e_object.putString(ctx.allocator, "version", new_version_str);
const file = std.fs.cwd().openFile(package_json_path, .{ .mode = .write_only }) catch |err| {
Output.errGeneric("Failed to open package.json for writing: {s}", .{@errorName(err)});
var buffer_writer = JSPrinter.BufferWriter.init(ctx.allocator);
buffer_writer.append_newline = package_json_contents.len > 0 and package_json_contents[package_json_contents.len - 1] == '\n';
var package_json_writer = JSPrinter.BufferPrinter.init(buffer_writer);
_ = JSPrinter.printJSON(
@TypeOf(&package_json_writer),
&package_json_writer,
json,
&package_json_source,
.{
.indent = json_result.indentation,
.mangled_props = null,
},
) catch |err| {
Output.errGeneric("Failed to save package.json: {s}", .{@errorName(err)});
Global.exit(1);
};
defer file.close();
try file.seekTo(0);
try file.setEndPos(0);
try file.writeAll(updated_contents);
std.fs.cwd().writeFile(.{
.sub_path = package_json_path,
.data = package_json_writer.ctx.writtenWithoutTrailingZero(),
}) catch |err| {
Output.errGeneric("Failed to write package.json: {s}", .{@errorName(err)});
Global.exit(1);
};
}
if (pm.options.do.run_scripts) {
if (scripts_obj) |s| {
if (s.get("version")) |script| {
if (script.asString(ctx.allocator)) |script_command| {
try RunCommand.runPackageScriptForeground(
ctx,
ctx.allocator,
script_command,
"version",
package_json_dir,
pm.env,
&.{},
pm.options.log_level == .silent,
ctx.debug.use_system_shell,
);
}
if (scripts_obj) |s| {
if (s.get("version")) |script| {
if (script.asString(ctx.allocator)) |script_command| {
try RunCommand.runPackageScriptForeground(
ctx,
ctx.allocator,
script_command,
"version",
package_json_dir,
pm.env,
&.{},
pm.options.log_level == .silent,
ctx.debug.use_system_shell,
);
}
}
}
@@ -147,22 +177,20 @@ pub const PmVersionCommand = struct {
try gitCommitAndTag(ctx.allocator, new_version_str, pm.options.message, package_json_dir);
}
if (pm.options.do.run_scripts) {
if (scripts_obj) |s| {
if (s.get("postversion")) |script| {
if (script.asString(ctx.allocator)) |script_command| {
try RunCommand.runPackageScriptForeground(
ctx,
ctx.allocator,
script_command,
"postversion",
package_json_dir,
pm.env,
&.{},
pm.options.log_level == .silent,
ctx.debug.use_system_shell,
);
}
if (scripts_obj) |s| {
if (s.get("postversion")) |script| {
if (script.asString(ctx.allocator)) |script_command| {
try RunCommand.runPackageScriptForeground(
ctx,
ctx.allocator,
script_command,
"postversion",
package_json_dir,
pm.env,
&.{},
pm.options.log_level == .silent,
ctx.debug.use_system_shell,
);
}
}
}
@@ -201,7 +229,7 @@ pub const PmVersionCommand = struct {
return;
}
if (!try isGitClean(cwd) and !pm.options.force) {
if (!pm.options.force and !try isGitClean(cwd)) {
Output.errGeneric("Git working directory not clean.", .{});
Global.exit(1);
}
@@ -256,6 +284,15 @@ pub const PmVersionCommand = struct {
Output.prettyln("Current package version: <green>v{s}<r>", .{version});
}
const patch_version = try calculateNewVersion(ctx.allocator, current_version, .patch, null, pm.options.preid, cwd);
const minor_version = try calculateNewVersion(ctx.allocator, current_version, .minor, null, pm.options.preid, cwd);
const major_version = try calculateNewVersion(ctx.allocator, current_version, .major, null, pm.options.preid, cwd);
const prerelease_version = try calculateNewVersion(ctx.allocator, current_version, .prerelease, null, pm.options.preid, cwd);
defer ctx.allocator.free(patch_version);
defer ctx.allocator.free(minor_version);
defer ctx.allocator.free(major_version);
defer ctx.allocator.free(prerelease_version);
const increment_help_text =
\\
\\<b>Increment<r>:
@@ -266,13 +303,20 @@ pub const PmVersionCommand = struct {
\\
;
Output.pretty(increment_help_text, .{
current_version, try calculateNewVersion(ctx.allocator, current_version, .patch, null, pm.options.preid, cwd),
current_version, try calculateNewVersion(ctx.allocator, current_version, .minor, null, pm.options.preid, cwd),
current_version, try calculateNewVersion(ctx.allocator, current_version, .major, null, pm.options.preid, cwd),
current_version, try calculateNewVersion(ctx.allocator, current_version, .prerelease, null, pm.options.preid, cwd),
current_version, patch_version,
current_version, minor_version,
current_version, major_version,
current_version, prerelease_version,
});
if (strings.indexOfChar(current_version, '-') != null or pm.options.preid.len > 0) {
const prepatch_version = try calculateNewVersion(ctx.allocator, current_version, .prepatch, null, pm.options.preid, cwd);
const preminor_version = try calculateNewVersion(ctx.allocator, current_version, .preminor, null, pm.options.preid, cwd);
const premajor_version = try calculateNewVersion(ctx.allocator, current_version, .premajor, null, pm.options.preid, cwd);
defer ctx.allocator.free(prepatch_version);
defer ctx.allocator.free(preminor_version);
defer ctx.allocator.free(premajor_version);
const prerelease_help_text =
\\ <cyan>prepatch<r> <d>{s} → {s}<r>
\\ <cyan>preminor<r> <d>{s} → {s}<r>
@@ -280,12 +324,15 @@ pub const PmVersionCommand = struct {
\\
;
Output.pretty(prerelease_help_text, .{
current_version, try calculateNewVersion(ctx.allocator, current_version, .prepatch, null, pm.options.preid, cwd),
current_version, try calculateNewVersion(ctx.allocator, current_version, .preminor, null, pm.options.preid, cwd),
current_version, try calculateNewVersion(ctx.allocator, current_version, .premajor, null, pm.options.preid, cwd),
current_version, prepatch_version,
current_version, preminor_version,
current_version, premajor_version,
});
}
const beta_prerelease_version = try calculateNewVersion(ctx.allocator, current_version, .prerelease, null, "beta", cwd);
defer ctx.allocator.free(beta_prerelease_version);
const set_specific_version_help_text =
\\ <cyan>from-git<r> <d>Use version from latest git tag<r>
\\ <blue>1.2.3<r> <d>Set specific version<r>
@@ -293,78 +340,22 @@ pub const PmVersionCommand = struct {
\\<b>Options<r>:
\\ <cyan>--no-git-tag-version<r> <d>Skip git operations<r>
\\ <cyan>--allow-same-version<r> <d>Prevents throwing error if version is the same<r>
\\ <cyan>--message<d>=\<val\><r>, <cyan>-m<r> <d>Custom commit message<r>
\\ <cyan>--preid<d>=\<val\><r> <d>Prerelease identifier<r>
\\ <cyan>--message<d>=\<val\><r>, <cyan>-m<r> <d>Custom commit message, use %s for version substitution<r>
\\ <cyan>--preid<d>=\<val\><r> <d>Prerelease identifier (i.e beta → {s})<r>
\\ <cyan>--force<r>, <cyan>-f<r> <d>Bypass dirty git history check<r>
\\
\\<b>Examples<r>:
\\ <d>$<r> <b><green>bun pm version<r> <cyan>patch<r>
\\ <d>$<r> <b><green>bun pm version<r> <blue>1.2.3<r> <cyan>--no-git-tag-version<r>
\\ <d>$<r> <b><green>bun pm version<r> <cyan>prerelease<r> <cyan>--preid<r> <blue>beta<r>
\\ <d>$<r> <b><green>bun pm version<r> <cyan>prerelease<r> <cyan>--preid<r> <blue>beta<r> <cyan>--message<r> <blue>"Release beta: %s"<r>
\\
\\More info: <magenta>https://bun.sh/docs/cli/pm#version<r>
\\
;
Output.pretty(set_specific_version_help_text, .{});
Output.pretty(set_specific_version_help_text, .{beta_prerelease_version});
Output.flush();
}
fn updateVersionString(allocator: std.mem.Allocator, contents: []const u8, old_version: []const u8, new_version: []const u8) ![]const u8 {
const version_key = "\"version\"";
var search_start: usize = 0;
while (std.mem.indexOfPos(u8, contents, search_start, version_key)) |key_pos| {
var colon_pos = key_pos + version_key.len;
while (colon_pos < contents.len and (contents[colon_pos] == ' ' or contents[colon_pos] == '\t')) {
colon_pos += 1;
}
if (colon_pos >= contents.len or contents[colon_pos] != ':') {
search_start = key_pos + 1;
continue;
}
colon_pos += 1;
while (colon_pos < contents.len and (contents[colon_pos] == ' ' or contents[colon_pos] == '\t')) {
colon_pos += 1;
}
if (colon_pos >= contents.len or contents[colon_pos] != '"') {
search_start = key_pos + 1;
continue;
}
const value_start = colon_pos + 1;
var value_end = value_start;
while (value_end < contents.len and contents[value_end] != '"') {
if (contents[value_end] == '\\' and value_end + 1 < contents.len) {
value_end += 2;
} else {
value_end += 1;
}
}
if (value_end >= contents.len) {
search_start = key_pos + 1;
continue;
}
const current_value = contents[value_start..value_end];
if (strings.eql(current_value, old_version)) {
var result = std.ArrayList(u8).init(allocator);
try result.appendSlice(contents[0..value_start]);
try result.appendSlice(new_version);
try result.appendSlice(contents[value_end..]);
return result.toOwnedSlice();
}
search_start = value_end + 1;
}
Output.errGeneric("Version not found in package.json", .{});
Global.exit(1);
}
fn calculateNewVersion(allocator: std.mem.Allocator, current_str: []const u8, version_type: VersionType, specific_version: ?[]const u8, preid: []const u8, cwd: []const u8) bun.OOM![]const u8 {
if (version_type == .specific) {
return try allocator.dupe(u8, specific_version.?);
@@ -487,12 +478,15 @@ pub const PmVersionCommand = struct {
.windows = if (Environment.isWindows) .{
.loop = bun.JSC.EventLoopHandle.init(bun.JSC.MiniEventLoop.initGlobal(null)),
},
}) catch return false;
}) catch |err| {
Output.errGeneric("Failed to spawn git process: {s}", .{@errorName(err)});
Global.exit(1);
};
switch (proc) {
.err => |err| {
Output.err(err, "Failed to spawn git process", .{});
return false;
Global.exit(1);
},
.result => |result| {
return result.isOK() and result.stdout.items.len == 0;
@@ -566,24 +560,27 @@ pub const PmVersionCommand = struct {
},
}) catch |err| {
Output.errGeneric("Git add failed: {s}", .{@errorName(err)});
return;
Global.exit(1);
};
switch (stage_proc) {
.err => |err| {
Output.err(err, "Git add failed unexpectedly", .{});
return;
Global.exit(1);
},
.result => |result| {
if (!result.isOK()) {
Output.errGeneric("Git add failed with exit code {d}", .{result.status.exited.code});
return;
Global.exit(1);
}
},
}
const commit_message = custom_message orelse try std.fmt.allocPrint(allocator, "v{s}", .{version});
defer if (custom_message == null) allocator.free(commit_message);
const commit_message = if (custom_message) |msg|
try std.mem.replaceOwned(u8, allocator, msg, "%s", version)
else
try std.fmt.allocPrint(allocator, "v{s}", .{version});
defer allocator.free(commit_message);
const commit_proc = bun.spawnSync(&.{
.argv = &.{ git_path, "commit", "-m", commit_message },
@@ -597,18 +594,18 @@ pub const PmVersionCommand = struct {
},
}) catch |err| {
Output.errGeneric("Git commit failed: {s}", .{@errorName(err)});
return;
Global.exit(1);
};
switch (commit_proc) {
.err => |err| {
Output.err(err, "Git commit failed unexpectedly", .{});
return;
Global.exit(1);
},
.result => |result| {
if (!result.isOK()) {
Output.errGeneric("Git commit failed", .{});
return;
Global.exit(1);
}
},
}
@@ -628,18 +625,18 @@ pub const PmVersionCommand = struct {
},
}) catch |err| {
Output.errGeneric("Git tag failed: {s}", .{@errorName(err)});
return;
Global.exit(1);
};
switch (tag_proc) {
.err => |err| {
Output.err(err, "Git tag failed unexpectedly", .{});
return;
Global.exit(1);
},
.result => |result| {
if (!result.isOK()) {
Output.errGeneric("Git tag failed", .{});
return;
Global.exit(1);
}
},
}

View File

@@ -2415,19 +2415,35 @@ pub const WriteBytesFn = *const fn(*anyopaque, ptr: [*]const u8, len: u32) callc
`;
const classes: ClassDefinition[] = [];
for (const file of files) {
const result = require(path.resolve(file));
if (!(result?.default?.length ?? 0)) continue;
console.log("Found", result.default.length, "classes from", file);
for (let { name, proto = {}, klass = {} } of result.default) {
let protoProps = Object.keys(proto).length ? `${Object.keys(proto).length} fields` : "";
let klassProps = Object.keys(klass).length ? `${Object.keys(klass).length} class fields` : "";
let props = [protoProps, klassProps].filter(Boolean).join(", ");
if (props.length) props = ` (${props})`;
console.log(` - ${name}` + props);
{
let errors = [];
for (const file of files) {
const filepath = path.resolve(file);
const result = require(filepath);
if (!(result?.default?.length ?? 0)) {
errors.push(
new TypeError(
`Missing classes in "${path.relative(process.cwd(), filepath)}". Expected \`export default [ define(...) ] satisfies Array<ClassDefinition>\` but got ${Bun.inspect(result).slice(0, 100) + "..."} `,
),
);
continue;
}
console.log("Found", result.default.length, "classes from", file);
for (let { name, proto = {}, klass = {} } of result.default) {
let protoProps = Object.keys(proto).length ? `${Object.keys(proto).length} fields` : "";
let klassProps = Object.keys(klass).length ? `${Object.keys(klass).length} class fields` : "";
let props = [protoProps, klassProps].filter(Boolean).join(", ");
if (props.length) props = ` (${props})`;
console.log(` - ${name}` + props);
}
classes.push(...result.default);
}
classes.push(...result.default);
if (errors.length) {
throw new AggregateError(errors, "Failed to generate classes");
}
}
classes.sort((a, b) => (a.name < b.name ? -1 : 1));

View File

@@ -66,7 +66,7 @@ pub fn append16(this: *StringBuilder, slice: []const u16, fallback_allocator: st
var list = std.ArrayList(u8).init(fallback_allocator);
var out = bun.strings.toUTF8ListWithTypeBun(&list, []const u16, slice, false) catch return null;
out.append(0) catch return null;
return list.items[0 .. list.items.len - 1 :0];
return out.items[0 .. out.items.len - 1 :0];
}
}

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`Bun.build Bun.write(BuildArtifact) 1`] = `
"var __defProp = Object.defineProperty;

View File

@@ -820,4 +820,80 @@ describe("bundler", () => {
},
};
});
itBundled("plugin/FileLoaderWithCustomContents", {
files: {
"index.html": /* html */ `
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<img src="./image.jpeg" />
<script src="./script.js"></script>
</body>
</html>
`,
"script.js": /* js */ `
console.log("Script loaded");
`,
"image.jpeg": "actual image data would be here",
},
entryPoints: ["./index.html"],
outdir: "/out",
plugins(build) {
// This plugin intercepts .jpeg files and returns them with custom contents
// This previously caused a crash because additional_files wasn't populated
build.onLoad({ filter: /\.jpe?g$/ }, async args => {
return {
loader: "file",
contents: "custom image contents",
};
});
},
onAfterBundle(api) {
// Verify the build succeeded and files were created
api.assertFileExists("index.html");
// The image should be copied with a hashed name
const html = api.readFile("index.html");
expect(html).toContain('src="');
expect(html).toContain('.jpeg"');
},
});
itBundled("plugin/FileLoaderMultipleAssets", {
files: {
"index.js": /* js */ `
import imgUrl from "./image.png";
import wasmUrl from "./module.wasm";
console.log(imgUrl, wasmUrl);
`,
"image.png": "png data",
"module.wasm": "wasm data",
},
entryPoints: ["./index.js"],
outdir: "/out",
plugins(build) {
// Test multiple file types with custom contents
build.onLoad({ filter: /\.(png|wasm)$/ }, async args => {
const ext = args.path.split(".").pop();
return {
loader: "file",
contents: `custom ${ext} contents`,
};
});
},
run: {
stdout: /\.(png|wasm)/,
},
onAfterBundle(api) {
// Verify the build succeeded and files were created
api.assertFileExists("index.js");
const js = api.readFile("index.js");
// Should contain references to the copied files
expect(js).toContain('.png"');
expect(js).toContain('.wasm"');
},
});
});

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`esbuild-bundler css/CSSAtImportConditionsFromExternalRepo: /out/001/default/style.css 1`] = `
"/* 001/default/a.css */

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`Bun.Transpiler using statements work right 1`] = `
"let __bun_temp_ref_1$ = [];

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`development: true react spa (no tailwind) dev server 1`] = `
"<html><head>

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`junit reporter 1`] = `
"<?xml version="1.0" encoding="UTF-8"?>

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`\`bun audit\` should exit code 1 when there are vulnerabilities: bun-audit-expect-vulnerabilities-found 1`] = `
"minimist <0.2.4

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`npa @scoped/package 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`auto-install symlinks (and junctions) are created correctly in the install cache 1`] = `
"{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`should report error on invalid format for package.json 1`] = `
"1 | foo

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`should write plaintext lockfiles 1`] = `
"{

View File

@@ -1,3 +1,3 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`bun pm migrate 1`] = `"E7F4C15F76D43059-37ed01456afdc149-B17A9541F8322712-04892ad4e094e703"`;

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`dependency on workspace without version in package.json: version: * 1`] = `
"{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`basic detect changes (bun.lock) 1`] = `
"{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`Bun.semver.satisfies() pre-release snapshot 1`] = `
[

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`lcov coverage reporter 1`] = `
"TN:

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`ssr works for 100-ish requests 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`hot reloading works on the client (+ tailwind hmr) 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`next build works: bun 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`sass source maps 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`When bun-plugin-svelte is enabled via Bun.plugin() can be render()-ed 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`inspect.table { a: 1, b: 2 } 1`] = `
"┌───┬────────┐

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`console.table expected output for: not object (number) 1`] = `
"42

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`can run a .c file: cc-fixture-stderr 1`] = `"Hello, World!"`;

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`fast-glob e2e tests patterns regular fixtures/*: fixtures/* 1`] = `
[

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`expect() toMatchSnapshot to return undefined 1`] = `"abc"`;

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`unhandled errors between tests are reported in beforeAll 1`] = `
"

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`toMatchSnapshot errors should throw if arguments are in the wrong order: right spot 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`it will work with an existing snapshot file made with bun 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`d0 d1 t1 1`] = `"hello\`snapshot\\"`;

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`test snapshots with Boolean and Number 1`] = `1`;

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`most types 1`] = `3`;
@@ -370,35 +370,35 @@ exports[`most types: testing 7 3`] = `8`;
exports[`most types: undefined 1`] = `undefined`;
exports[`snapshots dollars 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"$"\`;
"
`;
exports[`snapshots backslash 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"\\\\"\`;
"
`;
exports[`snapshots dollars curly 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"\\\${}"\`;
"
`;
exports[`snapshots dollars curly 2 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"\\\${"\`;
"
`;
exports[`snapshots stuff 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`
"æ™
@@ -409,7 +409,7 @@ exports[\`abc 1\`] = \`
`;
exports[`snapshots stuff 2 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`
"æ™
@@ -420,28 +420,28 @@ exports[\`abc 1\`] = \`
`;
exports[`snapshots regexp 1 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`/\\\${1..}/\`;
"
`;
exports[`snapshots regexp 2 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`/\\\${2..}/\`;
"
`;
exports[`snapshots string 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"abc"\`;
"
`;
exports[`snapshots string with newline 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`
"qwerty
@@ -451,35 +451,35 @@ ioup"
`;
exports[`snapshots null byte 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"1 \\x00"\`;
"
`;
exports[`snapshots null byte 2 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"2 \\x00"\`;
"
`;
exports[`snapshots backticks 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"This is \\\`wrong\\\`"\`;
"
`;
exports[`snapshots unicode 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"😊abc\\\`\\\${def} <20>, <20> "\`;
"
`;
exports[`snapshots jest newline oddity 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`
"
@@ -489,14 +489,14 @@ exports[\`abc 1\`] = \`
`;
exports[`snapshots grow file for new snapshot 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"hello"\`;
"
`;
exports[`snapshots grow file for new snapshot 2`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"hello"\`;
@@ -505,7 +505,7 @@ exports[\`def 1\`] = \`"hello"\`;
`;
exports[`snapshots grow file for new snapshot 3`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"goodbye"\`;
@@ -514,35 +514,35 @@ exports[\`def 1\`] = \`"hello"\`;
`;
exports[`snapshots backtick in test name 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`\\\` 1\`] = \`"abc"\`;
"
`;
exports[`snapshots dollars curly in test name 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`\\\${} 1\`] = \`"abc"\`;
"
`;
exports[`snapshots #15283 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`Should work 1\`] = \`"This is \\\`wrong\\\`"\`;
"
`;
exports[`snapshots #15283 unicode 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`Should work 1\`] = \`"😊This is \\\`wrong\\\`"\`;
"
`;
exports[`snapshots replaces file that fails to parse when update flag is used 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`t1 1\`] = \`"abc def ghi jkl"\`;
@@ -553,7 +553,7 @@ exports[\`t3 1\`] = \`"abc def ghi"\`;
`;
exports[`snapshots property matchers 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`
{
@@ -582,7 +582,7 @@ exports[`inline snapshots #15283 1`] = `
`;
exports[`snapshots unicode surrogate halves 1`] = `
"// Bun Snapshot v1, https://goo.gl/fbAQLP
"// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[\`abc 1\`] = \`"😊abc\\\`\\\${def} <20>, <20> "\`;
"

View File

@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`snapshots in different directory 1`] = `
"12

View File

@@ -311,7 +311,7 @@ for (const inlineSnapshot of [false, true]) {
{ forceUpdate: true },
);
expect(await t.getSnapshotContents()).toBe(
'// Bun Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`t1 1`] = `"abc def ghi jkl"`;\n\nexports[`t2 1`] = `"abc\\`def"`;\n\nexports[`t3 1`] = `"abc def ghi"`;\n',
'// Bun Snapshot v1, https://bun.sh/docs/test/snapshots\n\nexports[`t1 1`] = `"abc def ghi jkl"`;\n\nexports[`t2 1`] = `"abc\\`def"`;\n\nexports[`t3 1`] = `"abc def ghi"`;\n',
);
});

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`error.cause 1`] = `
"1 | import { expect, test } from "bun:test";

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`reportError 1`] = `
"1 | reportError(new Error("reportError Test!"));

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`can get sourceURL from eval inside node:vm 1`] = `
"evalmachine.<anonymous>:2

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`it works 1`] = `
{

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`console.group: console-group-error 1`] = `
"Warning log

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`WebSocket error event snapshot: Snapshot snapshot 1`] = `ErrorEvent {
type: "error",

View File

@@ -1,4 +1,4 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`macros should not lead to seg faults under any given input 1`] = `
"2 | fn(\`©\${Number(0)}\`);