LynxJS win11-x64

This commit is contained in:
SheetJS 2026-06-14 19:29:38 -04:00
parent 042edb00b0
commit 5072c31d40
23 changed files with 318 additions and 176 deletions

@ -72,7 +72,7 @@
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/desktop/wails#complete-example"><Data ss:Type="String">Wails</Data></Cell>

@ -34,7 +34,7 @@
</Style>
</Styles>
<Worksheet ss:Name="Frameworks">
<Table ss:ExpandedColumnCount="8" ss:ExpandedRowCount="18" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
<Table ss:ExpandedColumnCount="9" ss:ExpandedRowCount="18" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
<Column ss:Index="3" ss:Width="24"/>
<Column ss:Width="31"/>
<Column ss:Width="24"/>
@ -44,9 +44,9 @@
<Row>
<Cell ss:StyleID="s17"><Data ss:Type="String"></Data></Cell>
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Real Device</Data></Cell>
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">MacOS Sim</Data></Cell>
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Windows Sim</Data></Cell>
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">Linux Sim</Data></Cell>
<Cell ss:MergeAcross="1" ss:StyleID="s19"><Data ss:Type="String">MacOS</Data></Cell>
<Cell ss:StyleID="s19"><Data ss:Type="String">Windows</Data></Cell>
<Cell ss:StyleID="s19"><Data ss:Type="String">Linux</Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s17"><Data ss:Type="String">Platform</Data></Cell>
@ -54,9 +54,7 @@
<Cell ss:StyleID="s17"><Data ss:Type="String">Android</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">iOS</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">Android</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">iOS</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">Android</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">iOS</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">Android</Data></Cell>
</Row>
<Row>
@ -65,9 +63,7 @@
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
</Row>
<Row>
@ -76,9 +72,7 @@
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
</Row>
<Row>
@ -87,9 +81,7 @@
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
</Row>
<Row>
@ -98,9 +90,7 @@
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"> </Data></Cell>
</Row>
<Row>
@ -109,9 +99,7 @@
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"> </Data></Cell>
</Row>
<Row>
@ -120,9 +108,7 @@
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"> </Data></Cell>
</Row>
<Row>
@ -131,9 +117,7 @@
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✘</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"> </Data></Cell>
</Row>
</Table>

@ -121,7 +121,7 @@ This demo was last tested in the following deployments:
| Architecture | BunJS | Date |
|:-------------|:---------|:-----------|
| `darwin-x64` | `1.3.6` | 2026-01-20 |
| `darwin-x64` | `1.3.14` | 2026-06-13 |
| `darwin-arm` | `1.3.6` | 2026-01-19 |
| `win11-x64` | `1.3.6` | 2026-01-28 |
| `win11-arm` | `1.3.10` | 2026-03-07 |

