embedded-react 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,110 +1,110 @@
1
- /*
2
- * Copyright 2026 Cory Lamming
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
-
17
- // `npm run aot:smoke` — automated compile-and-screenshot smoke test for the Flow B (AOT) demos.
18
- //
19
- // For each demo it: (1) compiles App.jsx → dist/app.gen.{c,h} (`node aot/compile.mjs`), (2) rebuilds the
20
- // linux-aot SDL host (which links the generated C), (3) runs it headless via ER_AOT_SHOT to render ONE
21
- // frame to a BMP, and (4) checks the image actually has content (distinct colours above a floor) — i.e. it
22
- // compiled, linked, and rendered something rather than crashing or drawing a blank screen. Exits non-zero
23
- // if any demo fails, so it can gate CI.
24
- //
25
- // Prereq: the linux-aot CMake build must be configurable (SDL2 found). It reuses examples/linux-aot/build;
26
- // if that isn't configured yet, set CMAKE_TOOLCHAIN_FILE (e.g. a vcpkg toolchain) and it will configure it.
27
- // Needs a display (SDL video); on a headless box run under a virtual framebuffer.
28
- import { execFileSync } from 'node:child_process';
29
- import { existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';
30
- import { resolve, dirname } from 'node:path';
31
- import { fileURLToPath } from 'node:url';
32
-
33
- const here = dirname(fileURLToPath(import.meta.url)); // bridges/quickjs/js/aot
34
- const jsDir = resolve(here, '..'); // bridges/quickjs/js
35
- const repoRoot = resolve(here, '../../../..');
36
- const exampleDir = resolve(repoRoot, 'examples/linux-aot');
37
- const buildDir = resolve(exampleDir, 'build');
38
- const exe = resolve(buildDir, process.platform === 'win32' ? 'embedded-react-desktop-aot.exe' : 'embedded-react-desktop-aot');
39
- const tmpDir = resolve(jsDir, 'dist', '.smoke');
40
-
41
- // Demos to smoke-test. `screen` (optional) sets ER_AOT_SCREEN_W/H so the responsive thermostat folds to its
42
- // compact (AOT-compilable) branch. `minColors` is the floor of distinct sampled colours for "rendered".
43
- const DEMOS = [
44
- { name: 'music-player', minColors: 40 },
45
- { name: 'thermostat', screen: { w: 240, h: 320 }, minColors: 40 },
46
- ];
47
-
48
- /** Counts distinct colours in an uncompressed 24/32-bpp BMP (sampled) — a quick "is anything drawn?" signal. */
49
- function bmpDistinctColors(path, step = 4) {
50
- const b = readFileSync(path);
51
- if (b[0] !== 0x42 || b[1] !== 0x4d) throw new Error(`not a BMP: ${path}`);
52
- const off = b.readUInt32LE(10);
53
- const w = b.readInt32LE(18);
54
- const h = Math.abs(b.readInt32LE(22));
55
- const bpp = b.readUInt16LE(28);
56
- if (bpp !== 24 && bpp !== 32) throw new Error(`unexpected BMP bpp ${bpp}`);
57
- const bytesPP = bpp / 8;
58
- const rowSize = Math.floor((bpp * w + 31) / 32) * 4; // rows padded to 4 bytes
59
- const colors = new Set();
60
- for (let y = 0; y < h; y += step) {
61
- for (let x = 0; x < w; x += step) {
62
- const p = off + y * rowSize + x * bytesPP;
63
- colors.add((b[p] << 16) | (b[p + 1] << 8) | b[p + 2]); // BGR triplet
64
- }
65
- }
66
- return colors.size;
67
- }
68
-
69
- function run(cmd, args, opts = {}) {
70
- execFileSync(cmd, args, { stdio: 'pipe', ...opts });
71
- }
72
-
73
- function ensureConfigured() {
74
- if (existsSync(resolve(buildDir, 'CMakeCache.txt'))) return;
75
- console.log('• configuring linux-aot build (first run)…');
76
- const args = ['-S', exampleDir, '-B', buildDir];
77
- if (process.env.CMAKE_TOOLCHAIN_FILE) args.push(`-DCMAKE_TOOLCHAIN_FILE=${process.env.CMAKE_TOOLCHAIN_FILE}`);
78
- if (process.platform === 'win32') args.push('-G', 'MinGW Makefiles');
79
- run('cmake', args);
80
- }
81
-
82
- let failures = 0;
83
- mkdirSync(tmpDir, { recursive: true });
84
- ensureConfigured();
85
-
86
- for (const demo of DEMOS) {
87
- const shot = resolve(tmpDir, `${demo.name}.bmp`);
88
- try {
89
- rmSync(shot, { force: true });
90
- const genEnv = { ...process.env };
91
- if (demo.screen) {
92
- genEnv.ER_AOT_SCREEN_W = String(demo.screen.w);
93
- genEnv.ER_AOT_SCREEN_H = String(demo.screen.h);
94
- }
95
- run('node', [resolve(here, 'compile.mjs'), demo.name], { cwd: jsDir, env: genEnv }); // → dist/app.gen.{c,h}
96
- run('cmake', ['--build', buildDir]); // relink the generated C
97
- run(exe, [], { cwd: buildDir, env: { ...process.env, ER_AOT_SHOT: shot } }); // render one frame → BMP
98
-
99
- if (!existsSync(shot)) throw new Error('no screenshot written (host crashed before present?)');
100
- const colors = bmpDistinctColors(shot);
101
- if (colors < demo.minColors) throw new Error(`screenshot looks blank (${colors} distinct colours < ${demo.minColors})`);
102
- console.log(`✓ ${demo.name}: rendered (${colors} distinct colours)`);
103
- } catch (e) {
104
- failures++;
105
- console.error(`✗ ${demo.name}: ${e.message?.split('\n')[0] || e}`);
106
- }
107
- }
108
-
109
- console.log(failures ? `\n${failures} demo(s) failed the smoke test.` : `\nAll ${DEMOS.length} demos compiled, built, and rendered.`);
110
- process.exit(failures ? 1 : 0);
1
+ /*
2
+ * Copyright 2026 Cory Lamming
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ // `npm run aot:smoke` — automated compile-and-screenshot smoke test for the Flow B (AOT) demos.
18
+ //
19
+ // For each demo it: (1) compiles App.jsx → dist/app.gen.{c,h} (`node aot/compile.mjs`), (2) rebuilds the
20
+ // linux-aot SDL host (which links the generated C), (3) runs it headless via ER_AOT_SHOT to render ONE
21
+ // frame to a BMP, and (4) checks the image actually has content (distinct colours above a floor) — i.e. it
22
+ // compiled, linked, and rendered something rather than crashing or drawing a blank screen. Exits non-zero
23
+ // if any demo fails, so it can gate CI.
24
+ //
25
+ // Prereq: the linux-aot CMake build must be configurable (SDL2 found). It reuses examples/linux-aot/build;
26
+ // if that isn't configured yet, set CMAKE_TOOLCHAIN_FILE (e.g. a vcpkg toolchain) and it will configure it.
27
+ // Needs a display (SDL video); on a headless box run under a virtual framebuffer.
28
+ import { execFileSync } from 'node:child_process';
29
+ import { existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';
30
+ import { resolve, dirname } from 'node:path';
31
+ import { fileURLToPath } from 'node:url';
32
+
33
+ const here = dirname(fileURLToPath(import.meta.url)); // bridges/quickjs/js/aot
34
+ const jsDir = resolve(here, '..'); // bridges/quickjs/js
35
+ const repoRoot = resolve(here, '../../../..');
36
+ const exampleDir = resolve(repoRoot, 'examples/linux-aot');
37
+ const buildDir = resolve(exampleDir, 'build');
38
+ const exe = resolve(buildDir, process.platform === 'win32' ? 'embedded-react-desktop-aot.exe' : 'embedded-react-desktop-aot');
39
+ const tmpDir = resolve(jsDir, 'dist', '.smoke');
40
+
41
+ // Demos to smoke-test. `screen` (optional) sets ER_AOT_SCREEN_W/H so the responsive thermostat folds to its
42
+ // compact (AOT-compilable) branch. `minColors` is the floor of distinct sampled colours for "rendered".
43
+ const DEMOS = [
44
+ { name: 'music-player', minColors: 40 },
45
+ { name: 'thermostat', screen: { w: 240, h: 320 }, minColors: 40 },
46
+ ];
47
+
48
+ /** Counts distinct colours in an uncompressed 24/32-bpp BMP (sampled) — a quick "is anything drawn?" signal. */
49
+ function bmpDistinctColors(path, step = 4) {
50
+ const b = readFileSync(path);
51
+ if (b[0] !== 0x42 || b[1] !== 0x4d) throw new Error(`not a BMP: ${path}`);
52
+ const off = b.readUInt32LE(10);
53
+ const w = b.readInt32LE(18);
54
+ const h = Math.abs(b.readInt32LE(22));
55
+ const bpp = b.readUInt16LE(28);
56
+ if (bpp !== 24 && bpp !== 32) throw new Error(`unexpected BMP bpp ${bpp}`);
57
+ const bytesPP = bpp / 8;
58
+ const rowSize = Math.floor((bpp * w + 31) / 32) * 4; // rows padded to 4 bytes
59
+ const colors = new Set();
60
+ for (let y = 0; y < h; y += step) {
61
+ for (let x = 0; x < w; x += step) {
62
+ const p = off + y * rowSize + x * bytesPP;
63
+ colors.add((b[p] << 16) | (b[p + 1] << 8) | b[p + 2]); // BGR triplet
64
+ }
65
+ }
66
+ return colors.size;
67
+ }
68
+
69
+ function run(cmd, args, opts = {}) {
70
+ execFileSync(cmd, args, { stdio: 'pipe', ...opts });
71
+ }
72
+
73
+ function ensureConfigured() {
74
+ if (existsSync(resolve(buildDir, 'CMakeCache.txt'))) return;
75
+ console.log('• configuring linux-aot build (first run)…');
76
+ const args = ['-S', exampleDir, '-B', buildDir];
77
+ if (process.env.CMAKE_TOOLCHAIN_FILE) args.push(`-DCMAKE_TOOLCHAIN_FILE=${process.env.CMAKE_TOOLCHAIN_FILE}`);
78
+ if (process.platform === 'win32') args.push('-G', 'MinGW Makefiles');
79
+ run('cmake', args);
80
+ }
81
+
82
+ let failures = 0;
83
+ mkdirSync(tmpDir, { recursive: true });
84
+ ensureConfigured();
85
+
86
+ for (const demo of DEMOS) {
87
+ const shot = resolve(tmpDir, `${demo.name}.bmp`);
88
+ try {
89
+ rmSync(shot, { force: true });
90
+ const genEnv = { ...process.env };
91
+ if (demo.screen) {
92
+ genEnv.ER_AOT_SCREEN_W = String(demo.screen.w);
93
+ genEnv.ER_AOT_SCREEN_H = String(demo.screen.h);
94
+ }
95
+ run('node', [resolve(here, 'compile.mjs'), demo.name], { cwd: jsDir, env: genEnv }); // → dist/app.gen.{c,h}
96
+ run('cmake', ['--build', buildDir]); // relink the generated C
97
+ run(exe, [], { cwd: buildDir, env: { ...process.env, ER_AOT_SHOT: shot } }); // render one frame → BMP
98
+
99
+ if (!existsSync(shot)) throw new Error('no screenshot written (host crashed before present?)');
100
+ const colors = bmpDistinctColors(shot);
101
+ if (colors < demo.minColors) throw new Error(`screenshot looks blank (${colors} distinct colours < ${demo.minColors})`);
102
+ console.log(`✓ ${demo.name}: rendered (${colors} distinct colours)`);
103
+ } catch (e) {
104
+ failures++;
105
+ console.error(`✗ ${demo.name}: ${e.message?.split('\n')[0] || e}`);
106
+ }
107
+ }
108
+
109
+ console.log(failures ? `\n${failures} demo(s) failed the smoke test.` : `\nAll ${DEMOS.length} demos compiled, built, and rendered.`);
110
+ process.exit(failures ? 1 : 0);
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- // ERPK — a binary asset pack for the simulator's runtime loader (see /SIMULATOR.md, Phase 2b).
17
+ // ERPK — a binary asset pack for the simulator's runtime loader (see tools/simulator/README.md).
18
18
  //
