forked from sheetjs/docs.sheetjs.com
		
	hermes-windows-x64
This commit is contained in:
		
							parent
							
								
									06e7413d36
								
							
						
					
					
						commit
						2c60a9483f
					
				@ -135,6 +135,30 @@ static char *read_file(const char *filename, size_t *sz) {
 | 
			
		||||
  size_t sz; char *xlsx_full_min_js = read_file("xlsx.full.min.js", &sz);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::caution pass
 | 
			
		||||
 | 
			
		||||
For Windows applications, the string must be null-terminated:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
/* Hermes-Windows requires the null terminator */
 | 
			
		||||
static char *read_file_null(const char *filename, size_t *sz) {
 | 
			
		||||
  FILE *f = fopen(filename, "rb");
 | 
			
		||||
  if(!f) return NULL;
 | 
			
		||||
  long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f) + 1; fseek(f, 0, SEEK_SET); }
 | 
			
		||||
  char *buf = (char *)malloc(fsize * sizeof(char));
 | 
			
		||||
  *sz = fread((void *) buf, 1, fsize, f);
 | 
			
		||||
  buf[fsize - 1] = 0;
 | 
			
		||||
  fclose(f);
 | 
			
		||||
  return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ...
 | 
			
		||||
  /* read SheetJS library from filesystem */
 | 
			
		||||
  size_t sz; char *xlsx_full_min_js = read_file_null("xlsx.full.min.js", &sz);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
_Hermes Wrapper_
 | 
			
		||||
 | 
			
		||||
Hermes does not provide a friendly way to prepare JavaScript code stored in a
 | 
			
		||||
@ -343,13 +367,20 @@ This demo was tested in the following deployments:
 | 
			
		||||
| `linux-x64`  | `49e1930`  | 2023-09-22 |
 | 
			
		||||
| `linux-arm`  | `70af78b`  | 2023-08-27 |
 | 
			
		||||
 | 
			
		||||
The main Hermes source tree does not have Windows support. The `hermes-windows`
 | 
			
		||||
fork, which powers React Native for Windows, does have built-in support[^5]
 | 
			
		||||
 | 
			
		||||
| Architecture | Git Commit | Date       |
 | 
			
		||||
|:-------------|:-----------|:-----------|
 | 
			
		||||
| `win10-x64`  | `c7a4a82`  | 2023-09-27 |
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
0) Install [dependencies](https://hermesengine.dev/docs/building-and-running/#dependencies)
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Installation Notes</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
The official guidance[^5] has been verified in macOS and HoloOS (Linux).
 | 
			
		||||
The official guidance[^6] has been verified in macOS and HoloOS (Linux).
 | 
			
		||||
 | 
			
		||||
On macOS:
 | 
			
		||||
 | 
			
		||||
@ -424,6 +455,158 @@ curl -LO https://sheetjs.com/pres.numbers`}
 | 
			
		||||
If successful, the program will print the library version number and the
 | 
			
		||||
contents of the first sheet as CSV rows.
 | 
			
		||||
 | 
			
		||||
### Windows Example
 | 
			
		||||
 | 
			
		||||
0) Install dependencies.
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Installation Notes</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
CMake and Visual Studio with "Desktop development with C++" workload must be
 | 
			
		||||
installed. In addition, the following Spectre-mitigated libs must be added:
 | 
			
		||||
 | 
			
		||||
- MSVC C++ Spectre-mitigated libs (Latest)
 | 
			
		||||
- C++ ATL for latest build tools with Spectre Mitigations
 | 
			
		||||
- C++ MFC for latest build tools with Spectre Mitigations
 | 
			
		||||
 | 
			
		||||
The easiest way to install is to select "Individual components" and search for
 | 
			
		||||
"spectre latest" (no quotation marks). Pick each option for the relevant CPU.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
1) Set up `depot_tools`.
 | 
			
		||||
 | 
			
		||||
