diff --git a/docz/docs/03-demos/01-math/11-tensorflow.md b/docz/docs/03-demos/01-math/11-tensorflow.md index 841eb14..c7d5a3e 100644 --- a/docz/docs/03-demos/01-math/11-tensorflow.md +++ b/docz/docs/03-demos/01-math/11-tensorflow.md @@ -34,22 +34,23 @@ results back to spreadsheets. Each browser demo was tested in the following environments: -| Browser | TF.js version | Date | -|:------------|:--------------|:-----------| -| Chrome 127 | `4.20.0` | 2024-08-16 | -| Safari 17.4 | `4.20.0` | 2024-08-16 | +| Browser | TF.js | Date | +|:------------|:----------|:-----------| +| Chrome 133 | `4.22.0` | 2025-04-21 | +| Safari 18.3 | `4.22.0` | 2025-04-21 | The NodeJS demo was tested in the following environments: -| NodeJS | TF.js version | Date | -|:---------|:------------------------------|:-----------| -| `22.3.0` | `4.20.0` (`@tensorflow/tfjs`) | 2024-08-16 | +| NodeJS | TF.js | Date | +|:------------|:----------|:-----------| +| `22.14.0` | `4.22.0` | 2025-04-21 | +| `20.18.0` | `4.22.0` | 2025-04-21 | The Kaioken demo was tested in the following environments: -| Kaioken | TF.js version | Date | -|:----------|:--------------|:-----------| -| `0.25.3` | `4.20.0` | 2024-08-16 | +| Kaioken | TF.js | Date | +|:------------|:----------|:-----------| +| `0.37.0` | `4.22.0` | 2025-04-21 | ::: @@ -57,7 +58,7 @@ The Kaioken demo was tested in the following environments: #### Standalone Browser Scripts -Live code blocks in this page use the TF.js `4.20.0` standalone build. +Live code blocks in this page use the TF.js `4.22.0` standalone build. Standalone scripts are available on various CDNs including UNPKG. The latest version can be loaded with the following `SCRIPT` tag. diff --git a/docz/docs/03-demos/30-cloud/11-aws.md b/docz/docs/03-demos/30-cloud/11-aws.md index bf931e3..6e1655c 100644 --- a/docz/docs/03-demos/30-cloud/11-aws.md +++ b/docz/docs/03-demos/30-cloud/11-aws.md @@ -33,7 +33,7 @@ will be available in the future. :::note Tested Deployments -This demo was last tested on 2024-06-13. +This demo was last tested on 2025-04-21. ::: @@ -72,7 +72,7 @@ The `busboy` body parser[^2] is battle-tested in NodeJS deployments. `busboy` fires a `'file'` event for every file in the form body. The callback receives a NodeJS stream that should be collected into a Buffer: -```js +```js title="Collecting file data from an upload (sketch)" /* accumulate the files manually */ var files = {}; bb.on('file', function(fieldname, file, filename) { @@ -93,7 +93,7 @@ workbook objects[^4] which can be processed with other API functions. For example, a handler can use `sheet_to_csv`[^5] to generate CSV text: -```js +```js title="Parse an uploaded file and generate a CSV (sketch)" /* on the finish event, all of the fields and files are ready */ bb.on('finish', function() { /* grab the first file */ @@ -116,7 +116,7 @@ bb.on('finish', function() { This example takes the first uploaded file submitted with the key `upload`, parses the file and returns the CSV content of the first worksheet. -```js +```js title="Complete Lambda Function" const XLSX = require('xlsx'); var Busboy = require('busboy'); @@ -168,7 +168,7 @@ For safely transmitting binary data, Base64 strings should be used. The SheetJS `write` method[^6] with the option `type: "base64"` will generate Base64-encoded strings. -```js +```js title="Generate a Base64-encoded XLSX workbook (sketch)" /* sample SheetJS workbook object */ var wb = XLSX.read("S,h,e,e,t,J,S\n5,4,3,3,7,9,5", {type: "binary"}); /* write to XLSX file in Base64 encoding */ @@ -179,7 +179,7 @@ The Lambda callback response function accepts options. Setting `isBase64Encoded` to `true` will ensure the callback handler decodes the data. To ensure browsers will try to download the response, the `Content-Disposition` header must be set: -```js +```js title="Respond with an attachment (sketch)" callback(null, { statusCode: 200, /* Base64-encoded file */ @@ -197,7 +197,7 @@ callback(null, { This example creates a sample workbook object and sends the file in the response: -```js +```js title="Complete Lambda Function" var XLSX = require('xlsx'); exports.handler = function(event, context, callback) { @@ -230,7 +230,7 @@ free requests per month and 400 thousand GB-seconds of compute resources. ::: -0) If you do not have an account, create a new AWS free tier account[^7]. +0) Create a new AWS free tier account[^7] or sign into an existing AWS account. #### Create Project ZIP @@ -251,13 +251,13 @@ curl -LO https://docs.sheetjs.com/aws/index.js {`\ mkdir -p node_modules -npm i https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz busboy`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz busboy`} 4) Create a .zip package of the contents of the folder: ```bash -zip -c ../SheetJSLambda.zip -r . +zip ../SheetJSLambda.zip -r . ``` #### Lambda Setup @@ -282,13 +282,17 @@ If the left sidebar is not open, click the `≡` icon in the left edge of the pa - Type a memorable "Function Name" ("SheetJSLambda" when last tested) - In the "Runtime" dropdown, look for the "Latest supported" section and select - "Node.js" ("Node.js 20.x" when last tested) + "Node.js" ("Node.js 22.x" when last tested) -- Expand "Advanced Settings" and check "Enable function URL". This will display - a few sub-options: +![Select Node.js runtime](pathname:///aws/runtime.png) + +- Expand "Additional Configurations" and check "Enable function URL". The page + will show additional sub-options: + "Auth type" select "NONE" (disable IAM authentication) + Check "Configure cross-origin resource sharing (CORS)" +![Select Additional Configurations](pathname:///aws/additional.png) + 10) Click "Create function" to create the function. #### Upload Code @@ -297,18 +301,25 @@ If the left sidebar is not open, click the `≡` icon in the left edge of the pa 12) Click the "Upload from" dropdown and select ".zip file". +![Upload from .zip file](pathname:///aws/upload-code.png) + 13) Click the "Upload" button in the modal. With the file picker, select the `SheetJSLambda.zip` file created in step 3. Click "Save". +![Modal after uploading SheetJSLambda.zip](pathname:///aws/upload-zip.png) + :::note pass + When the demo was last tested, the ZIP was small enough that the Lambda code -editor will load the package. +editor loaded the package. ::: 14) In the code editor, double-click `index.js` and confirm the code editor displays JavaScript code. +![Editor window post-upload](pathname:///aws/editor-postload.png) + #### External Access 15) Click "Configuration" in the tab list. @@ -331,7 +342,10 @@ If no policy statements are defined, select "Add Permission" with the options: - Ensure that Principal is set to `*` - Ensure that Action is set to `lambda:InvokeFunctionUrl` -Click "Save" and a new Policy statement should be created. +Click "Save" and a new Policy statement should be created. The corresponding row +should match the details in the following screenshot: + +![Resource-based policy statements](pathname:///aws/rbps.png) #### Lambda Testing @@ -367,7 +381,7 @@ The `aws-sdk` module exports a function `S3` that performs the connection. The function expects an options object that includes an API version and credentials. Access keys for an IAM user[^9] must be used: -```js +```js title="Connect to S3 from NodeJS (sketch)" /* credentials */ var accessKeyId = "...", secretAccessKey = "...""; @@ -389,7 +403,7 @@ var s3 = new AWS.S3({ The `s3#getObject` method returns an object with a `createReadStream` method. `createReadStream` returns a NodeJS stream: -```js +```js title="Get Object from S3 (sketch)" /* open stream to the file */ var stream = s3.getObject({ Bucket: Bucket, Key: Key }).createReadStream(); ``` @@ -398,7 +412,7 @@ var stream = s3.getObject({ Bucket: Bucket, Key: Key }).createReadStream(); Buffers can be concatenated from the stream into one unified Buffer object: -```js +```js title="Fetch data from S3 object and collect into a Buffer (sketch)" /* array of buffers */ var bufs = []; /* add each data chunk to the array */ @@ -419,7 +433,7 @@ workbook objects[^11] which can be processed with other API functions. For example, a callback can use `sheet_to_csv`[^12] to generate CSV text: -```js +```js title="Parse workbook from S3 and generate a CSV (sketch)" stream.on('end', function() { /* concatenate */ var buf = Buffer.concat(bufs); @@ -442,7 +456,7 @@ NodeJS Buffers. `S3#upload` directly accepts these Buffer objects. This example creates a sample workbook object, generates XLSX file data in a NodeJS Buffer, and uploads the data to S3: -```js +```js title="Upload sample workbook to S3 (sketch)" /* generate sample workbook */ var wb = XLSX.read("S,h,e,e,t,J,S\n5,4,3,3,7,9,5", {type: "binary"}); @@ -478,7 +492,7 @@ a root user account. ![AWS search for "S3"](pathname:///aws/S3.png) -3) Open "Buckets" in the left sidebar. +3) Open "General purpose buckets" in the left sidebar. If the left sidebar is not open, click the `≡` icon in the left edge of the page. @@ -486,7 +500,9 @@ If the left sidebar is not open, click the `≡` icon in the left edge of the pa 5) Select the following options: -- Type a memorable "Bucket Name" ("sheetjsbouquet" when last tested) +- Bucket Type: "General purpose" (default) + +- Type a memorable "Bucket Name" ("sheetjsbuckit" when last tested) - In the "Object Ownership" section, select "ACLs disabled" @@ -536,7 +552,8 @@ There should be one entry. #### Generate Keys -20) Click "Security credentials", then click "Create access key". +20) Click "Security credentials", then scroll down to the "Access keys" section +and click "Create access key". 21) Select the "Local code" option. Check "I understand the above recommendation and want to proceed to create an access key." and click "Next" @@ -562,7 +579,7 @@ npm init -y {`\ mkdir -p node_modules -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz aws-sdk@2.1467.0`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz aws-sdk@2.1692.0`} #### Write Test diff --git a/docz/docs/03-demos/30-cloud/22-airtable.md b/docz/docs/03-demos/30-cloud/22-airtable.md index 0f825e2..820ada5 100644 --- a/docz/docs/03-demos/30-cloud/22-airtable.md +++ b/docz/docs/03-demos/30-cloud/22-airtable.md @@ -1,5 +1,6 @@ --- -title: Airtable +title: Flying Sheets with Airtable +sidebar_label: Airtable pagination_prev: demos/local/index pagination_next: demos/extensions/index --- @@ -206,7 +207,7 @@ const wb = XLSX.readFile("SheetJSAirtableTest.xlsb"); :::note Tested Deployments -This demo was last tested on 2024-05-04. In the most recent test, free accounts +This demo was last tested on 2025-04-21. In the most recent test, free accounts included limited API access. ::: @@ -215,16 +216,9 @@ included limited API access. ### Personal Access Token -:::note pass - -In the past, Airtable offered API keys. They were officially deprecated on 2024 -February 1. They recommend "Personal Access Tokens" for operations. - -::: - API actions will require a PAT, which must be created through the developer hub: -1) Click on account icon (topright area of the page) and select "Developer Hub". +1) Click on account icon (topright area of the page) and select "Builder Hub". :::caution pass @@ -233,7 +227,7 @@ to create a token. ::: -2) Click the blue "Create Token" button. +2) Click "Personal access tokens" in the sidebar, then click "Create Token". 3) In the form, make the following selections: @@ -253,10 +247,18 @@ For the purposes of this demo, a sample workspace should be created: 5) Download https://docs.sheetjs.com/pres.xlsx -6) Click "Back to Home" to return to the home page. +6) Click the left arrow in the top-left corner to return to the home page. -7) Create a project in Airtable using "Quickly upload". Select "Microsoft Excel" -and select the downloaded file from step 1. Click "Upload", then "Import". +7) In the left sidebar, scroll down and click the "Import" link. + +In the modal, select "Microsoft Excel". + +In the upload modal, click "browse files" and select `pres.xlsx` from Step 5. + +Click the blue "Upload 1 file" button. + +In the new modal, click "Import". When this demo was last tested, Airtable +created 5 records with "Name" and "Index" column headers. 8) A workspace will be created. The name will be found in the URL. For example: @@ -315,7 +317,8 @@ const base = "app..."; node SheetJSAirtableRead.js ``` -The script should write `SheetJSAirtable.xlsb`. The file can be opened in Excel. +The script will export the data from Airtable to `SheetJSAirtable.xlsb`. The new +spreadsheet can be opened in Excel. ### Importing Data @@ -361,7 +364,7 @@ Open Airtable and verify the new row was added: [^1]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input) [^2]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`. [^3]: See [`writeFile` in "Writing Files"](/docs/api/write-options) -[^4]: See ["Sheet Objects"](/docs/csf/sheet) for more details/ +[^4]: See ["Sheet Objects"](/docs/csf/sheet) for more details [^5]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output) [^6]: See ["Workbook Object"](/docs/csf/book) [^7]: See [`readFile` in "Reading Files"](/docs/api/parse-options) diff --git a/docz/docs/03-demos/42-engines/04-jsc.md b/docz/docs/03-demos/42-engines/04-jsc.md index e9108e4..17ce6c8 100644 --- a/docz/docs/03-demos/42-engines/04-jsc.md +++ b/docz/docs/03-demos/42-engines/04-jsc.md @@ -42,9 +42,9 @@ JavaScriptCore can be built from source and linked in C / C++ programs. | Architecture | Version | Date | |:-------------|:-----------------|:-----------| | `darwin-x64` | `7618.2.12.11.7` | 2025-01-10 | -| `darwin-arm` | `7620.2.4.111.7` | 2025-02-13 | +| `darwin-arm` | `7620.2.4.111.7` | 2025-04-21 | | `linux-x64` | `7618.2.12.11.7` | 2024-06-22 | -| `linux-arm` | `7618.2.12.11.7` | 2024-06-22 | +| `linux-arm` | `7620.2.4.111.7` | 2025-04-21 | [**Swift Compiled from Source**](#swift-c) @@ -53,7 +53,7 @@ Swift compiler can link against libraries built from the JavaScriptCore source. | Architecture | Version | Date | |:-------------|:-----------------|:-----------| | `linux-x64` | `7618.2.12.11.7` | 2024-06-22 | -| `linux-arm` | `7618.2.12.11.7` | 2024-06-22 | +| `linux-arm` | `7620.2.4.111.7` | 2025-04-21 | ::: @@ -409,6 +409,20 @@ to `SheetJSwift.xlsx`. That file can be verified by opening in Excel / Numbers. ### C++ +:::danger pass + +Older versions of this demo recommended downloading the WebKit release archives. + +**Microsoft disabled all WebKit archive downloads!** + +https://codeload.github.com/WebKit/WebKit/zip/refs/tags/WebKit-7620.2.4.111.7 , +when the demo was last tested, returned HTTP 422 `Archive creation is blocked`. + +The updated instructions now clone the repository. An additional 20GB of storage +space and 11GB of bandwidth is required to fetch and store the code. + +::: + 0) Install dependencies
@@ -443,12 +457,13 @@ mkdir sheetjs-jsc cd sheetjs-jsc ``` -2) Download and extract the WebKit snapshot: +2) Clone the WebKit repository and switch to the `WebKit-7620.2.4.111.7` tag: ```bash -curl -LO https://codeload.github.com/WebKit/WebKit/zip/refs/tags/WebKit-7620.2.4.111.7 -mv WebKit-7620.2.4.111.7 WebKit.zip -unzip WebKit.zip +git clone https://github.com/WebKit/WebKit.git WebKit +cd WebKit +git checkout WebKit-7620.2.4.111.7 +cd .. ``` 3) Build JavaScriptCore: @@ -457,27 +472,27 @@ unzip WebKit.zip ```bash -cd WebKit-WebKit-7620.2.4.111.7 -Tools/Scripts/build-webkit --jsc-only --cmakeargs="-DENABLE_STATIC_JSC=ON" +cd WebKit +env CFLAGS="-Wno-error -Wno-deprecated-declarations" CXXFLAGS="-Wno-error -Wno-deprecated-declarations" LDFLAGS="-framework Foundation" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error -DENABLE_STATIC_JSC=ON -DCMAKE_C_FLAGS=\"-Wno-error -Wno-deprecated-declarations\" -DCMAKE_CXX_FLAGS=\"-Wno-error -Wno-deprecated-declarations\"" --make-args="-Wno-error -Wno-deprecated-declarations" cd .. ``` -:::danger pass +:::note pass -When this demo was last tested on ARM64 macOS, JIT elicited runtime errors and -WebAssembly elicited compile-time errors. WebAssembly and JIT must be disabled: +In some test runs on ARM64 macOS, JIT elicited runtime errors and WebAssembly +elicited compile-time errors. WebAssembly and JIT should be disabled: ```bash -cd WebKit-WebKit-7620.2.4.111.7 -env CFLAGS="-Wno-error -Wno-deprecated-declarations" CXXFLAGS="-Wno-error -Wno-deprecated-declarations" LDFLAGS="-framework Foundation" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error -DENABLE_STATIC_JSC=ON -DCMAKE_C_FLAGS=\"-Wno-error -Wno-deprecated-declarations\" -DCMAKE_CXX_FLAGS=\"-Wno-error -Wno-deprecated-declarations\"" --no-jit --no-webassembly --make-args="-Wno-error -Wno-deprecated-declarations" +cd WebKit +env CFLAGS="-Wno-error -Wno-deprecated-declarations" CXXFLAGS="-Wno-error -Wno-deprecated-declarations" LDFLAGS="-framework Foundation" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error -DENABLE_STATIC_JSC=ON -DCMAKE_C_FLAGS=\"-Wno-error -Wno-deprecated-declarations\" -DCMAKE_CXX_FLAGS=\"-Wno-error -Wno-deprecated-declarations\"" --make-args="-Wno-error -Wno-deprecated-declarations" --no-jit --no-webassembly cd .. ``` ::: -:::caution pass +:::note pass -When this demo was tested on macOS, the build failed with the error message +In some test runs, the build failed with the error message ``` Source/WTF/wtf/text/ASCIILiteral.h:65:34: error: use of undeclared identifier 'NSString' @@ -502,9 +517,9 @@ namespace WTF { ::: -:::caution pass +:::note pass -When this demo was tested, the build failed with the error message +In some test runs, the build failed with the error message ``` Source/JavaScriptCore/runtime/JSCBytecodeCacheVersion.cpp:37:10: fatal error: 'wtf/spi/darwin/dyldSPI.h' file not found @@ -529,8 +544,8 @@ The `#include` should be changed to a relative directive: ```bash -cd WebKit-WebKit-7620.2.4.111.7 -env CFLAGS="-Wno-error=dangling-reference -Wno-dangling-reference" CXXFLAGS="-Wno-error=dangling-reference -Wno-dangling-reference" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error -DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF -DCMAKE_C_FLAGS=\"-Wno-error -Wno-dangling-reference\" -DCMAKE_CXX_FLAGS=\"-Wno-error -Wno-dangling-reference\"" --make-args="-j1 -Wno-error -Wno-error=dangling-reference" -j1 +cd WebKit +env CFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" CXXFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -Wno-error=volatile-register-var -DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF -DCMAKE_C_FLAGS=\"-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference\" -DCMAKE_CXX_FLAGS=\"-Wno-error=all -Wno-error=volatile-register-var \"" --make-args="-j1 -Wno-error=all -Wno-error=volatile-register-var " -j1 cd .. ``` @@ -540,9 +555,9 @@ When this was last tested on the Steam Deck, the build ran for 24 minutes! ::: -:::danger pass +:::note pass -When this demo was last tested on ARM64, there was a dangling pointer error: +In some test runs on AArch64 Linux, there was a dangling pointer error:
 WebKitBuild/JSCOnly/Release/WTF/Headers/wtf/SentinelLinkedList.h:61:55: error: storing the address of local variable ‘toBeRemoved’ in ‘{"*"}MEM[(struct BasicRawSentinelNode {"*"} const &)this_4(D) + 96].WTF::BasicRawSentinelNode<JSC::CallLinkInfoBase>::m_next’ [-Werror=dangling-pointer=]