@ -56,15 +56,15 @@ This demo was tested in the following environments:
| OS | Device | NS | Date |
|:-----------|:--------------------|:---------|:-----------|
| Android 30 | NVIDIA Shield | `8.9.2` | 2025-05-06 |
| iOS 15.1 | iPad Pro | `8.9.2` | 2025-05-06 |
| Android 33 | AYN Thor Max | `9.0.3` | 2026-06-13 |
| iOS 26.5 | iPhone 17 Pro Max | `9.0.3` | 2026-06-13 |
**Simulators**
| OS | Device | NS | Dev Platform | Date |
|:-----------|:--------------------|:---------|:-------------|:-----------|
| Android 35 | Pixel 9 Pro XL | `8.9.2` | `darwin-x64` | 2025-05-06 |
| iOS 18.4 | iPhone 16 Pro Max | `8.9.2` | `darwin-x64` | 2025-05-06 |
| Android 36 | Pixel 9 Pro XL | `9.0.3` | `darwin-arm` | 2026-06-13 |
| iOS 18.4 | iPhone 16 Pro Max | `9.0.3` | `darwin-arm` | 2026-06-13 |
| Android 35 | Pixel 9 | `8.9.2` | `win11-x64` | 2025-06-08 |
| Android 36 | Pixel 9 | `8.9.2` | `linux-x64` | 2025-07-06 |
@ -332,7 +332,7 @@ In the last macOS test, the following output was displayed:
<span {...g}></span> Javac is installed and is configured properly.
<span {...g}></span> The Java Development Kit (JDK) is installed and is configured properly.
<span {...g}></span> Getting NativeScript components versions information...
<span {...g}></span> Component nativescript has 8.9.2 version and is up to date.
<span {...g}></span> Component nativescript has 9.0.6 version and is up to date.
</pre>
</details>
@ -361,7 +361,7 @@ In the last macOS test, the following output was displayed:
<span {...g}></span> Python installed and configured correctly.
<span {...g}></span> Xcode version 16.3.0 satisfies minimum required version 10.
<span {...g}></span> Getting NativeScript components versions information...
<span {...g}></span> Component nativescript has 8.9.2 version and is up to date.
<span {...g}></span> Component nativescript has 9.0.6 version and is up to date.
</pre>
</details>
@ -428,30 +428,29 @@ The goal of this section is to display the SheetJS library version number.
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
7) Edit `src/app/item/items.component.ts` so that the component imports the
7) Edit `src/app/people/person.component.ts` so that the component imports the
SheetJS version string and adds it to a `version` variable in the component:
```ts title="src/app/item/items.component.ts (add highlighted lines)"
```ts title="src/app/people/person.component.ts (add highlighted lines)"
// highlight-next-line
import { version } from 'xlsx';
import { Component, NO_ERRORS_SCHEMA, inject } from '@angular/core'
import { ChangeDetectionStrategy, Component, NO_ERRORS_SCHEMA, inject } from '@angular/core'
// ...
export class ItemsComponent {
export class PersonComponent {
// highlight-next-line
version = `SheetJS - ${version}`;
itemService = inject(ItemService)
page = inject(Page)
// ...
personService = inject(PersonService);
}
```
8) Edit the template `src/app/item/items.component.html` to reference `version`
in the title of the action bar:
8) Edit the template `src/app/people/person.component.html` to reference
`version` in the title of the action bar:
```xml title="src/app/item/items.component.html (edit highlighted line)"
```xml title="src/app/people/person.component.html (edit highlighted line)"
<!-- highlight-next-line -->
<ActionBar [title]="version"></ActionBar>
<ActionBar [title]="version" iosLargeTitle="true"> </ActionBar>
<GridLayout>
<!-- ... -->
@ -471,7 +470,7 @@ The title bar should show the version.
10) Add the Import and Export buttons to the template:
```xml title="src/app/item/items.component.html (add highlighted lines)"
```xml title="src/app/people/person.component.html (add highlighted lines)"
<ActionBar [title]="version"></ActionBar>
<!-- highlight-start -->
@ -481,7 +480,7 @@ The title bar should show the version.
<Button text="Export File" (tap)="export()" style="padding: 10px"></Button>
</StackLayout>
<!-- highlight-end -->
<ListView [items]="itemService.items()">
<ListView [items]="personService.items()">
<!-- ... -->
</ListView>
<!-- highlight-next-line -->
@ -490,16 +489,15 @@ The title bar should show the version.
11) Add the `import` and `export` methods in the component script:
```ts title="src/app/item/items.component.ts (add highlighted lines)"
```ts title="src/app/people/person.component.ts (add highlighted lines)"
// highlight-start
import { version, utils, read, write } from 'xlsx';
import { Dialogs, getFileAccess } from '@nativescript/core';
import { Folder, knownFolders, path } from '@nativescript/core/file-system';
// highlight-end
import { Component, NO_ERRORS_SCHEMA, inject } from '@angular/core'
import { ChangeDetectionStrategy, Component, NO_ERRORS_SCHEMA, inject } from '@angular/core'
import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular'
import { Page } from '@nativescript/core'
import { ItemService } from './item.service'
import { PersonService } from './person.service'
// highlight-start
function get_url_for_filename(filename: string): string {
@ -510,10 +508,9 @@ function get_url_for_filename(filename: string): string {
// ...
export class ItemsComponent {
export class PersonComponent {
version = `SheetJS - ${version}`;
itemService = inject(ItemService)
page = inject(Page)
personService = inject(PersonService);
// highlight-start
/* Import button */
@ -524,8 +521,7 @@ export class ItemsComponent {
async export() {
}
// highlight-end
// ...
}
```
12) End the script and relaunch the app in the Android simulator:
@ -540,7 +536,7 @@ Two buttons should appear just below the header:
13) Implement import and export by adding the highlighted lines:
```ts title="src/app/item/items.component.ts (add highlighted lines)"
```ts title="src/app/people/person.component.ts (add highlighted lines)"
/* Import button */
async import() {
// highlight-start
@ -560,7 +556,7 @@ Two buttons should appear just below the header:
const ws = wb.Sheets[wsname];
/* update table */
this.itemService.items.set(utils.sheet_to_json(ws));
this.personService.items.set(utils.sheet_to_json(ws));
} catch(e) { await Dialogs.alert(e.message); }
// highlight-end
}
@ -573,7 +569,7 @@ Two buttons should appear just below the header:
try {
/* create worksheet from data */
const ws = utils.json_to_sheet(this.itemService.items());
const ws = utils.json_to_sheet(this.personService.items());
/* create workbook from worksheet */
const wb = utils.book_new();
@ -638,14 +634,14 @@ After the header row, insert a row and make the following assignments:
- Set cell `A2` to `0`
- Set cell `B2` to `SheetJS` (type `'SheetJS` in the formula bar)
- Set cell `C2` to `Library` (type `'Library` in the formula bar)
- Set cell `C2` to `American` (type `'American` in the formula bar)
After making the changes, the worksheet should look like the following:
```text
id | name | role
id | name | nationality
# highlight-next-line
0 | SheetJS | Library
0 | SheetJS | American
...
```
@ -711,9 +707,9 @@ After the header row, insert a row and make the following assignments:
After making the changes, the worksheet should look like the following:
```text
id | name | role
id | name | nationality
# highlight-next-line
0 | SheetJS | Library
0 | SheetJS | American
...
```
@ -726,20 +722,20 @@ The first item in the list will change:
### Fetching Files
25) Replace `item.service.ts` with the following:
25) Replace `person.service.ts` with the following:
```ts title="src/app/item/item.service.ts"
import { read, utils } from 'xlsx';
import { Injectable, signal, effect } from '@angular/core'
```ts title="src/app/people/person.service.ts (replace contents)"
import { read, utils } from 'xlsx';
import { Injectable, signal, effect } from '@angular/core';
import { knownFolders, path, getFileAccess } from '@nativescript/core';
import { getFile } from '@nativescript/core/http';
import { Item } from './item'
import { Person } from './person';
interface IPresident { Name: string; Index: number };
@Injectable({ providedIn: 'root' })
export class ItemService {
items = signal<Item[]>([]);
@Injectable({providedIn: 'root'})
export class PersonService {
items = signal<Person[]>([]);
constructor() { effect(() => { (async() => {
/* fetch https://docs.sheetjs.com/pres.xlsx */
const temp: string = path.join(knownFolders.temp().path, "pres.xlsx");
@ -749,11 +745,11 @@ export class ItemService {
/* translate the first worksheet to the required Item type */
const data = utils.sheet_to_json<IPresident>(wb.Sheets[wb.SheetNames[0]]);
/* update state */
this.items.set(data.map((pres, id) => ({id, name: pres.Name, role: ""+pres.Index} as Item)));
this.items.set(data.map((pres, id) => ({id, name: pres.Name, nationality: ""+pres.Index} as Person)));
})(); }); }
getItem(id: number): Item {
return this.items().find((item) => item.id === id)
getPerson(id: number): Person {
return this.items().find((person) => person.id === id);
}
}
```
@ -795,23 +791,23 @@ at `App_Resources/Android/src/main/AndroidManifest.xml`:
npm i --save @nativescript-community/perms
```
31) Add the highlighted lines to `items.component.ts`:
31) Add the highlighted lines to `person.component.ts`:
- Import `File` from NativeScript core and `request` from the new dependency:
```ts title="items.component.ts (add highlighted lines)"
import { Dialogs, getFileAccess, Utils } from '@nativescript/core';
```ts title="person.component.ts (add highlighted lines)"
import { Dialogs, getFileAccess } from '@nativescript/core';
// highlight-start
import { request } from '@nativescript-community/perms';
import { Folder, knownFolders, path, File } from '@nativescript/core/file-system';
// highlight-end
import { Component, OnInit } from '@angular/core'
import { ChangeDetectionStrategy, Component, NO_ERRORS_SCHEMA, inject } from '@angular/core'
// ...
```
- Add a new write operation to the `export` method:
```ts title="items.component.ts (add highlighted lines)"
```ts title="person.component.ts (add highlighted lines)"
/* attempt to save Uint8Array to file */
await getFileAccess().writeBufferAsync(url, global.isAndroid ? (Array.from(u8) as any) : u8);
await Dialogs.alert(`Wrote to SheetJSNS.xls at ${url}`);
@ -822,7 +818,7 @@ import { Component, OnInit } from '@angular/core'
const res = await request('storage');
/* write to Downloads folder */
const dl = android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
File.fromPath(dl + "/SheetJSNS.xls").writeSync(Array.from(u8));
await File.fromPath(dl + "/SheetJSNS.xls").write(Array.from(u8));
}
/* highlight-end */
} catch(e) { await Dialogs.alert(e.message); }
@ -858,10 +854,10 @@ file named `SheetJSNS.xls`.
35) Enable developer code signing certificates:
Open `platforms/ios/SheetJSNS.xcodeproj/project.xcworkspace` in Xcode. Select
the "Project Navigator" and select `SheetJSNS`. In the main view, select the
`SheetJSNS` target. Click "Signing & Capabilities". Under "Signing", select a
team in the dropdown menu.
Open `platforms/ios/SheetJSNS.xcodeproj` in Xcode. Select "Project Navigator" in
the left sidebar and click `SheetJSNS`. In the main view, select the `SheetJSNS`
target. Click "Signing & Capabilities". Under "Signing", select a team in the
dropdown menu.
:::caution pass
@ -893,6 +889,17 @@ npx -y -p nativescript ns platform clean ios
npx -y -p nativescript ns run ios
```
:::caution pass
In some test runs, iOS showed a "Developer Mode Required" popup:
> "SheetJSNS" requires Developer Mode to run. Until Developer Mode has been
> enabled this app will not be available for use.
Under "Settings" > "Privacy & Security", enable "Developer Mode" and restart.
:::
:::info pass
If this is the first time testing an app on a device, the certificate must be

@ -59,7 +59,7 @@ This demo was tested in the following environments:
|:-----------|:------------------|:---------|:---------|:-------------|:-----------|
| Android 36 | Pixel Tablet | `3.11.1` | `3.41.4` | `darwin-arm` | 2026-03-11 |
| iOS 18.6 | iPhone 16 Pro Max | `3.11.1` | `3.41.4` | `darwin-arm` | 2026-03-11 |
| Android 36 | Pixel 9 Pro XL | `3.7.2` | `3.29.3` | `win11-x64` | 2054-04-28 |
| Android 36 | Pixel 9 Pro XL | `3.7.2` | `3.29.3` | `win11-x64` | 2025-04-28 |
:::

@ -212,6 +212,7 @@ This demo was tested in the following environments:
|:-----------|:--------------------|:---------|:-------------|:-------------|:-----------|
| Android 35 | Pixel 3a | `0.8.6` | `3.2.0-rc.1` | `darwin-arm` | 2025-03-26 |
| iOS 18.3 | iPhone 16 Pro | `0.8.6` | `3.2.0-rc.1` | `darwin-arm` | 2025-03-26 |
| Android 37 | Pixel 10 Pro XL | `0.14.5` | `3.8.1` | `win11-x64` | 2026-06-14 |
:::
@ -235,7 +236,7 @@ Make sure you can run a basic test app on your simulator before continuing!
1) Create project:
```bash
npm create rspeedy@0.8.6 -- -d SheetJSLynxFetch -t react-ts --tools biome
npm create rspeedy@0.14.5 -- -d SheetJSLynxFetch -t react-ts --tools biome
```
2) Install shared dependencies:
@ -314,7 +315,7 @@ emulator -avd Medium_Phone_API_35
7) Download the LynxExplorer[^4] APK.
The latest test used [`LynxExplorer-noasan-release.apk` for version `3.2.0-rc.1`](https://github.com/lynx-family/lynx/releases/download/3.2.0-rc.1/LynxExplorer-noasan-release.apk).
The latest test used [`LynxExplorer-noasan-release.apk` for version `3.8.1`](https://github.com/lynx-family/lynx/releases/download/3.8.1/LynxExplorer-noasan-release.apk).
8) Drag and drop the APK into the Android emulator window.

@ -119,14 +119,14 @@ input.click();
This demo was tested in the following environments:
| OS and Version | Architecture | NW.js | Date | Notes |
|:---------------|:-------------|:----------|:-----------|:---------------------|
| macOS 15.7.4 | `darwin-x64` | `0.112.0` | 2026-06-13 | |
| macOS 14.5 | `darwin-arm` | `0.94.0` | 2025-03-30 | |
| Windows 11 | `win11-x64` | `0.111.3` | 2026-05-22 | |
| Windows 11 | `win11-arm` | `0.94.0` | 2025-02-23 | |
| Linux (Ubuntu) | `linux-x64` | `0.101.2` | 2025-07-06 | |
| Linux (Debian) | `linux-arm` | `0.60.0` | 2025-02-16 | Unofficial build[^1] |
| OS and Version | Architecture | NW.js | Date |
|:---------------|:-------------|:----------|:-----------|
| macOS 15.7.4 | `darwin-x64` | `0.112.0` | 2026-06-13 |
| macOS 14.5 | `darwin-arm` | `0.94.0` | 2025-03-30 |
| Windows 11 | `win11-x64` | `0.111.3` | 2026-05-22 |
| Windows 11 | `win11-arm` | `0.94.0` | 2025-02-23 |
| Linux (Ubuntu) | `linux-x64` | `0.101.2` | 2025-07-06 |
| Linux (Debian) | `linux-arm` | `0.112.0` | 2026-06-14 |
:::
@ -203,7 +203,7 @@ npm i
4) To verify the app works, run in the test environment:
```bash
npx nw .
npx -y nw .
```
On launch, the app will fetch and parse https://docs.sheetjs.com/pres.numbers .
@ -214,28 +214,10 @@ table will refresh with the contents of the selected file.
Click "Export Data!" and save the generated file to `SheetJSNWDemo.xlsx`. This
file can be opened in Excel or another spreadsheet editor.
<details>
<summary><b>Linux ARM64 support</b> (click to show)</summary>
NW.js does not officially support `linux-arm`. The official recommendation is to
use a third-party pre-built version.
```bash
curl -LO https://github.com/LeonardLaszlo/nw.js-armv7-binaries/releases/download/nw60-arm64_2022-01-08/nw60-arm64_2022-01-08.tar.gz
tar -xzf nw60-arm64_2022-01-08.tar.gz
cp usr/docker/dist/nwjs-chromium-ffmpeg-branding/nwjs-v0.60.1-linux-arm64.tar.gz
tar -xzf nwjs-v0.60.1-linux-arm64.tar.gz
./nwjs-v0.60.1-linux-arm64/nw .
```
Unfortunately `nw-builder` will not be able to build a standalone program.
</details>
5) To build a standalone app, run the builder:
```bash
npx -p nw-builder@4.17.10 nwbuild --mode=build --version=0.111.3 --glob=false --outDir=../out ./
npx -y -p nw-builder@4.17.10 nwbuild --mode=build --version=0.111.3 --glob=false --outDir=../out ./
```
This will generate the standalone app in the `..\out\` folder.
@ -249,5 +231,4 @@ This will generate the standalone app in the `..\out\` folder.
| `win11-x64` | `..\out\sheetjs-nwjs.exe` |
| `win11-arm` | `..\out\sheetjs-nwjs.exe` |
| `linux-x64` | `../out/sheetjs-nwjs` |
[^1]: The [`nw60-arm64_2022-01-08` release](https://github.com/LeonardLaszlo/nw.js-armv7-binaries/releases/tag/nw60-arm64_2022-01-08) included an ARM64 version of `nw`.
| `linux-arm` | `../out/sheetjs-nwjs` |

@ -58,7 +58,7 @@ This demo was tested in the following environments:
|:---------------|:-------------|:----------|:----------|:-----------|
| macOS 15.7.4 | `darwin-x64` | `v1.6.0` | VueJS | 2026-06-13 |
| macOS 14.5 | `darwin-arm` | `v1.6.0` | Kaioken | 2025-03-30 |
| Windows 11 | `win11-x64` | `v1.6.0` | VueJS | 2025-05-27 |
| Windows 11 | `win11-x64` | `v1.6.0` | VueJS | 2026-06-14 |
| Windows 11 | `win11-arm` | `v1.6.0` | VueJS | 2025-02-23 |
| Linux (HoloOS) | `linux-x64` | `v1.6.0` | VueJS | 2025-07-06 |
| Linux (Debian) | `linux-arm` | `v1.6.0` | VueJS | 2025-05-27 |

@ -34,7 +34,7 @@ This demo was tested in the following deployments:
| `darwin-arm` | `3.0.0` | `23.11.0` | 2026-03-13 |
| `win11-x64` | `3.0.0` | `22.22.2` | 2026-05-08 |
| `linux-x64` | `3.0.0` | `25.8.0` | 2026-03-08 |
| `linux-arm` | `2.4.4` | `23.8.0` | 2025-02-15 |
| `linux-arm` | `3.0.0` | `23.8.0` | 2026-06-14 |
:::
@ -113,7 +113,7 @@ The `-n` flag controls the target NodeJS version. For this demo, the following
command uses NodeJS `23.8.0`:
```bash
npx -y boxednode@2.4.4 -s xlsx-cli.js -t xlsx-cli -n 23.8.0
npx -y boxednode@3.0.0 -s xlsx-cli.js -t xlsx-cli -n 23.8.0
```
:::

@ -26,8 +26,8 @@ Each browser demo was tested in the following environments:
| Safari 26.2 | `darwin-arm` | 2026-05-16 | `text/rtf` not supported |
| Chromium 147 | `win11-arm` | 2026-05-26 | |
| Edge 148 | `win11-arm` | 2026-05-26 | |
| Chromium 135 | `linux-arm` | 2025-04-23 | |
| Konqueror 22 | `linux-arm` | 2025-04-23 | `text/rtf`, files not supported |
| Chromium 147 | `linux-arm` | 2026-06-14 | `text/rtf` did not work |
| Konqueror 25 | `linux-arm` | 2026-06-14 | `text/rtf` not supported |
Windows and macOS tests were run against Excel, while Linux tests were run
against Gnumeric.
@ -106,7 +106,14 @@ and copy spreadsheets into the clipboard.
:::
The event `clipboardData.files` property, if it is set, is a list of files.
The event `clipboardData.files` property, if it is set, is a list of
[`File`](/docs/demos/local/file#blob-and-file) objects.
The `arrayBuffer` method of the `File` object returns a `Promise` that resolves
to an `ArrayBuffer` with binary data. The `ArrayBuffer` can be parsed by the
SheetJS [`read`](/docs/api/parse-options) method.
The following example parses copied files and displays all sheet names:
```jsx live
function ClipboardReadFiles() {
@ -210,6 +217,14 @@ function ClipboardWrite() {
}
```
:::caution pass
When the clipboard contains a full HTML document, Gnumeric prepends the title to
the table. The first row of the table will be "SheetJS Table Export". This does
not affect Excel or other popular spreadsheet software.
:::
## Electron
Electron Clipboard API supports HTML and RTF clipboards.

@ -39,7 +39,7 @@ This demo was tested in the following deployments:
| OS and Version | Architecture | Excel | Date |
|:---------------|:-------------|:-----------|:-----------|
| macOS 15.3 | `darwin-x64` | 16.95.4 | 2025-04-17 |
| macOS 15.7.4 | `darwin-x64` | 16.109 | 2026-06-13 |
| macOS 14.5 | `darwin-arm` | 16.106.3 | 2026-05-05 |
| Windows 11 | `win11-x64` | 365 (2604) | 2026-06-05 |
| Windows 11 | `win11-arm` | 365 (2503) | 2025-04-24 |
@ -287,6 +287,16 @@ var XLSX = require("xlsx");
export function version() {
return [[XLSX.version]];
}
/**
* Download file and write data
* @customfunction
* @param {string} url URL to fetch and parse
* @returns {any[][]} Worksheet data
*/
export async function extern(url) {
return [[""]];
}
```
12) Close the terminal window and the Excel window. Do not save the Excel file.
@ -372,7 +382,7 @@ npm start
15) Add the following code snippet to `src\functions\functions.js` and save:
```js title="src\functions\functions.js (add to end)"
```js title="src\functions\functions.js (replace existing function)"
/**
* Download file and write data
* @customfunction

@ -53,7 +53,7 @@ This demo was tested in the following deployments:
| Architecture | Version | Date |
|:-------------|:------------------|:-----------|
| `darwin-x64` | `18.5` (StataNow) | 2025-06-20 |
| `darwin-x64` | `19.5` (StataNow) | 2026-06-13 |
| `darwin-arm` | `19.5` (StataNow) | 2026-03-13 |
| `win11-x64` | `19.5` (StataNow) | 2026-05-14 |
| `win11-arm` | `18.5` (StataNow) | 2025-02-23 |
@ -257,9 +257,9 @@ curl -LO https://www.stata.com/plugins/stplugin.c
curl -LO https://www.stata.com/plugins/stplugin.h
```
:::danger pass
:::caution pass
**When this demo was last tested, `stplugin.h` was removed from the website!**
**In some demo test runs, `stplugin.h` was not available from the website!**
If the official links do not work, the following files should be used:

@ -38,8 +38,8 @@ This demo was tested by SheetJS users in the following deployments:
| Architecture | Version | Date |
|:-------------|:---------|:-----------|
| `darwin-x64` | `2025.1` | 2025-06-20 |
| `win11-x64` | `2025.1` | 2025-07-17 |
| `darwin-x64` | `2025.1` | 2026-06-13 |
| `win11-x64` | `2025.1` | 2026-06-13 |
:::

@ -27,7 +27,7 @@ This demo was tested by SheetJS users in the following deployments:
| Architecture | Ghidra | Date |
|:-------------|:----------|:-----------|
| `darwin-x64` | `11.13.1` | 2025-04-17 |
| `darwin-x64` | `12.1.2` | 2026-06-13 |
| `darwin-arm` | `11.13.1` | 2025-10-19 |
:::
@ -264,16 +264,18 @@ When this demo was last tested, Java and Ghidra were installed using Homebrew:
```bash
brew install zulu@21
brew install --cask ghidra
brew install ghidra
```
</details>
1) Add the base Ghidra folder to the PATH variable. The following shell command
adds to the path for the current `zsh` or `bash` session:
1) Add the base Ghidra folder to the PATH variable. The following shell commands
adds common paths for the current `zsh` or `bash` session:
```bash
export PATH="$PATH":$(dirname $(realpath `which ghidraRun`))
export PATH="$PATH":$(realpath $(dirname $(realpath `which ghidraRun`))/../libexec/Ghidra)
export PATH="$PATH":$(realpath $(dirname $(realpath `which ghidraRun`))/../libexec/Extensions/Ghidra)
```
2) Install `ghidra.js` globally:
@ -323,7 +325,7 @@ binaries. `lipo` creates a new binary with support for one architecture.
6) Analyze the program:
```bash
$(dirname $(realpath `which ghidraRun`))/support/analyzeHeadless /tmp/sheetjs-ghidra Numbers -import TSTables.macho
$(dirname $(realpath `which ghidraRun`))/../libexec/support/analyzeHeadless /tmp/sheetjs-ghidra Numbers -import TSTables.macho
```
<details>
@ -411,7 +413,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
9) Run the script:
```bash
$(dirname $(realpath `which ghidraRun`))/support/analyzeHeadless /tmp/sheetjs-ghidra Numbers -process TSTables.macho -noanalysis -scriptPath `pwd` -postScript sheetjs-ghidra.js
$(dirname $(realpath `which ghidraRun`))/../libexec/support/analyzeHeadless /tmp/sheetjs-ghidra Numbers -process TSTables.macho -noanalysis -scriptPath `pwd` -postScript sheetjs-ghidra.js
```
10) Open the generated `SheetJSGhidraTSTCell.xlsx` spreadsheet with Numbers:

@ -132,7 +132,7 @@ This demo was tested in the following deployments:
| `darwin-arm` | `2.7.0` | 2026-03-07 |
| `win11-x64` | `2.7.0` | 2026-05-26 |
| `win11-arm` | `2.7.0` | 2025-02-23 |
| `linux-x64` | `2.7.0` | 2025-04-21 |
| `linux-x64` | `2.7.0` | 2026-06-14 |
| `linux-arm` | `2.7.0` | 2026-03-07 |
:::
@ -408,7 +408,7 @@ This demo was tested in the following deployments:
|:-------------|:--------|:---------|:-----------|
| `darwin-x64` | `2.7.0` | `8.4.11` | 2026-01-21 |
| `darwin-arm` | `2.7.0` | `8.4.8` | 2026-01-23 |
| `linux-x64` | `2.7.0` | `8.3.6` | 2025-04-21 |
| `linux-x64` | `2.7.0` | `8.4.11` | 2026-06-14 |
| `linux-arm` | `2.7.0` | `8.4.16` | 2026-03-07 |
:::
@ -552,7 +552,7 @@ This demo was tested in the following deployments:
| `darwin-arm` | `2.7.0` | `3.12.3` | 2026-01-23 |
| `win11-x64` | `2.7.0` | `3.11.9` | 2026-02-02 |
| `win11-arm` | `2.7.0` | `3.11.9` | 2026-02-02 |
| `linux-x64` | `2.7.0` | `3.12.3` | 2025-04-21 |
| `linux-x64` | `2.7.0` | `3.13.9` | 2026-06-14 |
| `linux-arm` | `2.7.0` | `3.13.5` | 2026-03-07 |
:::
@ -910,7 +910,7 @@ This demo was tested in the following deployments:
| `darwin-arm` | `2.7.0` | `0.15.2` | 2026-01-20 |
| `win11-x64` | `2.7.0` | `0.15.2` | 2026-05-26 |
| `win11-arm` | `2.7.0` | `0.13.0` | 2025-02-23 |
| `linux-x64` | `2.7.0` | `0.14.0` | 2025-04-21 |
| `linux-x64` | `2.7.0` | `0.15.2` | 2026-06-14 |
| `linux-arm` | `2.7.0` | `0.15.2` | 2026-03-07 |
On Windows, due to incompatibilities between WSL and PowerShell, some commands
@ -952,7 +952,7 @@ tar -xzf zig-*.tar.xz
For X64 Linux:
```bash
curl -LO https://ziglang.org/download/0.14.0/zig-linux-x86_64-0.14.0.tar.xz
curl -LO https://ziglang.org/download/0.15.2/zig-x86_64-linux-0.15.2.tar.xz
xz -d zig-linux-*.tar.xz
tar -xf zig-linux-*.tar
```
@ -1141,7 +1141,7 @@ This demo was tested in the following deployments:
| `darwin-x64` | `2.2.0` | 2026-01-21 |
| `darwin-arm` | `2.2.0` | 2026-03-07 |
| `win11-arm` | `2.2.0` | 2026-05-09 |
| `linux-x64` | `2.2.0` | 2025-04-21 |
| `linux-x64` | `2.2.0` | 2026-06-14 |
| `linux-arm` | `2.2.0` | 2026-03-07 |
:::

@ -146,11 +146,11 @@ This demo was tested in the following deployments:
| V8 Version | Platform | OS Version | Compiler | Date |
|:--------------|:-------------|:--------------|:-----------------|:-----------|
| `13.7.5` | `darwin-x64` | macOS 15.3.2 | `clang 16.0.0` | 2025-03-31 |
| `15.1.102` | `darwin-x64` | macOS 15.7.4 | `clang 17.0.0` | 2026-06-13 |
| `13.5.92` | `darwin-arm` | macOS 14.5 | `clang 16.0.0` | 2025-02-15 |
| `13.8.124` | `win11-x64` | Windows 11 | `CL 19.43.34810` | 2025-05-11 |
| `13.5.92` | `linux-x64` | Ubuntu 24.04 | `gcc 13.3.0` | 2025-06-16 |
| `13.5.92` | `linux-arm` | Debian 12 | `gcc 12.2.0` | 2025-02-15 |
| `13.8.124` | `linux-arm` | Debian 12 | `gcc 14.2.0` | 2026-06-14 |
:::
@ -449,19 +449,30 @@ The recommended fix is to delete the referenced folder and re-run `gclient sync`
</Tabs>
5) Checkout the desired version. The following command pulls `13.8.124`:
5) Checkout the desired version. The following command pulls `15.1.102`:
```bash
git checkout tags/13.8.124 -b sample
git checkout tags/15.1.102 -b sample
```
:::info pass
The ["Tested Deployments" table](#complete-example) includes the exact versions
that were tested on various platforms. It is strongly recommeded to use the
tested versions as they have been explicitly verified by SheetJS teammates.
**Please reach out to [the SheetJS chat](https://sheetjs.com/chat) if there are
any issues not mentioned in the demo page.**
:::
:::caution pass
The official documentation recommends:
```bash
git checkout refs/tags/13.8.124 -b sample -t
git checkout refs/tags/15.1.102 -b sample -t
```
This command failed in local testing:
@ -480,17 +491,33 @@ fatal: cannot set up tracking information; starting point 'refs/tags/13.8.124' i
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="Intel Mac">
Run the following command. It may fail.
```bash
tools/dev/v8gen.py x64.release.sample
```
Append the following lines to `out.gn/x64.release.sample/args.gn`:
```text title="out.gn/x64.release.sample/args.gn (add to file)"
v8_enable_sandbox = false
use_allocator_shim = false
v8_enable_temporal_support = false
```
Run the build:
```bash
gn gen out.gn/x64.release.sample/
ninja -C out.gn/x64.release.sample v8_monolith
```
:::caution pass
:::info pass
**This may not work in newer Python releases due to a breaking change!**
Python 3.13 removed the `pipes` module from the standard library[^7]. `v8gen.py`
will fail on newer Python releases with the following traceback:
may fail on newer Python releases with the following traceback:
```
Traceback (most recent call last):
@ -567,6 +594,8 @@ treat_warnings_as_errors = false
</TabItem>
<TabItem value="linux-arm" label="Linux ARM">
Run the following command. It may fail.
```bash
tools/dev/v8gen.py arm64.release.sample
```
@ -576,11 +605,14 @@ Append the following lines to `out.gn/arm64.release.sample/args.gn`:
```text title="out.gn/arm64.release.sample/args.gn (add to file)"
is_clang = false
treat_warnings_as_errors = false
v8_enable_sandbox = false
v8_enable_temporal_support = false
```
Run the build:
```bash
gn gen out.gn/arm64.release.sample/
ninja -C out.gn/arm64.release.sample v8_monolith
```
@ -628,6 +660,22 @@ adding `false &&` to the `elif` preprocessor directives:
int8x8_t x;
```
There may be a block in `src/objects/simd.cc` that includes `arm_neon.h`. If
this block is present, the entire `ifdef` clause should be commented:
```cpp title="src/objects/simd.cc (edit highlighted lines)"
#ifdef V8_HOST_ARCH_ARM64
// We use Neon only on 64-bit ARM (because on 32-bit, some instructions and some
// types are not available). Note that ARM64 is guaranteed to have Neon.
//highlight-start
//#define NEON64
//#include <arm_neon.h>
//highlight-end
#endif
```
:::
:::note pass
@ -742,10 +790,27 @@ ninja -C out.gn\x64.release.sample v8_monolith
```bash
g++ -I. -Iinclude samples/hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
-ldl -Lout.gn/x64.release.sample/obj/ -pthread \
-std=c++20 -DV8_COMPRESS_POINTERS=1 -DV8_ENABLE_SANDBOX -framework Foundation
-std=c++20 -DV8_COMPRESS_POINTERS=1 -framework Foundation
./hello_world
```
:::caution pass
In some tests, the `hello_world` program failed with a message referencing ICU:
```
Failed to initialize ICU
```
`icudtl.dat` must be copied to the folder with the `hello_world` program:
```bash
cp out.gn/x64.release.sample/icudtl.dat .
./hello_world
```
:::
:::info pass
In older V8 versions, the flags `-lv8_libbase -lv8_libplatform` were required.
@ -798,7 +863,7 @@ g++ -I. -Iinclude samples/hello-world.cc -o hello_world -fno-rtti -lv8_monolith
```bash
g++ -I. -Iinclude samples/hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
-lv8_libbase -lv8_libplatform -ldl -Lout.gn/arm64.release.sample/obj/ -pthread \
-std=c++20 -DV8_COMPRESS_POINTERS=1 -DV8_ENABLE_SANDBOX
-std=c++20 -DV8_COMPRESS_POINTERS=1
./hello_world
```
@ -878,6 +943,12 @@ cp ~/dev/v8/v8/samples/hello-world.cc .
```bash
ln -s ~/dev/v8/v8/include
ln -s ~/dev/v8/v8/out.gn/x64.release.sample/obj
```
In addition, `icudtl.dat` must be copied to this folder:
```bash
cp ~/dev/v8/v8/out.gn/*/icudtl.dat .
```
</TabItem>
@ -952,7 +1023,16 @@ g++ -I. -Iinclude hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
:::caution pass
On macOS, in some V8 versions, the `Foundation` framework is required:
On macOS, some builds fail due to undefined symbols starting with `_CF`:
```
Undefined symbols for architecture x86_64:
"_CFRelease", referenced from:
absl::time_internal::cctz::local_time_zone() in libv8_monolith.a[777](time_zone_lookup.o)
```
These symbols are provided by `Foundation` framework. `-framework Foundation`
must be added to the build step:
```bash
g++ -I. -Iinclude hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
@ -963,6 +1043,27 @@ g++ -I. -Iinclude hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
:::
:::caution pass
In some tests, the `hello_world` program failed with a sandbox error:
```
# Embedder-vs-V8 build configuration mismatch. On embedder side sandbox is ENABLED while on V8 side it's DISABLED.
```
If the sandbox was disabled earlier, the `-DV8_ENABLE_SANDBOX` must be removed.
For example, the following build command works with V8 `15.1.102` on Intel Mac:
```bash
g++ -I. -Iinclude hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
-ldl -Lobj/ -pthread -std=c++20 \
-DV8_COMPRESS_POINTERS=1 -framework Foundation
./hello_world
```
:::
</TabItem>
<TabItem value="win" label="Windows">
@ -1026,7 +1127,16 @@ g++ -I. -Iinclude sheetjs.v8.cc -o sheetjs.v8 -fno-rtti -lv8_monolith \
:::caution pass
On macOS, in some V8 versions, the `Foundation` framework is required:
On macOS, some builds fail due to undefined symbols starting with `_CF`:
```
Undefined symbols for architecture x86_64:
"_CFRelease", referenced from:
absl::time_internal::cctz::local_time_zone() in libv8_monolith.a[777](time_zone_lookup.o)
```
These symbols are provided by `Foundation` framework. `-framework Foundation`
must be added to the build step:
```bash
g++ -I. -Iinclude sheetjs.v8.cc -o sheetjs.v8 -fno-rtti -lv8_monolith \
@ -1055,6 +1165,26 @@ cl /MT /I..\v8\v8\ /I..\v8\v8\include sheetjs.v8.cc /GR- v8_monolith.lib Advapi3
./sheetjs.v8 pres.numbers
```
:::caution pass
In some tests, the `hello_world` program failed with a sandbox error:
```
# Embedder-vs-V8 build configuration mismatch. On embedder side sandbox is ENABLED while on V8 side it's DISABLED.
```
If the sandbox was disabled earlier, the `-DV8_ENABLE_SANDBOX` must be removed.
For example, the following build command works with V8 `15.1.102` on Intel Mac:
```bash
g++ -I. -Iinclude sheetjs.v8.cc -o sheetjs.v8 -fno-rtti -lv8_monolith \
-ldl -Lobj/ -pthread -std=c++20 \
-DV8_COMPRESS_POINTERS=1 -framework Foundation
./sheetjs.v8 pres.numbers
```
:::
</TabItem>
<TabItem value="win" label="Windows">
@ -1098,7 +1228,7 @@ This demo was last tested in the following deployments:
|:-------------|:----------|:-----------|
| `darwin-x64` | `146.3.0` | 2026-03-08 |
| `darwin-arm` | `134.3.0` | 2025-02-13 |
| `win11-x64` | `137.1.0` | 2025-05-11 |
| `win11-x64` | `150.0.0` | 2026-06-14 |
| `win11-arm` | `145.0.0` | 2026-02-02 |
| `linux-x64` | `142.2.0` | 2026-01-08 |
| `linux-arm` | `146.3.0` | 2026-03-07 |
@ -1175,7 +1305,7 @@ curl.exe -L -o src/main.rs https://docs.sheetjs.com/v8/main.rs
:::info pass
There were multiple breaking changes in the `v8` crate. This example was tested
against version `142.2.0`.
against versions `142.2.0` and `150.0.0`.
Older versions of this demo script were designed for older `v8` versions. They
are available in the source repo for the documentation. Please reach out to the
@ -1212,7 +1342,7 @@ This demo was last tested in the following deployments:
| Architecture | V8 Version | Javet | Java | Date |
|:-------------|:--------------|:--------|:----------|:-----------|
| `darwin-x64` | `13.2.152.16` | `4.1.1` | `24.0.1` | 2025-04-21 |
| `darwin-x64` | `13.2.152.16` | `4.1.1` | `25.0.2` | 2026-06-13 |
| `darwin-arm` | `13.2.152.16` | `4.1.1` | `17.0.14` | 2026-03-04 |
| `win11-x64` | `13.2.152.16` | `4.1.1` | `17.0.12` | 2026-03-04 |
| `win11-arm` | `13.2.152.16` | `4.1.1` | `25.0.2` | 2026-03-04 |
@ -1447,7 +1577,7 @@ This demo was last tested in the following deployments:
|:-------------|:--------------|:-----------|
| `darwin-x64` | `13.3.415.23` | 2026-03-06 |
| `darwin-arm` | `13.3.415.23` | 2026-03-06 |
| `win11-x64` | `13.3.415.23` | 2025-05-11 |
| `win11-x64` | `14.7.173.23` | 2026-06-14 |
| `win11-arm` | `12.3.219.12` | 2025-02-23 |
| `linux-x64` | `12.3.219.12` | 2026-03-06 |
| `linux-arm` | `13.3.415.23` | 2026-03-07 |
@ -1525,7 +1655,7 @@ dotnet run
4) Add ClearScript to the project:
```bash
dotnet add package Microsoft.ClearScript.Complete --version 7.5.0
dotnet add package Microsoft.ClearScript.Complete --version 7.5.1
```
5) Download the SheetJS standalone script and test file. Move both files to the
@ -1740,8 +1870,8 @@ This demo was last tested in the following deployments:
|:-------------|:--------------|:----------|:-----------|
| `darwin-x64` | `13.5.212.10` | `136.0.0` | 2026-03-08 |
| `darwin-arm` | `13.5.212.10` | `136.0.0` | 2025-04-24 |
| `win11-x64` | `13.5.212.10` | `136.0.0` | 2025-05-11 |
| `linux-x64` | `13.5.212.10` | `136.0.0` | 2025-06-16 |
| `win11-x64` | `15.0.245.2` | `150.0.0` | 2026-06-14 |
| `linux-x64` | `15.0.245.2` | `150.0.0` | 2026-06-14 |
| `linux-arm` | `13.5.212.10` | `136.0.0` | 2026-03-07 |
:::
@ -1828,7 +1958,7 @@ mv target/release/sheet2csv .
<TabItem value="win" label="Windows">
```bash
mv target/release/sheet2csv.exe .
move target\release\sheet2csv.exe .
.\sheet2csv.exe pres.numbers
```

