diff --git a/docz/docs/03-demos/12-engines/07_chakra.md b/docz/docs/03-demos/12-engines/07_chakra.md new file mode 100644 index 0000000..45bb1f6 --- /dev/null +++ b/docz/docs/03-demos/12-engines/07_chakra.md @@ -0,0 +1,232 @@ +--- +title: C++ + ChakraCore +pagination_prev: demos/bigdata/index +pagination_next: solutions/input +--- + +ChakraCore is an embeddable JS engine written in C++. + +The [Standalone scripts](/docs/getting-started/installation/standalone) can be +parsed and evaluated in a ChakraCore context. + +## Integration Details + +_Initialize ChakraCore_ + +ChakraCore provides a `global` object through `JsGetGlobalObject`: + +```cpp +/* initialize */ +JsRuntimeHandle runtime; +JsContextRef context; +size_t cookie = 0; +JsCreateRuntime(JsRuntimeAttributeNone, nullptr, &runtime); +JsCreateContext(runtime, &context); +JsSetCurrentContext(context); + +/* obtain reference to global object */ +JsValueRef global; +JsGetGlobalObject(&global); + +/* DO WORK HERE */ + +/* cleanup */ +JsSetCurrentContext(JS_INVALID_REFERENCE); +JsDisposeRuntime(runtime); +``` + +:::note + +Cleanup and validation code is omitted from the discussion. The integration +example shows structured validation and controlled memory usage. + +::: + +_Load SheetJS Scripts_ + +The main library can be loaded by reading the script from the file system and +evaluating in the ChakraCore context: + +```cpp +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; +} + +#define EVAL_FILE(path) {\ + JsValueRef filename; \ + JsValueRef result; \ + JsCreateString(path, strlen(path), &filename); \ + size_t len; const char* script = read_file(path, &len);\ + JsValueRef src;\ + JsCreateExternalArrayBuffer((void*)script, len, nullptr, nullptr, &src);\ + JsRun(src, cookie++, filename, JsParseScriptAttributeNone, &result); \ +} + +// ... + /* load library */ + EVAL_FILE("shim.min.js") + EVAL_FILE("xlsx.full.min.js") +``` + +### Reading Files + +`JsCreateExternalArrayBuffer` can generate an `ArrayBuffer` from a C byte array: + +```cpp +/* read file */ +size_t len; char *buf = read_file(argv[1], &len); + +/* load data into array buffer */ +JsValueRef ab; +JsCreateExternalArrayBuffer((void*)buf, len, nullptr, nullptr, &ab); +``` + +After pushing the data, it is easiest to store properties on `globalThis`: + +```cpp +/* assign to the `buf` global variable */ +JsValueRef buf_str; JsCreateString("buf", strlen("buf"), &buf_str); +JsObjectSetProperty(global, buf_str, ab, true); + +/* call globalThis.wb = XLSX.read(ab) */ +const char* script_str ="globalThis.wb = XLSX.read(buf);" + +JsValueRef script; +JsCreateExternalArrayBuffer((void*)script_str, (size_t)strlen(script_str), nullptr, nullptr, &script); +JsRun(script, cookie++, fname, JsParseScriptAttributeNone, &result); +``` + +## Complete Example + +The "Integration Example" covers a traditional integration in a C application, +while the "CLI Test" demonstrates other concepts using the `ch` CLI tool. + +### Integration Example + +:::note + +This demo was last tested on 2023 April 09 against ChakraCore commit `c3ead3f` +on a Intel Mac. `gcc -v` printed: + +``` +Apple clang version 14.0.0 (clang-1400.0.29.202) +Target: x86_64-apple-darwin21.6.0 +``` + +::: + +0) Build ChakraCore: + +```bash +git clone https://github.com/Microsoft/ChakraCore +cd ChakraCore +git checkout c3ead3f +./build.sh --static --icu=/usr/local/opt/icu4c/include --test-build -j=8 +cd .. +``` + +1) Download the source file and Makefile: + +- [`sheetjs.ch.cpp`](pathname:///chakra/sheetjs.ch.cpp) +- [`Makefile`](pathname:///chakra/Makefile) + +```bash +curl -LO https://docs.sheetjs.com/chakra/sheetjs.ch.c +curl -LO https://docs.sheetjs.com/chakra/Makefile +``` + +2) Build the sample application: + +```bash +make +``` + +This program tries to parse the file specified by the first argument + +4) Download the standalone script, shim script, and test file: + +
+ +```bash +curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js +curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js +curl -LO https://sheetjs.com/pres.numbers +``` + +5) Run the test program: + +``` +./sheetjs.ch pres.numbers +``` + +If successful, the program will print the contents of the first sheet as CSV. + + +### CLI Test + +:::note + +This demo was last tested on 2023 April 09 against `ch` `1.13.0.0-beta`. +The command line tool was built against commit `c3ead3f`. + +::: + +Due to limitations of the `ch` standalone binary, this demo will encode a test +file as a Base64 string and directly add it to an amalgamated script. + +0) Download and extract the ChakraCore release ZIP. Copy the binary (`bin/ch`) +to your project folder. + +1) Download the standalone script, shim, and test file: + + + +2) Bundle the test file and create `payload.js`: + +```bash +node -e "fs.writeFileSync('payload.js', 'var payload = \"' + fs.readFileSync('pres.numbers').toString('base64') + '\";')" +``` + +3) Create support scripts: + +- `global.js` creates a `global` variable: + +```js title="global.js" +var global = (function(){ return this; }).call(null); +``` + +- `chakra.js` will call `XLSX.read` and `XLSX.utils.sheet_to_csv`: + +```js title="chakra.js" +var wb = XLSX.read(payload, {type:'base64'}); +console.log(XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]])); +``` + +4) Create the amalgamation `xlsx.chakra.js`: + +```bash +cat global.js xlsx.full.min.js payload.js chakra.js > xlsx.chakra.js +``` + +The final script defines `global` before loading the standalone library. Once +ready, it will read the bundled test data and print the contents as CSV. + +5) Run the script using the ChakraCore standalone binary: + +``` +./ch xlsx.chakra.js +``` diff --git a/docz/docs/03-demos/12-engines/08_quickjs.md b/docz/docs/03-demos/12-engines/08_quickjs.md index 80faf86..06771e2 100644 --- a/docz/docs/03-demos/12-engines/08_quickjs.md +++ b/docz/docs/03-demos/12-engines/08_quickjs.md @@ -126,7 +126,7 @@ Target: x86_64-apple-darwin21.6.0 0) Build `libquickjs.a`: ```bash -git clone --depth=1 https://github.com/bellard/quickjs +git clone https://github.com/bellard/quickjs cd quickjs git checkout 2788d71 make diff --git a/docz/docs/03-demos/12-engines/index.md b/docz/docs/03-demos/12-engines/index.md index b0b2e7f..e9dd687 100644 --- a/docz/docs/03-demos/12-engines/index.md +++ b/docz/docs/03-demos/12-engines/index.md @@ -57,6 +57,12 @@ only be used when there is no safe way to pass `ArrayBuffer` or `Uint8Array`. This list is sorted in alphabetical order. +### ChakraCore + +ChakraCore is an embeddable JS engine written in C++. + +This demo has been moved [to a dedicated page](/docs/demos/engines/chakra). + ### Duktape Duktape is an embeddable JS engine written in C. It has been ported to a number @@ -261,82 +267,3 @@ This demo has been moved [to a dedicated page](/docs/demos/engines/quickjs). Rhino is an ES3+ engine in Java. This demo has been moved [to a dedicated page](/docs/demos/engines/rhino). - -### ChakraCore - -:::caution - -ChakraCore was an open source JavaScript engine released by Microsoft. It was a -fork of the Chakra engine that powered Internet Explorer. When Microsoft Edge -switched to become a fork of Chromium, Microsoft stopped providing support. - -::: - -ChakraCore is an embeddable JS engine written in C++. The library and binary -distributions include a command-line tool `chakra` for running JS scripts. - -The simplest way to interact with the engine is to pass Base64 strings. The make -target builds a very simple payload with the data. - -:::note - -The official release includes the `ch` standalone binary. While applications -should link against the official libraries, the standalone tool is useful for -verifying functionality. - -::: - -