RESOLVED MOVED291138
TextDecoder.decode() fails with TypeError: Type error in Safari Technology Preview release 216
https://bugs.webkit.org/show_bug.cgi?id=291138
Summary TextDecoder.decode() fails with TypeError: Type error in Safari Technology Pr...
Andrew Hodel
Reported 2025-04-05 10:57:13 PDT
Created attachment 474836 [details] console output This is the failing Javascript code, it only happens when the memory heap is beyond a certain size in Safari and works in all other browsers. ``` 1675 var ab = existing_array_buffer; 1676 console.log(ab); 1677 console.log(ab instanceof ArrayBuffer); 1678 console.log(new TextDecoder().decode(ab)); ``` Look at the attached screenshot to see the console output of `TypeError: Type error` at line 1678. The data in the array buffer is `97, 97, 97, 97`, valid utf8 data that writes to a string with: ``` var utf8_text_decode = function(ab) { var v = new DataView(ab); var s = ''; var l = 0; while (l < v.byteLength) { s += String.fromCharCode(v.getUint8(l)); l++; } return s; } ``` As is obvious, that function does not work with any except 0-255 in utf8 and certainly does not work with utf16. That's not very nice considering the browser is named Safari and once you are writing in most other languages Safari is unable to decode an ArrayBuffer to a string. The Basic Multilingual Plane (BMP) is the first plane in the Unicode character set, containing code points from U+0000 to U+FFFF, encompassing most commonly used characters and symbols for various languages. As it stands you are wasting people's time making them write a Unicode processor that supports all of utf8 and utf16 and most of them probably don't know that. There are many already written functions for this at this link, why does Safari do this to people? https://stackoverflow.com/questions/17191945/conversion-between-utf-8-arraybuffer-and-string
Attachments
console output (112.64 KB, image/png)
2025-04-05 10:57 PDT, Andrew Hodel
no flags
test (doesn't reproduce) (233 bytes, text/html)
2025-04-07 15:55 PDT, Alexey Proskuryakov
no flags
Andrew Hodel
Comment 1 2025-04-05 11:00:40 PDT
This works and can be used without charge until Apple fixes this bug. https://jsfiddle.net/3VuLx/2/
Alexey Proskuryakov
Comment 2 2025-04-07 15:55:44 PDT
Created attachment 474864 [details] test (doesn't reproduce) Thank you for the report! I tried to re-create a test from your description, but it works as expected (not too surprising given the "only happens when the memory heap is beyond a certain size" part of your report). Would it be possible for you to provide steps to reproduce that we could follow to see the issue in action?
Radar WebKit Bug Importer
Comment 3 2025-04-12 10:58:12 PDT
Andrew Hodel
Comment 4 2025-04-13 09:23:46 PDT
I understand the dilemma of proof and don't understand why the error output of ArrayBuffer cannot explain why with numbers. For example, why does the error output of ArrayBuffer not output something like: Because 13MB of other objects, 4000 being ArrayBuffer, 2000 being {} in the last 15 minutes of active tab usage and 500MB of other objects, 25000 being ArrayBuffer, 33000 being {} in the last 15 seconds of active tab usage exceeds the limits shown in [table of allocation limits and overlapping time]. There's really no reason not to improve the error output to that level if you have decided to not let the limits of allocation be based on the hardware. The fact is that if Webkit is not used, the hardware is able to handle the allocation that is requested. It works in Google Chrome. I've already shown you the error in a screenshot of the console and it does not explain why in the detail required to solve the problem. The amount of allocated space is very small, the number of new allocations is moderate to many and it seems that you are expecting garbage control instead of accepting that JavaScript parses to the end of a function before the single thread moves to another context if there are no other function calls within the function context. If the new allocation is declared within the root function context and there is no usage of it in the functions within the root function context and each new allocation is within an outer loop that is of the same context truths there is no possibility of not clearing the allocation at the end of each loop iteration instead of piling it all into something that is cleared at short intervals that are much longer than the interval a while loop executes at. This is what Webkit does differently and it's wrong, the limits and requests that exceed the limits would prove where the problem is (in other words how are there this many MB of data requested) and the logical conclusion would be that the new allocations that are being used and not required anywhere later are not being cleared at the end of each iteration of the while loop. Because of the way that ArrayBuffer requires slice (that makes a new ArrayBuffer allocation) to remove data from the start of an ArrayBuffer or requires using a DataView to write to another ArrayBuffer (that also makes a new ArrayBuffer allocation), there is no other way to parse incoming data without doing exactly what you are doing wrong, and that is adding the data to a buffer then running a loop to deal with it (a much easier task or a much harder task) and the speed results are in my favor regardless of it being less work for me. The fact is that if you are going to provide a browser, you need to do this based on the performance not based on the truth that it is easier for you.
Andrew Hodel
Comment 5 2026-03-20 10:44:08 PDT
Note You need to log in before you can comment on or make changes to this bug.