@ -108,8 +108,8 @@ This demo was tested in the following deployments:
| `darwin-x64` | `651366f` | `1.25.6` | 2026-01-21 |
| `darwin-arm` | `6a7976c` | `1.24.0` | 2026-03-07 |
| `win11-x64` | `6a7976c` | `1.24.2` | 2026-03-08 |
| `win11-arm` | `065cd970` | `1.26.1` | 2026-03-22 |
| `linux-x64` | `cb187b0` | `1.22.2` | 2025-06-16 |
| `win11-arm` | `065cd97` | `1.26.1` | 2026-03-22 |
| `linux-x64` | `348e6be` | `1.25.11` | 2026-06-14 |
| `linux-arm` | `6a7976c` | `1.24.4` | 2026-03-07 |
At the time of writing, Goja did not have proper version numbers. Versions are

@ -366,7 +366,7 @@ This demo was tested in the following deployments:
|:-------------|:-----------|:-----------|
| `darwin-x64` | `f45c6bc` | 2026-03-06 |
| `darwin-arm` | `f45c6bc` | 2026-01-23 |
| `linux-x64` | `8ef11b4` | 2025-04-21 |
| `linux-x64` | `f45c6bc` | 2026-06-14 |
| `linux-arm` | `f45c6bc` | 2026-03-07 |
The main Hermes source tree does not have Windows support. The `hermes-windows`
@ -914,7 +914,7 @@ This demo was tested in the following deployments:
| `darwin-arm` | `0.13.0` | 2026-03-06 |
| `win11-x64` | `0.13.0` | 2026-05-10 |
| `win11-arm` | `0.13.0` | 2025-02-23 |
| `linux-x64` | `0.13.0` | 2025-04-21 |
| `linux-x64` | `0.13.0` | 2026-06-14 |
| `linux-arm` | `0.13.0` | 2026-03-07 |
When this demo was last tested, `jsvu` did not install a native `linux-arm`

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
v8 = "136.0.0"
v8 = "150.0.0"
[[bin]]
name = "sheet2csv"