[`depot_tools.zip`](https://storage.googleapis.com/chrome-infra/depot_tools.zip)
 | 
			
		||||
must be downloaded and extracted to `c:\src\depot_tools\`.
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
This ZIP has a number of hidden files and folders (including `.git`) which
 | 
			
		||||
should be extracted along with the normal files.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
Add the path `c:\src\depot_tools\` to the User `PATH` environment variable
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Environment Variable Setup</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
Type `env` in the search bar and select "Edit the system environment variables".
 | 
			
		||||
 | 
			
		||||
In the new window, click the "Environment Variables..." button.
 | 
			
		||||
 | 
			
		||||
In the new window, look for the "User variables" section. Select "Path" in the
 | 
			
		||||
list and click "Edit".
 | 
			
		||||
 | 
			
		||||
In the new window, click "New" and type `c:\src\depot_tools` and press Enter.
 | 
			
		||||
 | 
			
		||||
Select the row and repeatedly click "Move Up" until it is the first entry.
 | 
			
		||||
 | 
			
		||||
Click "OK" in each window (3 windows) and restart your computer.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
2) Delete `c:\src\depot_tools\ninja` if it exists, then download the
 | 
			
		||||
[official Windows release](https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip)
 | 
			
		||||
and move the `ninja.exe` into `c:\src\depot_tools`. If a `ninja.exe` exists in
 | 
			
		||||
the folder, replace the existing program.
 | 
			
		||||
 | 
			
		||||
3) Make a project directory:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
mkdir sheetjs-hermes
 | 
			
		||||
cd sheetjs-hermes
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
4) Clone the `hermes-windows` repo:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
git clone https://github.com/microsoft/hermes-windows
 | 
			
		||||
cd hermes-windows
 | 
			
		||||
git checkout c7a4a82
 | 
			
		||||
cd ..
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
If there are errors related to SSL or certificates or `CApath`, temporarily
 | 
			
		||||
disable SSL in Git:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
git config --global http.sslVerify false
 | 
			
		||||
git clone https://github.com/microsoft/hermes-windows
 | 
			
		||||
git config --global http.sslVerify true
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
5) Build the library:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
cd hermes-windows
 | 
			
		||||
.\.ado\scripts\cibuild.ps1 -AppPlatform win32 -Platform x64 -ToolsPlatform x64
 | 
			
		||||
cd ..
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
The script may fail with the message:
 | 
			
		||||
 | 
			
		||||
> cannot be loaded because running scripts is disabled on this system
 | 
			
		||||
 | 
			
		||||
In a "Run as Administrator" powershell window, run the following command:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
6) Copy every generated `.lib` and `.dll` file into the main folder:
 | 
			
		||||
 | 
			
		||||
```powershell
 | 
			
		||||
dir -r -Path .\hermes-windows\workspace\build\win32-x64-debug\ -Filter "*.dll" | Copy-Item -Destination .\
 | 
			
		||||
dir -r -Path .\hermes-windows\workspace\build\win32-x64-debug\ -Filter "*.lib" | Copy-Item -Destination .\
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
7) Download [`sheetjs-hermes.cpp`](pathname:///hermes/sheetjs-hermesw.cpp):
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -LO https://docs.sheetjs.com/hermes/sheetjs-hermesw.cpp
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
8) Build the application:
 | 
			
		||||
 | 
			
		||||
```powershell
 | 
			
		||||
cl /MDd sheetjs-hermesw.cpp DbgHelp.lib *.lib /I hermes-windows\API /I hermes-windows\include /I hermes-windows\public\ /I hermes-windows\API\jsi
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::caution pass
 | 
			
		||||
 | 
			
		||||
If `cl` is not found, run the command in the "Native Tools Command Prompt"
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
9) Download the SheetJS Standalone script and the test file. Save both files in
 | 
			
		||||
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://sheetjs.com/pres.numbers">pres.numbers</a></li>
 | 
			
		||||
</ul>
 | 
			
		||||
 | 
			
		||||
<CodeBlock language="bash">{`\
 | 
			
		||||
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
 | 
			
		||||
curl -LO https://sheetjs.com/pres.numbers`}
 | 
			
		||||
</CodeBlock>
 | 
			
		||||
 | 
			
		||||
