forked from sheetjs/docs.sheetjs.com
		
	chakra
This commit is contained in:
		
							parent
							
								
									76543faea9
								
							
						
					
					
						commit
						5b755a1370
					
				
							
								
								
									
										232
									
								
								docz/docs/03-demos/12-engines/07_chakra.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										232
									
								
								docz/docs/03-demos/12-engines/07_chakra.md
									
									
									
									
									
										Normal file
									
								
							| @ -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: | ||||
| 
 | ||||
| <ul> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js`}>shim.min.js</a></li> | ||||
| <li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li> | ||||
| </ul> | ||||
| 
 | ||||
| ```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: | ||||
| 
 | ||||
| <ul> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js`}>shim.min.js</a></li> | ||||
| <li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li> | ||||
| </ul> | ||||
| 
 | ||||
| 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 | ||||
| ``` | ||||
| @ -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 | ||||
|  | ||||
| @ -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. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| <details><summary><b>Complete Example</b> (click to show)</summary> | ||||
| 
 | ||||
| Due to limitations of the 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: | ||||
| 
 | ||||
| <ul> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li> | ||||
| <li><a href={`https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js`}>shim.min.js</a></li> | ||||
| <li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li> | ||||
| </ul> | ||||
| 
 | ||||
| 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" | ||||
| /* sheetjs (C) 2013-present  SheetJS -- https://sheetjs.com */ | ||||
| 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 | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
|  | ||||
| @ -142,7 +142,7 @@ const config = { | ||||
|       prism: { | ||||
|         theme: lightCodeTheme, | ||||
|         darkTheme: darkCodeTheme, | ||||
|         additionalLanguages: [ "swift", "java", "csharp", "perl", "ruby" ], | ||||
|         additionalLanguages: [ "swift", "java", "csharp", "perl", "ruby", "cpp" ], | ||||
|       }, | ||||
|       liveCodeBlock: { | ||||
|         playgroundPosition: 'top' | ||||
|  | ||||
							
								
								
									
										13
									
								
								docz/static/chakra/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										13
									
								
								docz/static/chakra/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| CC=g++ | ||||
| CHAKRALIB=ChakraCore/out/Test/lib/libChakraCoreStatic.a | ||||
| ICU4C=/usr/local/opt/icu4c/lib | ||||
| ICULIB=$(ICU4C)/libicudata.a $(ICU4C)/libicuuc.a $(ICU4C)/libicui18n.a | ||||
| 
 | ||||
| CFLAGS=-lstdc++ -std=c++11 -IChakraCore/lib/Jsrt | ||||
| 
 | ||||
| sheetjs.ch: sheetjs.ch.cpp | ||||
| 	g++ $< $(CFLAGS) -Wl,-force_load $(CHAKRALIB) $(ICULIB) -framework CoreFoundation -framework Security -lm -ldl -Wno-c++11-compat-deprecated-writable-strings -Wno-deprecated-declarations -Wno-unknown-warning-option -o $@  | ||||
| 
 | ||||
| .PHONY: clean | ||||
| clean: | ||||
| 	rm sheetjs.ch | ||||
							
								
								
									
										89
									
								
								docz/static/chakra/sheetjs.ch.cpp
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										89
									
								
								docz/static/chakra/sheetjs.ch.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | ||||
| /* this sample is based off of the official ChakraCore examples */ | ||||
| #include "ChakraCore.h" | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string> | ||||
| #include <cstring> | ||||
| 
 | ||||
| #define FAIL_CHECK(cmd) \ | ||||
|   do { \ | ||||
|     JsErrorCode errCode = cmd; \ | ||||
|     if (errCode != JsNoError) { \ | ||||
|       printf("Error %d at '%s'\n", errCode, #cmd); \ | ||||
|       return 1; \ | ||||
|     } \ | ||||
|   } while(0) | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| 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; \ | ||||
|   FAIL_CHECK(JsCreateString(path, strlen(path), &filename)); \ | ||||
|   size_t len; const char* script = read_file(path, &len);\ | ||||
|   JsValueRef src;\ | ||||
|   FAIL_CHECK(JsCreateExternalArrayBuffer((void*)script, len, nullptr, nullptr, &src));\ | ||||
|   FAIL_CHECK(JsRun(src, cookie++, filename, JsParseScriptAttributeNone, &result)); \ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main(int argc, char *argv[]) { | ||||
|   JsRuntimeHandle runtime; | ||||
|   JsContextRef context; | ||||
|   JsValueRef result; | ||||
|   size_t cookie = 0; | ||||
| 
 | ||||
|   FAIL_CHECK(JsCreateRuntime(JsRuntimeAttributeNone, nullptr, &runtime)); | ||||
|   FAIL_CHECK(JsCreateContext(runtime, &context)); | ||||
|   FAIL_CHECK(JsSetCurrentContext(context)); | ||||
| 
 | ||||
|   JsValueRef global; | ||||
|   FAIL_CHECK(JsGetGlobalObject(&global)); | ||||
| 
 | ||||
|   EVAL_FILE("shim.min.js") | ||||
| 
 | ||||
|   EVAL_FILE("xlsx.full.min.js") | ||||
| 
 | ||||
|   JsValueRef buf_str; | ||||
|   FAIL_CHECK(JsCreateString("buf", strlen("buf"), &buf_str)); | ||||
| 
 | ||||
|   size_t len; char *buf = read_file(argv[1], &len); | ||||
|   JsValueRef ab; | ||||
|   FAIL_CHECK(JsCreateExternalArrayBuffer((void*)buf, len, nullptr, nullptr, &ab)); | ||||
|   FAIL_CHECK(JsObjectSetProperty(global, buf_str, ab, true)); | ||||
| 
 | ||||
|   JsValueRef fname; | ||||
|   FAIL_CHECK(JsCreateString("<script>", strlen("<script>"), &fname)); | ||||
| 
 | ||||
|   const char* script_str = | ||||
|     "var wb = XLSX.read(buf);" | ||||
|     "var ws = wb.Sheets[wb.SheetNames[0]];" | ||||
|     "XLSX.utils.sheet_to_csv(ws);"; | ||||
| 
 | ||||
|   JsValueRef script; | ||||
|   FAIL_CHECK(JsCreateExternalArrayBuffer((void*)script_str, (size_t)strlen(script_str), nullptr, nullptr, &script)); | ||||
|   FAIL_CHECK(JsRun(script, cookie++, fname, JsParseScriptAttributeNone, &result)); | ||||
| 
 | ||||
|   free(buf); | ||||
|   FAIL_CHECK(JsCopyString(result, nullptr, 0, &len)); | ||||
|   buf = (char*)malloc(len + 1); | ||||
|   FAIL_CHECK(JsCopyString(result, buf, len + 1, nullptr)); | ||||
|   buf[len] = 0; | ||||
| 
 | ||||
|   printf("%s\n", buf); | ||||
|   free(buf); | ||||
| 
 | ||||
|   FAIL_CHECK(JsSetCurrentContext(JS_INVALID_REFERENCE)); | ||||
|   FAIL_CHECK(JsDisposeRuntime(runtime)); | ||||
|   return 0; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user