@@ -573,11 +588,56 @@ The error can be suppressed with preprocessor directives around the definition:
 After patching the header, JSC must be built without WebAssembly or JIT support:
 
 ```bash
-cd WebKit-WebKit-7620.2.4.111.7
-env CFLAGS="-Wno-error=dangling-reference -Wno-dangling-reference" CXXFLAGS="-Wno-error=dangling-reference -Wno-dangling-reference" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error -DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF -DCMAKE_C_FLAGS=\"-Wno-error -Wno-dangling-reference\" -DCMAKE_CXX_FLAGS=-Wno-error -Wno-dangling-reference"  --make-args="-j1 -Wno-error -Wno-error=dangling-reference" -j1 --no-jit --no-webassembly
+cd WebKit
+env CFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" CXXFLAGS="-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference" Tools/Scripts/build-webkit --jsc-only --cmakeargs="-Wno-error=all -Wno-error=volatile-register-var -DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF -DCMAKE_C_FLAGS=\"-Wno-error=all -Wno-error=volatile-register-var -Wno-dangling-reference\" -DCMAKE_CXX_FLAGS=\"-Wno-error=all -Wno-error=volatile-register-var \""  --make-args="-j1 -Wno-error=all -Wno-error=volatile-register-var " -j1 --no-jit --no-webassembly
 cd ..
 ```
 