10) Run the application:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
.\sheetjs-hermesw.exe pres.numbers
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If successful, the program will print the library version number and the
 | 
			
		||||
contents of the first sheet as CSV rows.
 | 
			
		||||
 | 
			
		||||
### CLI Test
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
@ -493,4 +676,5 @@ If successful, the script will print CSV data from the test file.
 | 
			
		||||
[^2]: See ["Workbook Object"](/docs/csf/book)
 | 
			
		||||
[^3]: See ["Workbook Object"](/docs/csf/book)
 | 
			
		||||
[^4]: See [`sheet_to_csv` in "Utilities"](/docs/api/utilities/csv#csv-output)
 | 
			
		||||
[^5]: See ["Dependencies" in "Building and Running"](https://hermesengine.dev/docs/building-and-running/#dependencies) in the Hermes Documentation
 | 
			
		||||
[^5]: See [`microsoft/hermes-windows`](https://github.com/microsoft/hermes-windows) on GitHub
 | 
			
		||||
[^6]: See ["Dependencies" in "Building and Running"](https://hermesengine.dev/docs/building-and-running/#dependencies) in the Hermes Documentation
 | 
			
		||||
@ -55,7 +55,7 @@ only be used when there is no safe way to pass `ArrayBuffer` or `Uint8Array`.
 | 
			
		||||
 | 
			
		||||
**Byte Conventions**
 | 
			
		||||
 | 
			
		||||
Java has no native concept of unsigned bytes. Values in a `byte[]` are clamped
 | 
			
		||||
Java has no native concept of unsigned bytes. Values in a `byte[]` are limited
 | 
			
		||||
to the range `-128 .. 127`. They need to be fixed within the JS engine.
 | 
			
		||||
 | 
			
		||||
Some engines support typed arrays. The `Uint8Array` constructor will fix values:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										117
									
								
								docz/static/hermes/sheetjs-hermesw.cpp
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										117
									
								
								docz/static/hermes/sheetjs-hermesw.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,117 @@
 | 
			
		||||
/* sheetjs-hermesw.cpp Copyright (c) SheetJS LLC. */
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include "hermes/hermes.h"
 | 
			
		||||
 | 
			
		||||
static char *read_file(const char *filename, size_t *sz) {
 | 
			
		||||
  FILE *f = fopen(filename, "rb");
 | 
			
		||||
  if(!f) return NULL;
 | 
			
		||||
  long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fseek(f, 0, SEEK_SET); }
 | 
			
		||||
  char *buf = (char *)malloc(fsize * sizeof(char));
 | 
			
		||||
  *sz = fread((void *) buf, 1, fsize, f);
 | 
			
		||||
  fclose(f);
 | 
			
		||||
  return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Hermes-Windows requires the null terminator */
 | 
			
		||||
static char *read_file_null(const char *filename, size_t *sz) {
 | 
			
		||||
  FILE *f = fopen(filename, "rb");
 | 
			
		||||
  if(!f) return NULL;
 | 
			
		||||
  long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f) + 1; fseek(f, 0, SEEK_SET); }
 | 
			
		||||
  char *buf = (char *)malloc(fsize * sizeof(char));
 | 
			
		||||
  *sz = fread((void *) buf, 1, fsize, f);
 | 
			
		||||
  buf[fsize - 1] = 0;
 | 
			
		||||
  fclose(f);
 | 
			
		||||
  return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Unfortunately the library provides no C-friendly Buffer classes */
 | 
			
		||||
class CBuffer : public facebook::jsi::Buffer {
 | 
			
		||||
  public:
 | 
			
		||||
    CBuffer(const uint8_t *data, size_t size) : buf(data), sz(size) {}
 | 
			
		||||
    size_t size() const override { return sz; }
 | 
			
		||||
    const uint8_t *data() const override { return buf; }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    const uint8_t *buf;
 | 
			
		||||
    size_t sz;
 | 
			
		||||
};
 | 
			
		||||
/* ArrayBuffer constructor expects MutableBuffer*/
 | 
			
		||||
class CMutableBuffer : public facebook::jsi::MutableBuffer {
 | 
			
		||||
  public:
 | 
			
		||||
    CMutableBuffer(uint8_t *data, size_t size) : buf(data), sz(size) {}
 | 
			
		||||
    size_t size() const override { return sz; }
 | 
			
		||||
    uint8_t *data() override { return buf; }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    uint8_t *buf;
 | 
			
		||||
    size_t sz;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
  std::unique_ptr<facebook::jsi::Runtime> rt(facebook::hermes::makeHermesRuntime());
 | 
			
		||||
 | 
			
		||||
  /* setup */
 | 
			
		||||
  try {
 | 
			
		||||
    auto src = std::make_shared<facebook::jsi::StringBuffer>(
 | 
			
		||||
      "var global = (function(){ return this; }).call(null);"
 | 
			
		||||
      "var console = { log: function(x) { print(x); } };"
 | 
			
		||||
    );
 | 
			
		||||
    auto js = rt->prepareJavaScript(src, std::string("<eval>"));
 | 
			
		||||
    rt->evaluatePreparedJavaScript(js);
 | 
			
		||||
  } catch (const facebook::jsi::JSIException &e) {
 | 
			
		||||
    std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n';
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* load SheetJS library */
 | 
			
		||||
  try {
 | 
			
		||||
    size_t sz; char *xlsx_full_min_js = read_file_null("xlsx.full.min.js", &sz);
 | 
			
		||||
    auto src = std::make_shared<CBuffer>(CBuffer((uint8_t *)xlsx_full_min_js, sz));
 | 
			
		||||
    auto js = rt->prepareJavaScript(src, std::string("xlsx.full.min.js"));
 | 
			
		||||
    rt->evaluatePreparedJavaScript(js);
 | 
			
		||||
  } catch (const facebook::jsi::JSIException &e) {
 | 
			
		||||
    std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n';
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* print library version */
 | 
			
		||||
  try {
 | 
			
		||||
    auto src = std::make_shared<facebook::jsi::StringBuffer>(
 | 
			
		||||
      "console.log('SheetJS Library Version: ' + XLSX.version)"
 | 
			
		||||
    );
 | 
			
		||||
    auto js = rt->prepareJavaScript(src, std::string("<eval>"));
 | 
			
		||||
    rt->evaluatePreparedJavaScript(js);
 | 
			
		||||
  } catch (const facebook::jsi::JSIException &e) {
 | 
			
		||||
    std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << '\n';
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    /* load payload as ArrayBuffer */
 | 
			
		||||
    size_t sz; char *data = read_file(argv[1], &sz);
 | 
			
		||||
    auto payload = std::make_shared<CMutableBuffer>(CMutableBuffer((uint8_t *)data, sz));
 | 
			
		||||
    auto ab = facebook::jsi::ArrayBuffer(*rt, payload);
 | 
			
		||||
 | 
			
		||||
    /* define stub function to read and convert first sheet to CSV */
 | 
			
		||||
    auto src = std::make_shared<facebook::jsi::StringBuffer>(
 | 
			
		||||
      "(function(buf) {"
 | 
			
		||||
        "var wb = XLSX.read(buf);"
 | 
			
		||||
        "return XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]);"
 | 
			
		||||
      "})"
 | 
			
		||||
    );
 | 
			
		||||
    auto js = rt->prepareJavaScript(src, std::string("<eval>"));
 | 
			
		||||
    auto func = rt->evaluatePreparedJavaScript(js);
 | 
			
		||||
 | 
			
		||||
    /* call stub function and capture result */
 | 
			
		||||
    auto csv = func.asObject(*rt).asFunction(*rt).call(*rt, ab);
 | 
			
		||||
 | 
			
		||||
    /* interpret as utf8 and print to stdout */
 | 
			
		||||
    std::string str = csv.getString(*rt).utf8(*rt);
 | 
			
		||||
    std::cout << str << std::endl;
 | 
			
		||||
  } catch (const facebook::jsi::JSIException &e) {
 | 
			
		||||
    std::cerr << "JavaScript terminated via uncaught exception: " << e.what() << std::endl;
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user