Compare commits

...

3 Commits

Author SHA1 Message Date
Jarred Sumner
144f815820 Fixes #12012 2024-06-20 16:24:34 -07:00
Jarred Sumner
1bd57adcbc This fixed a bug where we put the ] on the newline when we shouldn't 2024-06-19 22:42:11 -07:00
Jarred Sumner
d74214b002 Fixes #301 2024-06-19 20:22:14 -07:00
7 changed files with 79 additions and 9 deletions

View File

@@ -2248,6 +2248,17 @@ pub const Formatter = struct {
writer.pretty("<r><d>{d} x empty items<r>", enable_ansi_colors, .{empty_count});
}
}
const Iterator = PropertyIterator(Writer, enable_ansi_colors);
var iter = Iterator{
.formatter = this,
.writer = writer_,
.always_newline = !this.single_line and (this.always_newline_scope or this.goodTimeForANewLine()),
.single_line = this.single_line,
.parent = value,
.i = i,
};
value.forEachPropertyNonIndexed(this.globalThis, &iter, Iterator.forEach);
}
if (!this.single_line and (this.ordered_properties or was_good_time or this.goodTimeForANewLine())) {

View File

@@ -4889,7 +4889,8 @@ bool JSC__JSValue__toBooleanSlow(JSC__JSValue JSValue0, JSC__JSGlobalObject* glo
return JSValue::decode(JSValue0).toBoolean(globalObject);
}
void JSC__JSValue__forEachProperty(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* arg2, void (*iter)(JSC__JSGlobalObject* arg0, void* ctx, ZigString* arg2, JSC__JSValue JSValue3, bool isSymbol, bool isPrivateSymbol))
template<bool nonIndexedOnly>
static void JSC__JSValue__forEachPropertyImpl(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* arg2, void (*iter)(JSC__JSGlobalObject* arg0, void* ctx, ZigString* arg2, JSC__JSValue JSValue3, bool isSymbol, bool isPrivateSymbol))
{
JSC::JSValue value = JSC::JSValue::decode(JSValue0);
JSC::JSObject* object = value.getObject();
@@ -4902,7 +4903,7 @@ void JSC__JSValue__forEachProperty(JSC__JSValue JSValue0, JSC__JSGlobalObject* g
size_t prototypeCount = 0;
JSC::Structure* structure = object->structure();
bool fast = canPerformFastPropertyEnumerationForIterationBun(structure);
bool fast = !nonIndexedOnly && canPerformFastPropertyEnumerationForIterationBun(structure);
JSValue prototypeObject = value;
if (fast) {
@@ -5003,7 +5004,12 @@ restart:
JSObject* iterating = prototypeObject.getObject();
while (iterating && !(iterating == globalObject->objectPrototype() || iterating == globalObject->functionPrototype() || (iterating->inherits<JSGlobalProxy>() && jsCast<JSGlobalProxy*>(iterating)->target() != globalObject)) && prototypeCount++ < 5) {
iterating->methodTable()->getOwnPropertyNames(iterating, globalObject, properties, DontEnumPropertiesMode::Include);
if constexpr (nonIndexedOnly) {
iterating->getOwnNonIndexPropertyNames(globalObject, properties, DontEnumPropertiesMode::Include);
} else {
iterating->methodTable()->getOwnPropertyNames(iterating, globalObject, properties, DontEnumPropertiesMode::Include);
}
RETURN_IF_EXCEPTION(scope, void());
for (auto& property : properties) {
if (UNLIKELY(property.isEmpty() || property.isNull()))
@@ -5013,6 +5019,12 @@ restart:
if (property == vm.propertyNames->constructor || clientData->builtinNames().bunNativePtrPrivateName() == property)
continue;
if constexpr (nonIndexedOnly) {
if (property == vm.propertyNames->length) {
continue;
}
}
JSC::PropertySlot slot(object, PropertySlot::InternalMethodType::Get);
if (!object->getPropertySlot(globalObject, property, slot))
continue;
@@ -5066,6 +5078,10 @@ restart:
iter(globalObject, arg2, &key, JSC::JSValue::encode(propertyValue), property.isSymbol(), isPrivate);
}
if constexpr (nonIndexedOnly) {
break;
}
// reuse memory
properties.data()->propertyNameVector().shrink(0);
if (iterating->isCallable())
@@ -5084,6 +5100,16 @@ restart:
}
}
void JSC__JSValue__forEachProperty(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* arg2, void (*iter)(JSC__JSGlobalObject* arg0, void* ctx, ZigString* arg2, JSC__JSValue JSValue3, bool isSymbol, bool isPrivateSymbol))
{
JSC__JSValue__forEachPropertyImpl<false>(JSValue0, globalObject, arg2, iter);
}
extern "C" void JSC__JSValue__forEachPropertyNonIndexed(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* arg2, void (*iter)(JSC__JSGlobalObject* arg0, void* ctx, ZigString* arg2, JSC__JSValue JSValue3, bool isSymbol, bool isPrivateSymbol))
{
JSC__JSValue__forEachPropertyImpl<true>(JSValue0, globalObject, arg2, iter);
}
void JSC__JSValue__forEachPropertyOrdered(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* arg2, void (*iter)(JSC__JSGlobalObject* arg0, void* ctx, ZigString* arg2, JSC__JSValue JSValue3, bool isSymbol, bool isPrivateSymbol))
{
JSC::JSValue value = JSC::JSValue::decode(JSValue0);

View File

@@ -3727,9 +3727,21 @@ pub const JSValue = enum(JSValueReprInt) {
is_private_symbol: bool,
) callconv(.C) void;
pub extern fn JSC__JSValue__forEachPropertyNonIndexed(JSValue0: JSValue, arg1: *JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?*const fn (*JSGlobalObject, ?*anyopaque, *ZigString, JSValue, bool, bool) callconv(.C) void) void;
pub extern fn JSC__JSValue__forEachProperty(JSValue0: JSValue, arg1: *JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?*const fn (*JSGlobalObject, ?*anyopaque, *ZigString, JSValue, bool, bool) callconv(.C) void) void;
pub extern fn JSC__JSValue__forEachPropertyOrdered(JSValue0: JSValue, arg1: *JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?*const fn (*JSGlobalObject, ?*anyopaque, *ZigString, JSValue, bool, bool) callconv(.C) void) void;
pub fn forEachPropertyNonIndexed(
this: JSValue,
globalThis: *JSC.JSGlobalObject,
ctx: ?*anyopaque,
callback: PropertyIteratorFn,
) void {
JSC__JSValue__forEachPropertyNonIndexed(this, globalThis, ctx, callback);
}
pub fn forEachProperty(
this: JSValue,
globalThis: *JSC.JSGlobalObject,

View File

@@ -2219,6 +2219,8 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionRun, (JSC::JSGlob
DO_REBIND(arg0);
}
int total_changes_before = sqlite3_total_changes(castedThis->version_db->db);
int status = sqlite3_step(stmt);
if (!sqlite3_stmt_readonly(stmt)) {
castedThis->version_db->version++;
@@ -2228,8 +2230,6 @@ JSC_DEFINE_HOST_FUNCTION(jsSQLStatementExecuteStatementFunctionRun, (JSC::JSGlob
initializeColumnNames(lexicalGlobalObject, castedThis);
}
int total_changes_before = sqlite3_total_changes(castedThis->version_db->db);
while (status == SQLITE_ROW) {
status = sqlite3_step(stmt);
}

View File

@@ -1251,3 +1251,15 @@ it("query should work if the cached statement was finalized", () => {
expect(() => prevQuery.get()).toThrow();
}
});
// https://github.com/oven-sh/bun/issues/12012
it("reports changes in Statement#run", () => {
const db = new Database(":memory:");
db.exec("CREATE TABLE cats (id INTEGER PRIMARY KEY, name TEXT)");
const sql = "INSERT INTO cats (name) VALUES ('Fluffy'), ('Furry')";
expect(db.run(sql).changes).toBe(2);
expect(db.prepare(sql).run().changes).toBe(2);
expect(db.query(sql).run().changes).toBe(2);
});

View File

@@ -470,3 +470,14 @@ describe("Functions with names", () => {
});
}
});
it("Bun.inspect array with non-indexed properties", () => {
const a = [1, 2, 3];
a.length = 42;
a[18] = 24;
a.potato = "hello";
console.log(a);
expect(Bun.inspect(a)).toBe(`[
1, 2, 3, 15 x empty items, 24, 23 x empty items, potato: "hello"
]`);
});

View File

@@ -289,13 +289,11 @@ it("should send cipher events in the right order", async () => {
`[ "cipher", "prefinish" ]`,
`[ "cipher", "readable" ]`,
`[ "cipher", "data" ]`,
`[ 1, "dfb6b7e029be3ad6b090349ed75931f28f991b52ca9a89f5bf6f82fa1c87aa2d624bd77701dcddfcceaf3add7d66ce06ced17aebca4cb35feffc4b8b9008b3c4"`,
`]`,
`[ 1, "dfb6b7e029be3ad6b090349ed75931f28f991b52ca9a89f5bf6f82fa1c87aa2d624bd77701dcddfcceaf3add7d66ce06ced17aebca4cb35feffc4b8b9008b3c4" ]`,
`[ "decipher", "prefinish" ]`,
`[ "decipher", "readable" ]`,
`[ "decipher", "data" ]`,
`[ 2, "4f7574206f6620746865206d6f756e7461696e206f6620646573706169722c20612073746f6e65206f6620686f70652e"`,
`]`,
`[ 2, "4f7574206f6620746865206d6f756e7461696e206f6620646573706169722c20612073746f6e65206f6620686f70652e" ]`,
`[ 3, "Out of the mountain of despair, a stone of hope." ]`,
`[ 4, "Out of the mountain of despair, a stone of hope." ]`,
`[ "cipher", "finish" ]`,