+:::
+
+:::caution pass
+
+In some test runs, there was a register error:
+
+```
+WebKit/Source/JavaScriptCore/heap/MarkedBlock.cpp: In member function ‘void JSC::MarkedBlock::dumpInfoAndCrashForInvalidHandle(WTF::AbstractLocker&, JSC::HeapCell*)’:
+WebKit/Source/JavaScriptCore/heap/MarkedBlock.cpp:589:32: error: address of explicit register variable ‘savedActualVM’ requested
+  589 |         VMInspector::forEachVM([&](VM& vm) {
+      |                                ^~~~~~~~~~~~~
+  590 |             if (blockVM == &vm) {
+      |             ~~~~~~~~~~~~~~~~~~~~~
+  591 |                 isValidBlockVM = true;
+      |                 ~~~~~~~~~~~~~~~~~~~~~~
+  592 |                 SAVE_TO_REG(savedActualVM, &vm);
+      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  593 |                 SAVE_TO_REG(savedBitfield, 8);
+      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  594 |                 LOG_INVALID_HANDLE_DETAILS("block VM %p is valid\n", &vm);
+      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  595 |                 return IterationStatus::Done;
+      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  596 |             }
+      |             ~                   
+  597 |             return IterationStatus::Continue;
+      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  598 |         });
+      |         ~
+```
+
+Until there is a proper upstream fix, the workaround is to explicitly no-op the
+`SAVE_TO_REG` macro in `MarkedBlock.cpp`:
+
+```diff title="WebKit/Source/JavaScriptCore/heap/MarkedBlock.cpp (remove red lines)"
+ #endif
+ 
+ #define SAVE_TO_REG(name, value) do { \
+-    name = WTF::opaque(value); \
+-    WTF::compilerFence(); \
+ } while (false)
+ 
+ NO_RETURN_DUE_TO_CRASH NEVER_INLINE void MarkedBlock::dumpInfoAndCrashForInvalidHandle(AbstractLocker&, HeapCell* heapCell)
+```
+
 :::
 
   
