V8 Python Binding Demo
This commit is contained in:
parent
d0f75f27c3
commit
8ccb92b3e5
13
docz/data/bindings.js
Normal file
13
docz/data/bindings.js
Normal file
@ -0,0 +1,13 @@
|
||||
import url from './engines.xls';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
const BindingData = () => {
|
||||
const [binding, setBinding] = useState("");
|
||||
|
||||
useEffect(() => { (async() => {
|
||||
const html = await (await fetch(url)).json();
|
||||
setBinding(html["Bindings"]);
|
||||
})(); }, []);
|
||||
return ( <p dangerouslySetInnerHTML={{__html: binding}}/> );
|
||||
};
|
||||
export default BindingData;
|
@ -3,19 +3,11 @@ import React, { useEffect, useState } from 'react';
|
||||
|
||||
const EngineData = () => {
|
||||
const [engines, setEngines] = useState("");
|
||||
const [binding, setBinding] = useState("");
|
||||
|
||||
useEffect(() => { (async() => {
|
||||
const html = await (await fetch(url)).json();
|
||||
setEngines(html["Engines"]);
|
||||
setBinding(html["Bindings"]);
|
||||
})(); }, []);
|
||||
return ( <>
|
||||
<p>The following engines have been tested in their native languages:</p>
|
||||
<div dangerouslySetInnerHTML={{__html: engines}}/>
|
||||
<p>The following bindings have been tested:</p>
|
||||
<div dangerouslySetInnerHTML={{__html: binding}}/>
|
||||
<p>Asterisks (✱) in the Windows columns mark tests that were run in Windows Subsystem for Linux (WSL)</p>
|
||||
</> );
|
||||
return ( <p dangerouslySetInnerHTML={{__html: engines}}/> );
|
||||
};
|
||||
export default EngineData;
|
@ -244,7 +244,7 @@
|
||||
</WorksheetOptions>
|
||||
</Worksheet>
|
||||
<Worksheet ss:Name="Bindings">
|
||||
<Table ss:ExpandedColumnCount="8" ss:ExpandedRowCount="15" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
|
||||
<Table ss:ExpandedColumnCount="8" ss:ExpandedRowCount="16" 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"/>
|
||||
@ -337,6 +337,16 @@
|
||||
<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/engines/v8#python"><Data ss:Type="String">V8</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Python</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>
|
||||
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/engines/jsc#swift"><Data ss:Type="String">JSC</Data></Cell>
|
||||
<Cell><Data ss:Type="String">Swift</Data></Cell>
|
||||
|
@ -134,9 +134,31 @@ sap.ui.define([
|
||||
"path/to/xlsx.full.min"
|
||||
], function(/* ... variables for the other libraries ... */, XLSX) {
|
||||
// use XLSX here
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
|
||||
In some deployments, the function argument was `undefined`.
|
||||
|
||||
The standalone scripts add `window.XLSX`, so it is recommended to use `_XLSX`
|
||||
in the function arguments and access the library with `XLSX` in the callback:
|
||||
|
||||
```js
|
||||
sap.ui.define([
|
||||
/* ... other libraries ... */
|
||||
"path/to/xlsx.full.min"
|
||||
], function(
|
||||
/* ... variables for the other libraries ... */,
|
||||
_XLSX // !! NOTE: this is not XLSX! A different variable name must be used
|
||||
) {
|
||||
// highlight-next-line
|
||||
alert(XLSX.version); // use XLSX in the callback
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::danger pass
|
||||
|
||||
**Copy and pasting code does not work** for SheetJS scripts as they contain
|
||||
|
@ -59,7 +59,7 @@ can be loaded in the root HTML page (typically `wwwroot/index.html`):
|
||||
#### ECMAScript Module
|
||||
|
||||
The SheetJS ECMAScript module script can be dynamically imported from functions.
|
||||
This ensures the library is only loaded when necessary. The following example
|
||||
This ensures the library is only loaded when necessary. The following JS example
|
||||
loads the library and returns a Promise that resolves to the version string:
|
||||
|
||||
<CodeBlock language="js">{`\
|
||||
@ -75,6 +75,22 @@ async function sheetjs_version(id) {
|
||||
|
||||
### Calling JS from C#
|
||||
|
||||
Callbacks for events in Razor elements invoke C# methods. The C# methods can use
|
||||
Blazor APIs to invoke JS methods that are visible in the browser global scope.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor U as User
|
||||
participant P as Browser
|
||||
participant A as Blazor
|
||||
U-->>P: click button
|
||||
P-->>A: click event
|
||||
Note over A: C#35; callback<br/><br/>InvokeVoidAsync
|
||||
A->>P: call JS function
|
||||
Note over P: global method<br/><br/>SheetJS logic
|
||||
P->>U: download workbook
|
||||
```
|
||||
|
||||
#### Setup
|
||||
|
||||
The primary mechanism for invoking JS functions from Blazor is `IJSRuntime`[^1].
|
||||
@ -88,7 +104,9 @@ It should be injected at the top of relevant Razor component scripts:
|
||||
|
||||
When exporting a file with the SheetJS `writeFile` method[^2], browser APIs do
|
||||
not provide success or error feedback. As a result, this demo invokes functions
|
||||
using the `InvokeVoidAsync` static method[^3]:
|
||||
using the `InvokeVoidAsync` static method[^3].
|
||||
|
||||
The following C# method will invoke the `export_method` method in the browser:
|
||||
|
||||
```csharp title="Invoking JS functions from C#"
|
||||
private async Task ExportDataset() {
|
||||
@ -96,7 +114,54 @@ private async Task ExportDataset() {
|
||||
}
|
||||
```
|
||||
|
||||
Methods are commonly bound to buttons in the Razor template using `@onclick`:
|
||||
:::caution pass
|
||||
|
||||
**The JS methods must be defined in the global scope!**
|
||||
|
||||
In this demo, the script is added to the `HEAD` block of the root HTML file:
|
||||
|
||||
```html title="wwwroot/index.html"
|
||||
<head>
|
||||
<!-- ... meta / title / base / link tags -->
|
||||
<link href="SheetJSBlazorWasm.styles.css" rel="stylesheet" />
|
||||
|
||||
<!-- highlight-start -->
|
||||
<!-- script with `export_method` is in the HEAD block -->
|
||||
<script>
|
||||
/* In a normal script tag, Blazor JS can call this method */
|
||||
async function export_method(...rows) {
|
||||
/* display the array of objects */
|
||||
console.log(rows);
|
||||
}
|
||||
</script>
|
||||
<!-- highlight-end -->
|
||||
</head>
|
||||
```
|
||||
|
||||
When using `<script type="module">`, top-level function definitions are not
|
||||
visible to Blazor by default. They must be attached to `globalThis`:
|
||||
|
||||
```html title="Attaching methods to globalThis"
|
||||
<script type="module">
|
||||
/* Using `type="module"`, Blazor JS cannot see this function definition */
|
||||
async function export_method(...rows) {
|
||||
/* display the array of objects */
|
||||
console.log(rows);
|
||||
}
|
||||
|
||||
// highlight-start
|
||||
/* Once attached to `globalThis`, Blazor JS can call this method */
|
||||
globalThis.export_method = export_method;
|
||||
// highlight-end
|
||||
</script>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
#### Blazor Callbacks
|
||||
|
||||
Methods are commonly bound to buttons in the Razor template using `@onclick`.
|
||||
When the following button is clicked, Blazor will invoke `ExportDataset`:
|
||||
|
||||
```html title="Binding callback to a HTML button"
|
||||
<button @onclick="ExportDataset">Export Dataset</button>
|
||||
|
@ -32,10 +32,10 @@ can be parsed and evaluated in a V8 context.
|
||||
|
||||
:::note pass
|
||||
|
||||
This section describes a flow where the script is parsed and evaluated every
|
||||
time the program is run.
|
||||
This section describes a flow where the script is parsed and evaluated each time
|
||||
the program is run.
|
||||
|
||||
Using V8 snapshots, SheetJS libraries can be parsed and evaluated beforehand.
|
||||
Using V8 snapshots, SheetJS libraries can be parsed and evaluated at build time.
|
||||
This greatly improves program startup time.
|
||||
|
||||
The ["Snapshots"](#snapshots) section includes a complete example.
|
||||
@ -96,30 +96,40 @@ To confirm the library is loaded, `XLSX.version` can be inspected:
|
||||
### Reading Files
|
||||
|
||||
V8 supports `ArrayBuffer` natively. Assuming `buf` is a C byte array, with
|
||||
length `len`, this snippet stores the data as an `ArrayBuffer` in global scope:
|
||||
length `len`, the following code stores the data in a global `ArrayBuffer`:
|
||||
|
||||
```cpp
|
||||
```cpp title="Loading data into an ArrayBuffer in the V8 engine"
|
||||
/* load C char array and save to an ArrayBuffer */
|
||||
std::unique_ptr<v8::BackingStore> back = v8::ArrayBuffer::NewBackingStore(isolate, len);
|
||||
memcpy(back->Data(), buf, len);
|
||||
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, std::move(back));
|
||||
v8::Maybe<bool> res = context->Global()->Set(context, v8::String::NewFromUtf8Literal(isolate, "buf"), ab);
|
||||
```
|
||||
|
||||
Once the raw data is pulled into the engine, the SheetJS `read` method[^1] can
|
||||
parse the data. It is recommended to attach the result to a global variable:
|
||||
|
||||
```cpp
|
||||
/* parse with SheetJS */
|
||||
v8::Local<v8::Value> result = eval_code(isolate, context, "globalThis.wb = XLSX.read(buf)");
|
||||
```
|
||||
|
||||
`wb` will be a variable in the JS environment that can be inspected using the
|
||||
various SheetJS API functions.
|
||||
`wb`, a SheetJS workbook object[^2], will be a variable in the JS environment
|
||||
that can be inspected using the various SheetJS API functions[^3].
|
||||
|
||||
### Writing Files
|
||||
|
||||
The underlying memory from an `ArrayBuffer` can be recovered:
|
||||
The SheetJS `write` method[^4] generates file bytes from workbook objects. The
|
||||
`array` type[^5] instructs the library to generate `ArrayBuffer` objects:
|
||||
|
||||
```c
|
||||
```cpp
|
||||
/* write with SheetJS using type: "array" */
|
||||
v8::Local<v8::Value> result = eval_code(isolate, context, "XLSX.write(wb, {type:'array', bookType:'xlsb'})");
|
||||
```
|
||||
|
||||
The underlying memory from an `ArrayBuffer` can be pulled from the engine:
|
||||
|
||||
```cpp title="Pulling raw bytes from an ArrayBuffer"
|
||||
/* pull result back to C++ */
|
||||
v8::Local<v8::ArrayBuffer> ab = v8::Local<v8::ArrayBuffer>::Cast(result);
|
||||
size_t sz = ab->ByteLength();
|
||||
@ -150,13 +160,13 @@ generates an XLSB file and writes to the filesystem.
|
||||
:::caution pass
|
||||
|
||||
When the demo was last tested, there were errors in the official V8 embed guide.
|
||||
The correct instructions are included below.
|
||||
Corrected instructions are included below.
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
:::danger pass
|
||||
|
||||
The build process is long and will test your patience.
|
||||
**The build process is long and will test your patience.**
|
||||
|
||||
:::
|
||||
|
||||
@ -894,7 +904,7 @@ may not work on every platform.
|
||||
|
||||
### Rust
|
||||
|
||||
The `v8` crate provides binary builds and straightforward bindings. The Rust
|
||||
The `v8` crate[^6] provides binary builds and straightforward bindings. The Rust
|
||||
code is similar to the C++ code.
|
||||
|
||||
Pulling data from an `ArrayBuffer` back into Rust involves an unsafe operation:
|
||||
@ -1125,7 +1135,8 @@ If the program succeeded, the CSV contents will be printed to console.
|
||||
|
||||
### C#
|
||||
|
||||
ClearScript provides a .NET interface to the V8 engine.
|
||||
[ClearScript](https://microsoft.github.io/ClearScript/) is a .NET interface to
|
||||
the V8 engine.
|
||||
|
||||
C# byte arrays (`byte[]`) must be explicitly converted to arrays of bytes:
|
||||
|
||||
@ -1231,8 +1242,8 @@ dotnet run
|
||||
dotnet add package Microsoft.ClearScript.Complete --version 7.4.5
|
||||
```
|
||||
|
||||
5) Download the SheetJS standalone script and test file. Move all three files to
|
||||
the project directory:
|
||||
5) Download the SheetJS standalone script and test file. Move both files to the
|
||||
project directory:
|
||||
|
||||
<ul>
|
||||
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
|
||||
@ -1282,6 +1293,139 @@ If successful, the program will print the contents of the first sheet as CSV
|
||||
rows. It will also create `SheetJSClearScript.xlsb`, a workbook that can be
|
||||
opened in a spreadsheet editor.
|
||||
|
||||
### Python
|
||||
|
||||
[`pyv8`](https://code.google.com/archive/p/pyv8/) is a Python wrapper for V8.
|
||||
|
||||
The `stpyv8` package[^7] is an actively-maintained fork with binary wheels.
|
||||
|
||||
:::caution pass
|
||||
|
||||
When this demo was last tested, there was no direct conversion between Python
|
||||
`bytes` and JavaScript `ArrayBuffer` data.
|
||||
|
||||
This is a known issue[^8]. The current recommendation is Base64 strings.
|
||||
|
||||
:::
|
||||
|
||||
#### Python Base64 Strings
|
||||
|
||||
The SheetJS `read`[^1] and `write`[^4] methods support Base64 strings through
|
||||
the `base64` type[^5].
|
||||
|
||||
_Reading Files_
|
||||
|
||||
It is recommended to create a global context with a special method that handles
|
||||
file reading from Python. The `read_file` helper in the following snippet will
|
||||
read bytes from `sheetjs.xlsx` and generate a Base64 string:
|
||||
|
||||
```py
|
||||
from base64 import b64encode;
|
||||
from STPyV8 import JSContext, JSClass;
|
||||
|
||||
# Create context with methods for file i/o
|
||||
class Base64Context(JSClass):
|
||||
def read_file(self, path):
|
||||
with open(path, "rb") as f:
|
||||
data = f.read();
|
||||
return b64encode(data).decode("ascii");
|
||||
globals = Base64Context();
|
||||
|
||||
# The JSContext starts and cleans up the V8 engine
|
||||
with JSContext(globals) as ctxt:
|
||||
print(ctxt.eval("read_file('sheetjs.xlsx')")); # read base64 data and print
|
||||
```
|
||||
|
||||
_Writing Files_
|
||||
|
||||
Since the SheetJS `write` method returns a Base64 string, the result can be
|
||||
decoded and written to file from Python:
|
||||
|
||||
```py
|
||||
from base64 import b64decode;
|
||||
from STPyV8 import JSContext;
|
||||
|
||||
# The JSContext starts and cleans up the V8 engine
|
||||
with JSContext() as ctxt:
|
||||
# ... initialization and workbook creation ...
|
||||
xlsb = ctxt.eval("XLSX.write(wb, {type: 'base64', bookType: 'xlsb'})");
|
||||
with open("SheetJSSTPyV8.xlsb", "wb") as f:
|
||||
f.write(b64decode(xlsb));
|
||||
```
|
||||
|
||||
#### Python Demo
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested in the following deployments:
|
||||
|
||||
| Architecture | V8 Version | Python | Date |
|
||||
|:-------------|:--------------|:---------|:-----------|
|
||||
| `darwin-arm` | `13.0.245.16` | `3.13.0` | 2024-10-20 |
|
||||
|
||||
:::
|
||||
|
||||
0) Make a new folder for the project:
|
||||
|
||||
```bash
|
||||
mkdir sheetjs-stpyv8
|
||||
cd sheetjs-stpyv8
|
||||
```
|
||||
|
||||
1) Install `stpyv8`:
|
||||
|
||||
```bash
|
||||
pip install stpyv8
|
||||
```
|
||||
|
||||
:::caution pass
|
||||
|
||||
The install may fail with a `externally-managed-environment` error:
|
||||
|
||||
```
|
||||
error: externally-managed-environment
|
||||
|
||||
× This environment is externally managed
|
||||
```
|
||||
|
||||
The wheel can be downloaded and forcefully installed. The following commands
|
||||
download and install version `13.0.245.16` for Python `3.13` on `darwin-arm`:
|
||||
|
||||
```bash
|
||||
curl -LO https://github.com/cloudflare/stpyv8/releases/download/v13.0.245.16/stpyv8-13.0.245.16-cp313-cp313-macosx_14_0_arm64.whl
|
||||
sudo python -m pip install --upgrade stpyv8-13.0.245.16-cp313-cp313-macosx_14_0_arm64.whl --break-system-packages
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
2) Download the SheetJS standalone script and test file. Move both files to the
|
||||
project directory:
|
||||
|
||||
<ul>
|
||||
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
|
||||
<li><a href="https://docs.sheetjs.com/pres.xlsx">pres.xlsx</a></li>
|
||||
</ul>
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
|
||||
curl -LO https://docs.sheetjs.com/pres.xlsx`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Download [`sheetjs-stpyv8.py`](pathname:///v8/sheetjs-stpyv8.py):
|
||||
|
||||
```bash
|
||||
curl -LO https://docs.sheetjs.com/v8/sheetjs-stpyv8.py
|
||||
```
|
||||
|
||||
4) Run the script and pass `pres.xlsx` as the first argument:
|
||||
|
||||
```bash
|
||||
python sheetjs-stpyv8.py pres.xlsx
|
||||
```
|
||||
|
||||
The script will display CSV rows from the first worksheet. It will also create
|
||||
`SheetJSSTPyV8.xlsb`, a workbook that can be opened with a spreadsheet editor.
|
||||
|
||||
## Snapshots
|
||||
|
||||
At a high level, V8 snapshots are raw dumps of the V8 engine state. It is much
|
||||
@ -1403,3 +1547,12 @@ mv target/release/sheet2csv.exe .
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
[^1]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^2]: See ["SheetJS Data Model"](/docs/csf) for more details on the object representation.
|
||||
[^3]: See ["API Reference"](/docs/api) for a list of functions that ship with the library. ["Spreadsheet Features"](/docs/csf/features) covers workbook and worksheet features that can be modified directly.
|
||||
[^4]: See [`write` in "Writing Files"](/docs/api/write-options)
|
||||
[^5]: See ["Supported Output Formats" type in "Writing Files"](/docs/api/write-options#supported-output-formats)
|
||||
[^6]: The project does not have an official website. The [official Rust crate](https://crates.io/crates/v8) is hosted on `crates.io`.
|
||||
[^7]: The project does not have a separate website. The source repository is hosted on [GitHub](https://github.com/cloudflare/stpyv8)
|
||||
[^8]: According to a maintainer, [typed arrays were not supported in the original `pyv8` project](https://github.com/cloudflare/stpyv8/issues/104#issuecomment-2059125389)
|
@ -22,6 +22,41 @@ This demo uses JSC and SheetJS to read and write spreadsheets. We'll explore how
|
||||
to load SheetJS in a JSC context and process spreadsheets and structured data
|
||||
from C++ and Swift programs.
|
||||
|
||||
:::note pass
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
[**Swift Built-in**](#swift)
|
||||
|
||||
Swift on MacOS supports JavaScriptCore without additional dependencies.
|
||||
|
||||
| Architecture | Swift | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | `5.10` | 2024-04-04 |
|
||||
| `darwin-arm` | `5.10` | 2024-06-30 |
|
||||
|
||||
[**C / C++ Compiled from Source**](#c)
|
||||
|
||||
JavaScriptCore can be built from source and linked in C / C++ programs.
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:-----------------|:-----------|
|
||||
| `darwin-x64` | `7618.1.15.14.7` | 2024-04-24 |
|
||||
| `darwin-arm` | `7618.2.12.11.7` | 2024-05-24 |
|
||||
| `linux-x64` | `7618.2.12.11.7` | 2024-06-22 |
|
||||
| `linux-arm` | `7618.2.12.11.7` | 2024-06-22 |
|
||||
|
||||
[**Swift Compiled from Source**](#swift-c)
|
||||
|
||||
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 |
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
|
||||
@ -308,31 +343,6 @@ FILE *f = fopen("sheetjsw.xlsb", "wb"); fwrite(buf, 1, sz, f); fclose(f);
|
||||
|
||||
### Swift
|
||||
|
||||
:::note pass
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
**Built-in**
|
||||
|
||||
Swift on MacOS supports JavaScriptCore without additional dependencies.
|
||||
|
||||
| Architecture | Swift | Date |
|
||||
|:-------------|:--------|:-----------|
|
||||
| `darwin-x64` | `5.10` | 2024-04-04 |
|
||||
| `darwin-arm` | `5.10` | 2024-06-30 |
|
||||
|
||||
**Compiled**
|
||||
|
||||
The ["Swift C"](#swift-c) section starts from the static libraries built in the
|
||||
["C++"](#c) section and builds Swift bindings.
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:-----------------|:-----------|
|
||||
| `linux-x64` | `7618.2.12.11.7` | 2024-06-22 |
|
||||
| `linux-arm` | `7618.2.12.11.7` | 2024-06-22 |
|
||||
|
||||
:::
|
||||
|
||||
The demo includes a sample `SheetJSCore` Wrapper class to simplify operations.
|
||||
|
||||
:::caution This demo only runs on MacOS
|
||||
@ -399,19 +409,6 @@ to `SheetJSwift.xlsx`. That file can be verified by opening in Excel / Numbers.
|
||||
|
||||
### C++
|
||||
|
||||
:::note pass
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| Architecture | Version | Date |
|
||||
|:-------------|:-----------------|:-----------|
|
||||
| `darwin-x64` | `7618.1.15.14.7` | 2024-04-24 |
|
||||
| `darwin-arm` | `7618.2.12.11.7` | 2024-05-24 |
|
||||
| `linux-x64` | `7618.2.12.11.7` | 2024-06-22 |
|
||||
| `linux-arm` | `7618.2.12.11.7` | 2024-06-22 |
|
||||
|
||||
:::
|
||||
|
||||
0) Install dependencies
|
||||
|
||||
<details>
|
||||
|
@ -95,8 +95,7 @@ This demo was tested in the following deployments:
|
||||
| `linux-arm` | `3.1.2` | `2.9.1` | 2024-05-25 |
|
||||
|
||||
When the demo was last tested, there was no official Ruby release for Windows
|
||||
on ARM. The `win11-arm` test was run in WSL. The `win10-x64` test used the
|
||||
official Ruby for Windows x64 release.
|
||||
on ARM. The `win11-arm` test was run in WSL.
|
||||
|
||||
:::
|
||||
|
||||
|
@ -5,6 +5,7 @@ pagination_next: solutions/input
|
||||
---
|
||||
|
||||
import EngineData from '/data/engines.js'
|
||||
import BindingData from '/data/bindings.js'
|
||||
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
@ -85,8 +86,27 @@ across multiple architectures (x64 and ARM64).
|
||||
|
||||
:::
|
||||
|
||||
The following engines have been tested in their native languages:
|
||||
|
||||
<EngineData/>
|
||||
|
||||
The following bindings have been tested:
|
||||
|
||||
<BindingData/>
|
||||
|
||||
:::note pass
|
||||
|
||||
Asterisks (✱) in the Windows columns mark tests that were run in Windows
|
||||
Subsystem for Linux (WSL). In some cases, community efforts have produced forks
|
||||
with native Windows support.
|
||||
|
||||
Blank cells mark untested or unsupported configurations. With cross-compilation,
|
||||
V8 can run natively in Windows on ARM. The `win11-arm` platform is not tested
|
||||
since the official build infrastructure does not support Windows on ARM and the
|
||||
V8 project does not distribute shared or static libraries for Windows on ARM.
|
||||
|
||||
:::
|
||||
|
||||
#### Boa
|
||||
|
||||
Boa is an embeddable JS engine written in Rust.
|
||||
@ -165,9 +185,7 @@ V8 is an embeddable JS engine written in C++. It powers Chromium and Chrome,
|
||||
NodeJS and Deno, Adobe UXP and other platforms.
|
||||
|
||||
This demo has been moved [to a dedicated page](/docs/demos/engines/v8).
|
||||
The demo includes examples in C++ and Rust.
|
||||
|
||||
The ["Python + Pandas" demo](/docs/demos/math/pandas) uses V8 with Python.
|
||||
The demo includes examples in C++, C#, Python, and Rust.
|
||||
|
||||
[^1]: See ["Initialize Hermes"](/docs/demos/engines/hermes#initialize-hermes) in the Hermes demo.
|
||||
[^2]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
|
36
docz/static/v8/sheetjs-stpyv8.py
Normal file
36
docz/static/v8/sheetjs-stpyv8.py
Normal file
@ -0,0 +1,36 @@
|
||||
from sys import stderr, argv;
|
||||
from base64 import b64encode, b64decode;
|
||||
from STPyV8 import JSContext, JSClass;
|
||||
|
||||
# Create context with methods for file i/o
|
||||
class Base64Context(JSClass):
|
||||
def read_file(self, path):
|
||||
with open(path, "rb") as f:
|
||||
data = f.read();
|
||||
return b64encode(data).decode("ascii");
|
||||
def write_file(self, data, path):
|
||||
with open(path, "wb") as f:
|
||||
f.write(b64decode(data));
|
||||
globals = Base64Context();
|
||||
|
||||
# Read xlsx.full.min.js
|
||||
with open("xlsx.full.min.js", "r") as f:
|
||||
sheetjs = f.read();
|
||||
|
||||
# The JSContext starts and cleans up the V8 engine
|
||||
with JSContext(globals) as ctxt:
|
||||
# Load SheetJS library and display version number
|
||||
ctxt.eval(sheetjs);
|
||||
version = ctxt.eval("XLSX.version");
|
||||
print(f"SheetJS Version: {version}", file=stderr);
|
||||
|
||||
# Parse workbook
|
||||
ctxt.eval(f"globalThis.wb = XLSX.read(read_file('{argv[1]}'), {{type:'base64'}}); void 0;");
|
||||
|
||||
# Print CSV from first worksheet
|
||||
csv = ctxt.eval("XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);");
|
||||
print(csv);
|
||||
|
||||
# Generate XLSB
|
||||
xlsb = ctxt.eval("XLSX.write(wb, {type: 'base64', bookType: 'xlsb'})");
|
||||
globals.write_file(xlsb,"SheetJSSTPyV8.xlsb");
|
Loading…
Reference in New Issue
Block a user