19
19
  // Produced from the SAME JS bakers (bake-image.mjs / bake-font.mjs) as the device's baked C, so the
20
20
  // simulator renders pixel-identical images and fonts. The sim host (tools/simulator/asset_pack.c)
package/cli.mjs ADDED
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Copyright 2026 Cory Lamming
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ // embedded-react — the consumer CLI.
19
+ //
20
+ // npx embedded-react dev [entry] [--port 3333]
21
+ //
22
+ // Runs the WASM simulator against the app in your current project: bundles your JSX, serves the prebuilt
23
+ // embedded-react.wasm host page, and hot-reloads on save (useState preserved). No native toolchain — the
24
+ // .wasm ships prebuilt in this package. See tools/web-sim/README.md.
25
+
26
+ import { copyFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
27
+ import { fileURLToPath } from 'node:url';
28
+ import { dirname, relative, resolve } from 'node:path';
29
+ import { tmpdir } from 'node:os';
30
+ import { buildApp, runDevServer } from './sim-server.mjs';
31
+
32
+ const PKG_ROOT = dirname(fileURLToPath(import.meta.url));
33
+
34
+ function usage() {
35
+ console.log(`embedded-react — React Native for embedded MCUs
36
+
37
+ Usage:
38
+ embedded-react dev [entry] [--port <n>] Run the WASM simulator with hot reload
39
+ embedded-react export [entry] [--out <dir>] Build a self-contained static playground (no server)
40
+
41
+ entry App entry file. Defaults to ./index.jsx, ./src/index.jsx, or package.json "main".
42
+ `);
43
+ }
44
+
45
+ /** Locate the package's prebuilt simulator assets (the .wasm ships with this package). */
46
+ function simDirOrExit() {
47
+ const simDir = resolve(PKG_ROOT, 'sim');
48
+ if (!existsSync(resolve(simDir, 'embedded-react.wasm'))) {
49
+ console.error('The prebuilt simulator (sim/embedded-react.wasm) is missing from this install.');
50
+ console.error('A published embedded-react package ships it; building from source needs the Emscripten SDK.');
51
+ process.exit(1);
52
+ }
53
+ return simDir;
54
+ }
55
+
56
+ const libSrc = () => resolve(PKG_ROOT, 'src/embedded-react/index.js');
57
+ const nodePaths = (cwd) => [resolve(PKG_ROOT, 'node_modules'), resolve(cwd, 'node_modules')];
58
+
59
+ /** Resolve the app entry: an explicit arg, else common conventions, else package.json "main"/"source". */
60
+ function resolveEntry(cwd, explicit) {
61
+ if (explicit) {
62
+ const p = resolve(cwd, explicit);
63
+ if (!existsSync(p)) {
64
+ console.error(`Entry not found: ${p}`);
65
+ process.exit(1);
66
+ }
67
+ return p;
68
+ }
69
+ for (const rel of ['index.jsx', 'src/index.jsx', 'index.tsx', 'src/index.tsx', 'App.jsx', 'src/App.jsx']) {
70
+ const p = resolve(cwd, rel);
71
+ if (existsSync(p)) return p;
72
+ }
73
+ const pkgPath = resolve(cwd, 'package.json');
74
+ if (existsSync(pkgPath)) {
75
+ try {
76
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
77
+ for (const field of [pkg.source, pkg.main]) {
78
+ if (field) {
79
+ const p = resolve(cwd, field);
80
+ if (existsSync(p)) return p;
81
+ }
82
+ }
83
+ } catch {
84
+ /* ignore */
85
+ }
86
+ }
87
+ console.error('No app entry found. Pass one explicitly: embedded-react dev <entry.jsx>');
88
+ console.error('(looked for ./index.jsx, ./src/index.jsx, … and package.json "main")');
89
+ process.exit(1);
90
+ }
91
+
92
+ async function dev(args) {
93
+ const cwd = process.cwd();
94
+ const portIdx = args.indexOf('--port');
95
+ const port = portIdx >= 0 ? parseInt(args[portIdx + 1], 10) : 3333;
96
+ const explicit = args.find((a, i) => !a.startsWith('--') && (portIdx < 0 || i !== portIdx + 1));
97
+
98
+ const simDir = simDirOrExit();
99
+ const entry = resolveEntry(cwd, explicit);
100
+ const outDir = resolve(tmpdir(), 'embedded-react-sim');
101
+ mkdirSync(outDir, { recursive: true });
102
+
103
+ await runDevServer({
104
+ entry,
105
+ projectRoot: cwd,
106
+ libSrc: libSrc(),
107
+ nodePaths: nodePaths(cwd),
108
+ indexHtml: resolve(simDir, 'index.html'),
109
+ simDir,
110
+ outDir,
111
+ port,
112
+ label: entry,
113
+ });
114
+ }
115
+
116
+ async function exportApp(args) {
117
+ const cwd = process.cwd();
118
+ const outIdx = args.indexOf('--out');
119
+ const outDir = resolve(cwd, outIdx >= 0 ? args[outIdx + 1] : 'sim-export');
120
+ const explicit = args.find((a, i) => !a.startsWith('--') && (outIdx < 0 || i !== outIdx + 1));
121
+
122
+ const simDir = simDirOrExit();
123
+ const entry = resolveEntry(cwd, explicit);
124
+ const pub = resolve(outDir, 'public');
125
+ mkdirSync(pub, { recursive: true });
126
+
127
+ // Bundle the app + bake assets into public/, then drop the prebuilt module + host page alongside.
128
+ await buildApp({ entry, projectRoot: cwd, libSrc: libSrc(), nodePaths: nodePaths(cwd), outDir: pub });
129
+ for (const f of ['embedded-react.js', 'embedded-react.wasm']) copyFileSync(resolve(simDir, f), resolve(pub, f));
130
+ copyFileSync(resolve(simDir, 'index.html'), resolve(outDir, 'index.html'));
131
+
132
+ console.log(`✓ exported a static playground → ${relative(cwd, outDir) || '.'}/`);
133
+ console.log(` serve it over http (e.g. \`npx serve ${relative(cwd, outDir) || '.'}\`) or deploy the folder to any static host.`);
134
+ }
135
+
136
+ const [cmd, ...rest] = process.argv.slice(2);
137
+ if (cmd === 'dev') {
138
+ await dev(rest);
139
+ } else if (cmd === 'export') {
140
+ await exportApp(rest);
141
+ } else if (!cmd || cmd === '--help' || cmd === '-h' || cmd === 'help') {
142
+ usage();
143
+ } else {
144
+ console.error(`Unknown command: ${cmd}\n`);
145
+ usage();
146
+ process.exit(1);
147
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "embedded-react",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "React Native-style component package + reconciler that drives the embedded-react C engine through the QuickJS NativeUI bridge (Flow A).",
6
6
  "license": "Apache-2.0",
@@ -34,6 +34,9 @@
34
34
  "exports": {
35
35
  ".": "./src/embedded-react/index.js"
36
36
  },
37
+ "bin": {
38
+ "embedded-react": "cli.mjs"
39
+ },
37
40
  "files": [
38
41
  "src/",
39
42
  "aot/",
@@ -41,6 +44,9 @@
41
44
  "build.mjs",
42
45
  "pack-container.mjs",
43
46
  "persist-transform.mjs",
47
+ "cli.mjs",
48
+ "sim-server.mjs",
49
+ "sim/",
44
50
  "README.md",
45
51
  "LICENSE",
46
52
  "NOTICE",
@@ -58,6 +64,7 @@
58
64
  "release": "node ../../../tools/release.mjs",
59
65
  "build:builtin-font": "node assets/build-builtin-font.mjs",
60
66
  "sim": "node sim.mjs",
67
+ "dev": "node cli.mjs dev",
61
68
  "create": "node create-embedded-react.mjs",
62
69
  "test": "vitest run",
63
70
  "test:watch": "vitest",
@@ -65,15 +72,18 @@
65
72
  "test:bytecode": "node test/runtime/run.mjs --bytecode"
66
73
  },
67
74
  "dependencies": {
68
- "react": "18.3.1",
69
- "react-reconciler": "0.29.2"
70
- },
71
- "devDependencies": {
72
75
  "@babel/core": "^7.29.7",
73
76
  "@babel/plugin-syntax-jsx": "^7.29.7",
74
- "esbuild": "^0.24.0",
77
+ "esbuild": "^0.28.1",
75
78
  "opentype.js": "^2.0.0",
76
79
  "pngjs": "^7.0.0",
77
- "vitest": "^2.1.0"
80
+ "react": "18.3.1",
81
+ "react-reconciler": "0.29.2"
82
+ },
83
+ "devDependencies": {
84
+ "vitest": "^3.2.4"
85
+ },
86
+ "overrides": {
87
+ "esbuild": "^0.28.1"
78
88
  }
79
89
  }
@@ -15,7 +15,7 @@
15
15
  */
16
16
 
17
17
  // Simulator-only Babel transform: rewrites `useState(init)` in app code to a persisting helper so
18
- // state transparently survives a hot reload (see /SIMULATOR.md, Phase 3 — transparent variant). Plain
18
+ // state transparently survives a hot reload (see tools/simulator/README.md). Plain
19
19
  // `useState` from 'react' just persists in the simulator; on a device (no transform, no __erPersist)
20
20
  // it's exactly useState. Only the app's own files are transformed — never the library or React (so
21
21
  // the helper itself isn't rewritten).
@@ -0,0 +1,2 @@
1
+ var createEmbeddedReact=(()=>{var _scriptName=typeof document!="undefined"?document.currentScript?.src:undefined;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var arguments_=[];var thisProgram="./this.program";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{readAsync=async url=>{var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var readyPromiseResolve,readyPromiseReject;var wasmMemory;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["k"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}var runDependencies=0;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("embedded-react.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){return{a:wasmImports}}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["j"];updateMemoryViews();assignWasmExports(wasmExports);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(mod,inst)=>{resolve(receiveInstance(mod,inst))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var __abort_js=()=>abort("");var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var ydayFromDate=date=>{var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday};var INT53_MAX=9007199254740992;var INT53_MIN=-9007199254740992;var bigintToI53Checked=num=>num<INT53_MIN||num>INT53_MAX?NaN:Number(num);function __localtime_js(time,tmPtr){time=bigintToI53Checked(time);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.codePointAt(i);if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);if(summerOffset<winterOffset){stringToUTF8(winterName,std_name,17);stringToUTF8(summerName,dst_name,17)}else{stringToUTF8(winterName,dst_name,17);stringToUTF8(summerName,std_name,17)}};var _emscripten_get_now=()=>performance.now();var _emscripten_date_now=()=>Date.now();var nowIsMonotonic=1;var checkWasiClock=clock_id=>clock_id>=0&&clock_id<=3;function _clock_time_get(clk_id,ignored_precision,ptime){ignored_precision=bigintToI53Checked(ignored_precision);if(!checkWasiClock(clk_id)){return 28}var now;if(clk_id===0){now=_emscripten_date_now()}else if(nowIsMonotonic){now=_emscripten_get_now()}else{return 52}var nsec=Math.round(now*1e3*1e3);HEAP64[ptime>>3]=BigInt(nsec);return 0}var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var _fd_close=fd=>52;function _fd_seek(fd,offset,whence,newOffset){offset=bigintToI53Checked(offset);return 70}var printCharBuffers=[null,[],[]];var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str};var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer));buffer.length=0}else{buffer.push(curr)}};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j<len;j++){printChar(fd,HEAPU8[ptr+j])}num+=len}HEAPU32[pnum>>2]=num;return 0};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var lengthBytesUTF8=str=>{var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func(...cArgs);function onDone(ret){if(stack!==0)stackRestore(stack);return convertReturnValue(ret)}ret=onDone(ret);return ret};var cwrap=(ident,returnType,argTypes,opts)=>{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"]}Module["ccall"]=ccall;Module["cwrap"]=cwrap;var _malloc,_free,_er_web_init,_er_web_load_source,_er_web_load_pack,_er_web_demo_scene,_er_web_resize,_er_web_pump,_er_web_touch,_er_web_reset,_er_web_framebuffer,_er_web_fb_width,_er_web_fb_height,__emscripten_stack_restore,__emscripten_stack_alloc,_emscripten_stack_get_current;function assignWasmExports(wasmExports){Module["_malloc"]=_malloc=wasmExports["l"];Module["_free"]=_free=wasmExports["m"];Module["_er_web_init"]=_er_web_init=wasmExports["n"];Module["_er_web_load_source"]=_er_web_load_source=wasmExports["o"];Module["_er_web_load_pack"]=_er_web_load_pack=wasmExports["p"];Module["_er_web_demo_scene"]=_er_web_demo_scene=wasmExports["q"];Module["_er_web_resize"]=_er_web_resize=wasmExports["r"];Module["_er_web_pump"]=_er_web_pump=wasmExports["s"];Module["_er_web_touch"]=_er_web_touch=wasmExports["t"];Module["_er_web_reset"]=_er_web_reset=wasmExports["u"];Module["_er_web_framebuffer"]=_er_web_framebuffer=wasmExports["v"];Module["_er_web_fb_width"]=_er_web_fb_width=wasmExports["w"];Module["_er_web_fb_height"]=_er_web_fb_height=wasmExports["x"];__emscripten_stack_restore=wasmExports["y"];__emscripten_stack_alloc=wasmExports["z"];_emscripten_stack_get_current=wasmExports["A"]}var wasmImports={i:__abort_js,e:__localtime_js,f:__tzset_js,h:_clock_time_get,g:_emscripten_date_now,b:_emscripten_resize_heap,d:_fd_close,c:_fd_seek,a:_fd_write};var wasmExports=await createWasm();function run(){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}function preInit(){if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}preInit();run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})}
2
+ ;return moduleRtn}})();if(typeof exports==="object"&&typeof module==="object"){module.exports=createEmbeddedReact;module.exports.default=createEmbeddedReact}else if(typeof define==="function"&&define["amd"])define([],()=>createEmbeddedReact);
Binary file