diff options
Diffstat (limited to 'src/javascript')
-rw-r--r-- | src/javascript/jsc/api/bun.zig | 57 | ||||
-rw-r--r-- | src/javascript/jsc/bindings/bindings.cpp | 21 | ||||
-rw-r--r-- | src/javascript/jsc/test/jest.zig | 12 |
3 files changed, 80 insertions, 10 deletions
diff --git a/src/javascript/jsc/api/bun.zig b/src/javascript/jsc/api/bun.zig index 8228139de..72d61d2e9 100644 --- a/src/javascript/jsc/api/bun.zig +++ b/src/javascript/jsc/api/bun.zig @@ -1623,8 +1623,49 @@ pub export fn Bun__escapeHTML( const input_value = arguments[0]; const zig_str = input_value.getZigString(globalObject); + if (zig_str.len == 0) + return ZigString.Empty.toValue(globalObject); + if (zig_str.is16Bit()) { - return input_value; + var input_slice = zig_str.utf16SliceAligned(); + var escaped_html = strings.escapeHTMLForUTF16Input(globalObject.bunVM().allocator, input_slice) catch { + globalObject.vm().throwError(globalObject, ZigString.init("Out of memory").toValue(globalObject)); + return JSC.JSValue.jsUndefined(); + }; + + if (escaped_html.ptr == input_slice.ptr and escaped_html.len == input_slice.len) { + return input_value; + } + + if (input_slice.len == 1) { + // single character escaped strings are statically allocated + return ZigString.init(std.mem.sliceAsBytes(escaped_html)).to16BitValue(globalObject); + } + + if (comptime Environment.allow_assert) { + // assert that re-encoding the string produces the same result + std.debug.assert( + std.mem.eql( + u16, + (strings.toUTF16Alloc(bun.default_allocator, strings.toUTF8Alloc(bun.default_allocator, escaped_html) catch unreachable, false) catch unreachable).?, + escaped_html, + ), + ); + + // assert we do not allocate a new string unnecessarily + std.debug.assert( + !std.mem.eql( + u16, + input_slice, + escaped_html, + ), + ); + + // the output should always be longer than the input + std.debug.assert(escaped_html.len > input_slice.len); + } + + return ZigString.from16(escaped_html.ptr, escaped_html.len).toExternalValue(globalObject); } else { var input_slice = zig_str.slice(); var escaped_html = strings.escapeHTMLForLatin1Input(globalObject.bunVM().allocator, input_slice) catch { @@ -1641,6 +1682,20 @@ pub export fn Bun__escapeHTML( return ZigString.init(escaped_html).toValue(globalObject); } + if (comptime Environment.allow_assert) { + // the output should always be longer than the input + std.debug.assert(escaped_html.len > input_slice.len); + + // assert we do not allocate a new string unnecessarily + std.debug.assert( + !std.mem.eql( + u8, + input_slice, + escaped_html, + ), + ); + } + return ZigString.init(escaped_html).toExternalValue(globalObject); } } diff --git a/src/javascript/jsc/bindings/bindings.cpp b/src/javascript/jsc/bindings/bindings.cpp index 7505a8a8f..a4435f06b 100644 --- a/src/javascript/jsc/bindings/bindings.cpp +++ b/src/javascript/jsc/bindings/bindings.cpp @@ -1101,23 +1101,26 @@ static void free_global_string(void* str, void* ptr, unsigned len) JSC__JSValue ZigString__toExternalU16(const uint16_t* arg0, size_t len, JSC__JSGlobalObject* global) { - return JSC::JSValue::encode(JSC::JSValue(JSC::jsOwnedString( - global->vm(), - ExternalStringImpl::create(reinterpret_cast<const UChar*>(arg0), len, nullptr, free_global_string)))); + auto ref = String(ExternalStringImpl::create(reinterpret_cast<const UChar*>(arg0), len, nullptr, free_global_string)); + + return JSC::JSValue::encode(JSC::JSValue(JSC::jsString( + global->vm(), WTFMove(ref)))); } // This must be a globally allocated string JSC__JSValue ZigString__toExternalValue(const ZigString* arg0, JSC__JSGlobalObject* arg1) { ZigString str = *arg0; if (Zig::isTaggedUTF16Ptr(str.ptr)) { - return JSC::JSValue::encode(JSC::JSValue(JSC::jsOwnedString( + auto ref = String(ExternalStringImpl::create(reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len, nullptr, free_global_string)); + + return JSC::JSValue::encode(JSC::JSValue(JSC::jsString( + arg1->vm(), WTFMove(ref)))); + } else { + auto ref = String(ExternalStringImpl::create(Zig::untag(str.ptr), str.len, nullptr, free_global_string)); + return JSC::JSValue::encode(JSC::JSValue(JSC::jsString( arg1->vm(), - ExternalStringImpl::create(reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len, nullptr, free_global_string)))); + WTFMove(ref)))); } - - return JSC::JSValue::encode(JSC::JSValue(JSC::jsOwnedString( - arg1->vm(), - ExternalStringImpl::create(Zig::untag(str.ptr), str.len, nullptr, free_global_string)))); } VirtualMachine* JSC__JSGlobalObject__bunVM(JSC__JSGlobalObject* arg0) diff --git a/src/javascript/jsc/test/jest.zig b/src/javascript/jsc/test/jest.zig index a07a4bcac..db6353d21 100644 --- a/src/javascript/jsc/test/jest.zig +++ b/src/javascript/jsc/test/jest.zig @@ -367,7 +367,16 @@ pub const Expect = struct { this.scope.tests.items[this.test_id].counter.actual += 1; const left = JSValue.fromRef(arguments[0]); const right = JSValue.fromRef(this.value); + if (!left.isSameValue(right, ctx.ptr())) { + if (left.isString() and right.isString()) { + var left_slice = left.toSlice(ctx, getAllocator(ctx)); + defer left_slice.deinit(); + var right_slice = right.toSlice(ctx, getAllocator(ctx)); + defer right_slice.deinit(); + std.debug.assert(!strings.eqlLong(left_slice.slice(), right_slice.slice(), false)); + } + var lhs_formatter: JSC.ZigConsoleClient.Formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = ctx.ptr() }; var rhs_formatter: JSC.ZigConsoleClient.Formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = ctx.ptr() }; @@ -381,8 +390,10 @@ pub const Expect = struct { ctx, exception, ); + return null; } + return thisObject; } @@ -563,6 +574,7 @@ pub const ExpectPrototype = struct { .scope = DescribeScope.active, .test_id = DescribeScope.active.current_test_id, }; + expect_.value.?.value().ensureStillAlive(); return Expect.Class.make(ctx, expect_); } }; |