@@ -586,7 +646,7 @@ cd ..
 4) Create a symbolic link to the `Release` folder in the source tree:
 
 ```bash
-ln -s WebKit-WebKit-7620.2.4.111.7/WebKitBuild/JSCOnly/Release/ .
+ln -s WebKit/WebKitBuild/JSCOnly/Release .
 ```
 
 5) Download [`sheetjs-jsc.c`](pathname:///jsc/sheetjs-jsc.c):
@@ -604,6 +664,18 @@ curl -LO https://docs.sheetjs.com/jsc/sheetjs-jsc.c
 g++ -o sheetjs-jsc sheetjs-jsc.c -IRelease/JavaScriptCore/Headers -LRelease/lib -lbmalloc -licucore -lWTF -lJavaScriptCore -IRelease/JavaScriptCore/Headers -framework Foundation
 ```
 
+:::note pass
+
+In some test runs, there were `ld` warnings about `macOS` versions:
+
+```
+ld: warning: object file (Release/lib/libWTF.a[2](ASCIICType.cpp.o)) was built for newer 'macOS' version (14.5) than being linked (14.0)
+```
+
+These warnings can be ignored.
+
+:::
+
   
   
 
@@ -652,7 +724,7 @@ For macOS and iOS deployments, it is strongly encouraged to use the official
 
 The `linux-x64` test was run on [Ubuntu 22.04 using Swift 5.10.1](https://download.swift.org/swift-5.10.1-release/ubuntu2204/swift-5.10.1-RELEASE/swift-5.10.1-RELEASE-ubuntu22.04.tar.gz)
 
-The `linux-arm` test was run on [Debian 12 "bookworm" using Swift 5.10.1](https://download.swift.org/swift-5.10.1-release/debian12-aarch64/swift-5.10.1-RELEASE/swift-5.10.1-RELEASE-debian12-aarch64.tar.gz)
+The `linux-arm` test was run on [Debian 12 "bookworm" using Swift 6.1](https://download.swift.org/swift-6.1-release/debian12-aarch64/swift-6.1-RELEASE/swift-6.1-RELEASE-debian12-aarch64.tar.gz)
 
 
@@ -683,7 +755,7 @@ curl -LO https://docs.sheetjs.com/pres.numbers`} 5) Copy all generated headers to the current directory: ```bash -find ../WebKit-WebKit*/WebKitBuild/JSCOnly/Release/JavaScriptCore/Headers/ -name \*.h | xargs -I '%' cp '%' . +find ../WebKit/WebKitBuild/JSCOnly/Release/JavaScriptCore/Headers/ -name \*.h | xargs -I '%' cp '%' . ``` 6) Edit each header file and replace all instances of `=0;--a){var i=this.tryEntries[a],o=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var s=n.call(i,"catchLoc"),u=n.call(i,"finallyLoc");if(s&&u){if(this.prev=0;--r){var a=this.tryEntries[r];if(a.tryLoc<=this.prev&&n.call(a,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),S(n),p}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var a=r.arg;S(n)}return a}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,n){return this.delegate={iterator:E(e),resultName:t,nextLoc:n},"next"===this.method&&(this.arg=void 0),p}},e}function s(e){return s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},s(e)}function u(e,t,n,r,a,i,o){try{var s=e[i](o),u=s.value}catch(e){return void n(e)}s.done?t(u):Promise.resolve(u).then(r,a)}function c(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var i=e.apply(t,n);function o(e){u(i,r,a,o,s,"next",e)}function s(e){u(i,r,a,o,s,"throw",e)}o(void 0)}))}}function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function h(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,o=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return o=e.done,e},e:function(e){s=!0,i=e},f:function(){try{o||null==n.return||n.return()}finally{if(s)throw i}}}}function F(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}a.prototype["function"==typeof Symbol&&Symbol.asyncIterator||"@@asyncIterator"]=function(){return this},a.prototype.next=function(e){return this._invoke("next",e)},a.prototype.throw=function(e){return this._invoke("throw",e)},a.prototype.return=function(e){return this._invoke("return",e)};var D,M,L=function(e){return e&&e.Math==Math&&e},z=L("object"==("undefined"==typeof globalThis?"undefined":s(globalThis))&&globalThis)||L("object"==("undefined"==typeof window?"undefined":s(window))&&window)||L("object"==("undefined"==typeof self?"undefined":s(self))&&self)||L("object"==s(n)&&n)||function(){return this}()||Function("return this")(),P={},B=function(e){try{return!!e()}catch(e){return!0}},W=!B((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),U=!B((function(){var e=function(){}.bind();return"function"!=typeof e||e.hasOwnProperty("prototype")})),V=U,G=Function.prototype.call,j=V?G.bind(G):function(){return G.apply(G,arguments)},H={},q={}.propertyIsEnumerable,K=Object.getOwnPropertyDescriptor,X=K&&!q.call({1:2},1),Y=(H.f=X?function(e){var t=K(this,e);return!!t&&t.enumerable}:q,function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}),J=U,Z=Function.prototype,Q=Z.call,$=J&&Z.bind.bind(Q,Q),ee=J?$:function(e){return function(){return Q.apply(e,arguments)}},te=ee,ne=te({}.toString),re=te("".slice),ae=function(e){return re(ne(e),8,-1)},ie=B,oe=ae,se=Object,ue=ee("".split),ce=ie((function(){return!se("z").propertyIsEnumerable(0)}))?function(e){return"String"==oe(e)?ue(e,""):se(e)}:se,le=function(e){return null==e},he=le,pe=TypeError,fe=function(e){if(he(e))throw pe("Can't call method on "+e);return e},de=ce,ve=fe,me=function(e){return de(ve(e))},ge="object"==("undefined"==typeof document?"undefined":s(document))&&document.all,ye={all:ge,IS_HTMLDDA:void 0===ge&&void 0!==ge},be=ye.all,xe=ye.IS_HTMLDDA?function(e){return"function"==typeof e||e===be}:function(e){return"function"==typeof e},ke=xe,we=ye.all,Ie=ye.IS_HTMLDDA?function(e){return"object"==s(e)?null!==e:ke(e)||e===we}:function(e){return"object"==s(e)?null!==e:ke(e)},Ne=z,Se=xe,Te=function(e){return Se(e)?e:void 0},Ee=function(e,t){return arguments.length<2?Te(Ne[e]):Ne[e]&&Ne[e][t]},Ce=ee({}.isPrototypeOf),Ae="undefined"!=typeof navigator&&String(navigator.userAgent)||"",Re=z,_e=Ae,Oe=Re.process,Fe=Re.Deno,De=Oe&&Oe.versions||Fe&&Fe.version,Me=De&&De.v8;Me&&(M=(D=Me.split("."))[0]>0&&D[0]<4?1:+(D[0]+D[1])),!M&&_e&&(!(D=_e.match(/Edge\/(\d+)/))||D[1]>=74)&&(D=_e.match(/Chrome\/(\d+)/))&&(M=+D[1]);var Le=M,ze=Le,Pe=B,Be=!!Object.getOwnPropertySymbols&&!Pe((function(){var e=Symbol();return!String(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&ze&&ze<41})),We=Be&&!Symbol.sham&&"symbol"==s(Symbol.iterator),Ue=Ee,Ve=xe,Ge=Ce,je=Object,He=We?function(e){return"symbol"==s(e)}:function(e){var t=Ue("Symbol");return Ve(t)&&Ge(t.prototype,je(e))},qe=String,Ke=function(e){try{return qe(e)}catch(e){return"Object"}},Xe=xe,Ye=Ke,Je=TypeError,Ze=function(e){if(Xe(e))return e;throw Je(Ye(e)+" is not a function")},Qe=Ze,$e=le,et=function(e,t){var n=e[t];return $e(n)?void 0:Qe(n)},tt=j,nt=xe,rt=Ie,at=TypeError,it=function(e,t){var n,r;if("string"===t&&nt(n=e.toString)&&!rt(r=tt(n,e)))return r;if(nt(n=e.valueOf)&&!rt(r=tt(n,e)))return r;if("string"!==t&&nt(n=e.toString)&&!rt(r=tt(n,e)))return r;throw at("Can't convert object to primitive value")},ot={exports:{}},st=!1,ut=z,ct=Object.defineProperty,lt=function(e,t){try{ct(ut,e,{value:t,configurable:!0,writable:!0})}catch(n){ut[e]=t}return t},ht=lt,pt="__core-js_shared__",ft=z[pt]||ht(pt,{}),dt=(ot.exports,ft);(ot.exports=function(e,t){return dt[e]||(dt[e]=void 0!==t?t:{})})("versions",[]).push({version:"3.29.1",mode:"global",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.29.1/LICENSE",source:"https://github.com/zloirock/core-js"});var vt=ot.exports,mt=fe,gt=Object,yt=function(e){return gt(mt(e))},bt=yt,xt=ee({}.hasOwnProperty),kt=Object.hasOwn||function(e,t){return xt(bt(e),t)},wt=ee,It=0,Nt=Math.random(),St=wt(1..toString),Tt=function(e){return"Symbol("+(void 0===e?"":e)+")_"+St(++It+Nt,36)},Et=vt,Ct=kt,At=Tt,Rt=Be,_t=We,Ot=z.Symbol,Ft=Et("wks"),Dt=_t?Ot.for||Ot:Ot&&Ot.withoutSetter||At,Mt=function(e){return Ct(Ft,e)||(Ft[e]=Rt&&Ct(Ot,e)?Ot[e]:Dt("Symbol."+e)),Ft[e]},Lt=j,zt=Ie,Pt=He,Bt=et,Wt=it,Ut=TypeError,Vt=Mt("toPrimitive"),Gt=function(e,t){if(!zt(e)||Pt(e))return e;var n,r=Bt(e,Vt);if(r){if(void 0===t&&(t="default"),n=Lt(r,e,t),!zt(n)||Pt(n))return n;throw Ut("Can't convert object to primitive value")}return void 0===t&&(t="number"),Wt(e,t)},jt=Gt,Ht=He,qt=function(e){var t=jt(e,"string");return Ht(t)?t:t+""},Kt=Ie,Xt=z.document,Yt=Kt(Xt)&&Kt(Xt.createElement),Jt=function(e){return Yt?Xt.createElement(e):{}},Zt=Jt,Qt=!W&&!B((function(){return 7!=Object.defineProperty(Zt("div"),"a",{get:function(){return 7}}).a})),$t=W,en=j,tn=H,nn=Y,rn=me,an=qt,on=kt,sn=Qt,un=Object.getOwnPropertyDescriptor,cn=(P.f=$t?un:function(e,t){if(e=rn(e),t=an(t),sn)try{return un(e,t)}catch(e){}if(on(e,t))return nn(!en(tn.f,e,t),e[t])},{}),ln=W&&B((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),hn=Ie,pn=String,fn=TypeError,dn=function(e){if(hn(e))return e;throw fn(pn(e)+" is not an object")},vn=W,mn=Qt,gn=ln,yn=dn,bn=qt,xn=TypeError,kn=Object.defineProperty,wn=Object.getOwnPropertyDescriptor,In="enumerable",Nn="configurable",Sn="writable",Tn=(cn.f=vn?gn?function(e,t,n){if(yn(e),t=bn(t),yn(n),"function"==typeof e&&"prototype"===t&&"value"in n&&Sn in n&&!n.writable){var r=wn(e,t);r&&r.writable&&(e[t]=n.value,n={configurable:Nn in n?n.configurable:r.configurable,enumerable:In in n?n.enumerable:r.enumerable,writable:!1})}return kn(e,t,n)}:kn:function(e,t,n){if(yn(e),t=bn(t),yn(n),mn)try{return kn(e,t,n)}catch(e){}if("get"in n||"set"in n)throw xn("Accessors not supported");return"value"in n&&(e[t]=n.value),e},cn),En=Y,Cn=W?function(e,t,n){return Tn.f(e,t,En(1,n))}:function(e,t,n){return e[t]=n,e},An={exports:{}},Rn=W,_n=kt,On=Function.prototype,Fn=Rn&&Object.getOwnPropertyDescriptor,Dn=_n(On,"name"),Mn={EXISTS:Dn,PROPER:Dn&&"something"===function(){}.name,CONFIGURABLE:Dn&&(!Rn||Rn&&Fn(On,"name").configurable)},Ln=xe,zn=ft,Pn=ee(Function.toString);Ln(zn.inspectSource)||(zn.inspectSource=function(e){return Pn(e)});var Bn,Wn,Un,Vn=zn.inspectSource,Gn=xe,jn=z.WeakMap,Hn=Gn(jn)&&/native code/.test(String(jn)),qn=Tt,Kn=vt("keys"),Xn=function(e){return Kn[e]||(Kn[e]=qn(e))},Yn={},Jn=Hn,Zn=z,Qn=Ie,$n=Cn,er=kt,tr=ft,nr=Xn,rr=Yn,ar="Object already initialized",ir=Zn.TypeError,or=Zn.WeakMap;if(Jn||tr.state){var sr=tr.state||(tr.state=new or);sr.get=sr.get,sr.has=sr.has,sr.set=sr.set,Bn=function(e,t){if(sr.has(e))throw ir(ar);return t.facade=e,sr.set(e,t),t},Wn=function(e){return sr.get(e)||{}},Un=function(e){return sr.has(e)}}else{var ur=nr("state");rr[ur]=!0,Bn=function(e,t){if(er(e,ur))throw ir(ar);return t.facade=e,$n(e,ur,t),t},Wn=function(e){return er(e,ur)?e[ur]:{}},Un=function(e){return er(e,ur)}}var cr={set:Bn,get:Wn,has:Un,enforce:function(e){return Un(e)?Wn(e):Bn(e,{})},getterFor:function(e){return function(t){var n;if(!Qn(t)||(n=Wn(t)).type!==e)throw ir("Incompatible receiver, "+e+" required");return n}}},lr=(An.exports,ee),hr=B,pr=xe,fr=kt,dr=W,vr=Mn.CONFIGURABLE,mr=Vn,gr=cr.enforce,yr=cr.get,br=String,xr=Object.defineProperty,kr=lr("".slice),wr=lr("".replace),Ir=lr([].join),Nr=dr&&!hr((function(){return 8!==xr((function(){}),"length",{value:8}).length})),Sr=String(String).split("String"),Tr=An.exports=function(e,t,n){"Symbol("===kr(br(t),0,7)&&(t="["+wr(br(t),/^Symbol\(([^)]*)\)/,"$1")+"]"),n&&n.getter&&(t="get "+t),n&&n.setter&&(t="set "+t),(!fr(e,"name")||vr&&e.name!==t)&&(dr?xr(e,"name",{value:t,configurable:!0}):e.name=t),Nr&&n&&fr(n,"arity")&&e.length!==n.arity&&xr(e,"length",{value:n.arity});try{n&&fr(n,"constructor")&&n.constructor?dr&&xr(e,"prototype",{writable:!1}):e.prototype&&(e.prototype=void 0)}catch(e){}var r=gr(e);return fr(r,"source")||(r.source=Ir(Sr,"string"==typeof t?t:"")),e};Function.prototype.toString=Tr((function(){return pr(this)&&yr(this).source||mr(this)}),"toString");var Er=An.exports,Cr=xe,Ar=cn,Rr=Er,_r=lt,Or=function(e,t,n,r){r||(r={});var a=r.enumerable,i=void 0!==r.name?r.name:t;if(Cr(n)&&Rr(n,i,r),r.global)a?e[t]=n:_r(t,n);else{try{r.unsafe?e[t]&&(a=!0):delete e[t]}catch(e){}a?e[t]=n:Ar.f(e,t,{value:n,enumerable:!1,configurable:!r.nonConfigurable,writable:!r.nonWritable})}return e},Fr={},Dr=Math.ceil,Mr=Math.floor,Lr=Math.trunc||function(e){var t=+e;return(t>0?Mr:Dr)(t)},zr=Lr,Pr=function(e){var t=+e;return t!=t||0===t?0:zr(t)},Br=Pr,Wr=Math.max,Ur=Math.min,Vr=function(e,t){var n=Br(e);return n<0?Wr(n+t,0):Ur(n,t)},Gr=Pr,jr=Math.min,Hr=function(e){return e>0?jr(Gr(e),9007199254740991):0},qr=Hr,Kr=function(e){return qr(e.length)},Xr=me,Yr=Vr,Jr=Kr,Zr=function(e){return function(t,n,r){var a,i=Xr(t),o=Jr(i),s=Yr(r,o);if(e&&n!=n){for(;o>s;)if((a=i[s++])!=a)return!0}else for(;o>s;s++)if((e||s in i)&&i[s]===n)return e||s||0;return!e&&-1}},Qr={includes:Zr(!0),indexOf:Zr(!1)},$r=kt,ea=me,ta=Qr.indexOf,na=Yn,ra=ee([].push),aa=function(e,t){var n,r=ea(e),a=0,i=[];for(n in r)!$r(na,n)&&$r(r,n)&&ra(i,n);for(;t.length>a;)$r(r,n=t[a++])&&(~ta(i,n)||ra(i,n));return i},ia=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],oa=aa,sa=ia.concat("length","prototype"),ua=(Fr.f=Object.getOwnPropertyNames||function(e){return oa(e,sa)},{}),ca=(ua.f=Object.getOwnPropertySymbols,Ee),la=Fr,ha=ua,pa=dn,fa=ee([].concat),da=ca("Reflect","ownKeys")||function(e){var t=la.f(pa(e)),n=ha.f;return n?fa(t,n(e)):t},va=kt,ma=da,ga=P,ya=cn,ba=function(e,t,n){for(var r=ma(t),a=ya.f,i=ga.f,o=0;oo;)ni.f(e,n=a[o++],r[n]);return e},Ee("document","documentElement")),si=dn,ui=Ja,ci=ia,li=Yn,hi=oi,pi=Jt,fi=Xn("IE_PROTO"),di=function(){},vi=function(e){return"