@ -1,5 +1,8 @@
/*! sheetjs (C) SheetJS -- https://sheetjs.com */
/* run code, get result as a Rust String */
fn eval_code(scope: &mut v8::HandleScope, code: &str) -> std::string::String {
fn eval_code(scope: &mut v8::PinScope, code: &str) -> std::string::String {
let scope = std::pin::pin!(v8::HandleScope::new(scope));
let scope = &mut scope.init();
let source = v8::String::new(scope, code).unwrap();
let script = v8::Script::compile(scope, source, None).unwrap();
let result = script.run(scope).unwrap();
@ -7,7 +10,9 @@ fn eval_code(scope: &mut v8::HandleScope, code: &str) -> std::string::String {
}
/* assuming JS code returns an ArrayBuffer, copy result to a Vec<u8> */
fn eval_code_ab(scope: &mut v8::HandleScope, code: &str) -> Vec<u8> {
fn eval_code_ab(scope: &mut v8::PinScope, code: &str) -> Vec<u8> {
let scope = std::pin::pin!(v8::HandleScope::new(scope));
let scope = &mut scope.init();
let source = v8::String::new(scope, code).unwrap();
let script = v8::Script::compile(scope, source, None).unwrap();
let result: v8::Local<v8::ArrayBuffer> = script.run(scope).unwrap().try_into().unwrap();
@ -30,11 +35,11 @@ fn main() {
/* read snapshot */
let startup_data: Vec<u8> = include_bytes!("./snapshot.bin").to_vec();
let params = v8::Isolate::create_params().snapshot_blob(startup_data);
let isolate = &mut v8::Isolate::new(params);
let handle_scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(handle_scope, Default::default());
let context_scope = &mut v8::ContextScope::new(handle_scope, context);
let params = v8::Isolate::create_params().snapshot_blob(startup_data.into());
let mut isolate = v8::Isolate::new(params);
v8::scope!(let scope, &mut isolate);
let context = v8::Context::new(scope, Default::default());
let context_scope = &mut v8::ContextScope::new(scope, context);
/* read file */
{

@ -1,6 +1,8 @@
/*! sheetjs (C) SheetJS -- https://sheetjs.com */
/* run code and ignore result */
fn eval_code(scope: &mut v8::HandleScope, code: &str) {
fn eval_code(scope: &mut v8::PinScope, code: &str) {
let scope = std::pin::pin!(v8::HandleScope::new(scope));
let scope = &mut scope.init();
let source = v8::String::new(scope, code).unwrap();
let script = v8::Script::compile(scope, source, None).unwrap();
let _ = script.run(scope);
@ -18,9 +20,9 @@ fn main() {
/* scope enforces the lifetime of the `&mut isolate` in `handle_scope` */
{
/* same steps as normal flow */
let handle_scope = &mut v8::HandleScope::new(&mut isolate);
let context = v8::Context::new(handle_scope, Default::default());
let context_scope = &mut v8::ContextScope::new(handle_scope, context);
v8::scope!(let scope, &mut isolate);
let context = v8::Context::new(scope, Default::default());
let context_scope = &mut v8::ContextScope::new(scope, context);
/* instructs the snapshot creator to dump the new context */
context_scope.set_default_context(context);

@ -3,7 +3,7 @@
import './App.css'
import { useCallback, useState } from '@lynx-js/react'
import SheetJSLogo from './assets/SheetJS-logo.png';
import { read, utils, WorkSheet } from 'xlsx';
import { read, utils, type WorkSheet } from 'xlsx';
const make_width = (ws: WorkSheet): number[] => {
const aoa = utils.sheet_to_json(ws, { header: 1 }), res: number[] = [];

@ -11,9 +11,10 @@ curl -LO https://docs.sheetjs.com/duk/SheetJSDuk.pl
curl -LO https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.extendscript.js
curl -LO https://docs.sheetjs.com/pres.xlsx
perl SheetJSDuk.pl pres.xlsx; echo $?
perl SheetJSDuk.pl pres.xlsx
PERL_EXIT=$?
npx -y xlsx-cli SheetJSDuk.xlsb
if [ $PERL_EXIT -ne 0 ] || [ ! -f SheetJSDuk.xlsb ]; then
cat <<EOF
If the script failed with an error about XS, install dependencies:
@ -23,3 +24,7 @@ This command may need to be run as root:
$ sudo cpan install JavaScript::Duktape::XS
EOF
exit 1
fi
npx -y xlsx-cli SheetJSDuk.xlsb