summaryrefslogtreecommitdiff
path: root/themes
diff options
context:
space:
mode:
Diffstat (limited to 'themes')
-rw-r--r--themes/.gitignore15
-rw-r--r--themes/Makefile44
-rw-r--r--themes/README.md58
-rw-r--r--themes/compile_commands.json127
-rwxr-xr-xthemes/compile_commands.sh7
-rw-r--r--themes/dist/output.js1669
-rwxr-xr-xthemes/dist/output.wasmbin157180 -> 101714 bytes
-rw-r--r--themes/emscripten.ini14
-rw-r--r--themes/meson.build122
-rw-r--r--themes/src/_shaders/sun.frag40
-rw-r--r--themes/src/_shaders/sun.vert27
-rw-r--r--themes/src/autumn/autumn_theme.cpp (renamed from themes/src/autumn/AutumnTheme.cpp)2
-rw-r--r--themes/src/autumn/autumn_theme.hpp (renamed from themes/src/autumn/AutumnTheme.hpp)6
-rw-r--r--themes/src/autumn/leaf_particle_render.cpp (renamed from themes/src/autumn/LeafParticleRender.cpp)6
-rw-r--r--themes/src/autumn/leaf_particle_render.h (renamed from themes/src/autumn/LeafParticleRender.h)2
-rw-r--r--themes/src/autumn/tree_shape.cpp (renamed from themes/src/autumn/TreeShape.cpp)2
-rw-r--r--themes/src/autumn/tree_shape.h (renamed from themes/src/autumn/TreeShape.h)2
-rw-r--r--themes/src/list.h2
-rw-r--r--themes/src/logger.cpp (renamed from themes/src/Logger.cpp)2
-rw-r--r--themes/src/logger.h (renamed from themes/src/Logger.h)0
-rw-r--r--themes/src/main.cpp21
-rw-r--r--themes/src/main_loop.cpp (renamed from themes/src/MainLoop.cpp)2
-rw-r--r--themes/src/main_loop.h (renamed from themes/src/MainLoop.h)2
-rw-r--r--themes/src/renderer_2d.cpp (renamed from themes/src/Renderer2d.cpp)6
-rw-r--r--themes/src/renderer_2d.h (renamed from themes/src/Renderer2d.h)4
-rw-r--r--themes/src/renderer_3d.cpp (renamed from themes/src/Renderer3d.cpp)8
-rw-r--r--themes/src/renderer_3d.h (renamed from themes/src/Renderer3d.h)0
-rw-r--r--themes/src/shader.cpp (renamed from themes/src/Shader.cpp)2
-rw-r--r--themes/src/shader.h (renamed from themes/src/Shader.h)0
-rw-r--r--themes/src/shaders/sun_frag.cpp40
-rw-r--r--themes/src/shaders/sun_vert.cpp27
-rw-r--r--themes/src/shapes_2d.cpp2
-rw-r--r--themes/src/shapes_2d.h2
-rw-r--r--themes/src/spring/grass_renderer.cpp (renamed from themes/src/spring/GrassRenderer.cpp)4
-rw-r--r--themes/src/spring/grass_renderer.hpp (renamed from themes/src/spring/GrassRenderer.hpp)2
-rw-r--r--themes/src/spring/spring_theme.cpp (renamed from themes/src/spring/SpringTheme.cpp)4
-rw-r--r--themes/src/spring/spring_theme.hpp (renamed from themes/src/spring/SpringTheme.hpp)2
-rw-r--r--themes/src/summer/summer_theme.cpp (renamed from themes/src/summer/SummerTheme.cpp)12
-rw-r--r--themes/src/summer/summer_theme.h (renamed from themes/src/summer/SummerTheme.h)4
-rw-r--r--themes/src/webgl_context.cpp (renamed from themes/src/WebglContext.cpp)2
-rw-r--r--themes/src/webgl_context.h (renamed from themes/src/WebglContext.h)0
-rw-r--r--themes/src/winter/snowflake.cpp (renamed from themes/src/winter/Snowflake.cpp)4
-rw-r--r--themes/src/winter/snowflake.h (renamed from themes/src/winter/Snowflake.h)2
-rw-r--r--themes/src/winter/windfield.cpp (renamed from themes/src/winter/Windfield.cpp)2
-rw-r--r--themes/src/winter/windfield.hpp (renamed from themes/src/winter/Windfield.hpp)0
-rw-r--r--themes/src/winter/winter_theme.cpp (renamed from themes/src/winter/WinterTheme.cpp)4
-rw-r--r--themes/src/winter/winter_theme.hpp (renamed from themes/src/winter/WinterTheme.hpp)4
47 files changed, 1247 insertions, 1062 deletions
diff --git a/themes/.gitignore b/themes/.gitignore
new file mode 100644
index 0000000..a967258
--- /dev/null
+++ b/themes/.gitignore
@@ -0,0 +1,15 @@
+# Build directories
+dist/
+builddir/
+.cache/
+
+# IDE
+.idea/
+.vscode/
+*.swp
+*.swo
+*~
+
+# Meson
+.meson_subdir/
+compile_commands.json
diff --git a/themes/Makefile b/themes/Makefile
deleted file mode 100644
index 45967f5..0000000
--- a/themes/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-TARGET_EXEC ?= output.js
-
-BUILD_DIR ?= ./dist
-SRC_DIRS ?= ./src
-
-CC := emcc
-CXX := em++
-SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c -or -name *.s)
-OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
-DEPS := $(OBJS:.o=.d)
-
-INC_DIRS := $(shell find $(SRC_DIRS) -type d)
-INC_FLAGS := $(addprefix -I,$(INC_DIRS))
-LDFLAGS = -s ALLOW_MEMORY_GROWTH=1 -s USE_WEBGL2=1 -s FULL_ES3=1 -s WASM=1 -s NO_EXIT_RUNTIME=1 -s FETCH
-
-CPPFLAGS ?= $(INC_FLAGS) -MMD -MP
-
-$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
- $(CC) $(OBJS) -o $@ $(LDFLAGS)
-
-# assembly
-$(BUILD_DIR)/%.s.o: %.s
- $(MKDIR_P) $(dir $@)
- $(AS) $(ASFLAGS) -c $< -o $@
-
-# c source
-$(BUILD_DIR)/%.c.o: %.c
- $(MKDIR_P) $(dir $@)
- $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
-
-# c++ source
-$(BUILD_DIR)/%.cpp.o: %.cpp
- $(MKDIR_P) $(dir $@)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
-
-
-.PHONY: clean
-
-clean:
- $(RM) -r $(BUILD_DIR)
-
--include $(DEPS)
-
-MKDIR_P ?= mkdir -p
diff --git a/themes/README.md b/themes/README.md
new file mode 100644
index 0000000..3425fb8
--- /dev/null
+++ b/themes/README.md
@@ -0,0 +1,58 @@
+# Themes
+This subproject provides themes for the website.
+
+## Prerequisites
+
+- Emscripten SDK (emsdk)
+- Meson build system (`pip install meson` or via your package manager)
+- Ninja build backend (usually installed with Meson)
+
+## Building
+
+### Initial Setup
+
+```bash
+meson setup builddir --cross-file emscripten.ini
+```
+
+### Compile
+
+```bash
+meson compile -C builddir
+```
+
+The output files will be automatically copied to:
+- `dist/output.js`
+- `dist/output.wasm`
+
+The original build artifacts are also available in `builddir/` if needed.
+
+### Clean Build
+
+```bash
+# Clean and rebuild
+meson compile -C builddir --clean
+meson compile -C builddir
+```
+
+### Complete Clean
+
+```bash
+# Remove the build directory entirely
+rm -rf builddir
+```
+
+## Build Options
+
+You can configure build options during setup:
+
+```bash
+# Debug build
+meson setup builddir --cross-file emscripten.ini --buildtype=debug
+
+# Release build with optimizations
+meson setup builddir --cross-file emescripten.ini --buildtype=release
+
+# Reconfigure an existing build
+meson configure builddir --buildtype=debug
+```
diff --git a/themes/compile_commands.json b/themes/compile_commands.json
deleted file mode 100644
index bcf5405..0000000
--- a/themes/compile_commands.json
+++ /dev/null
@@ -1,127 +0,0 @@
-[
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/MainLoop.cpp -o dist/./src/MainLoop.cpp.o",
- "file": "dist/./src/MainLoop.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/spring/SpringTheme.cpp -o dist/./src/spring/SpringTheme.cpp.o",
- "file": "dist/./src/spring/SpringTheme.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/spring/GrassRenderer.cpp -o dist/./src/spring/GrassRenderer.cpp.o",
- "file": "dist/./src/spring/GrassRenderer.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/mathlib.cpp -o dist/./src/mathlib.cpp.o",
- "file": "dist/./src/mathlib.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/shaders/renderer3d_frag.cpp -o dist/./src/shaders/renderer3d_frag.cpp.o",
- "file": "dist/./src/shaders/renderer3d_frag.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/shaders/sun_frag.cpp -o dist/./src/shaders/sun_frag.cpp.o",
- "file": "dist/./src/shaders/sun_frag.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/shaders/renderer3d_vert.cpp -o dist/./src/shaders/renderer3d_vert.cpp.o",
- "file": "dist/./src/shaders/renderer3d_vert.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/shaders/renderer2d_frag.cpp -o dist/./src/shaders/renderer2d_frag.cpp.o",
- "file": "dist/./src/shaders/renderer2d_frag.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/shaders/sun_vert.cpp -o dist/./src/shaders/sun_vert.cpp.o",
- "file": "dist/./src/shaders/sun_vert.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/shaders/renderer2d_vert.cpp -o dist/./src/shaders/renderer2d_vert.cpp.o",
- "file": "dist/./src/shaders/renderer2d_vert.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/shader_fetcher.cpp -o dist/./src/shader_fetcher.cpp.o",
- "file": "dist/./src/shader_fetcher.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/Logger.cpp -o dist/./src/Logger.cpp.o",
- "file": "dist/./src/Logger.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/Renderer3d.cpp -o dist/./src/Renderer3d.cpp.o",
- "file": "dist/./src/Renderer3d.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/Shader.cpp -o dist/./src/Shader.cpp.o",
- "file": "dist/./src/Shader.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/summer/SummerTheme.cpp -o dist/./src/summer/SummerTheme.cpp.o",
- "file": "dist/./src/summer/SummerTheme.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/winter/Windfield.cpp -o dist/./src/winter/Windfield.cpp.o",
- "file": "dist/./src/winter/Windfield.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/winter/WinterTheme.cpp -o dist/./src/winter/WinterTheme.cpp.o",
- "file": "dist/./src/winter/WinterTheme.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/winter/Snowflake.cpp -o dist/./src/winter/Snowflake.cpp.o",
- "file": "dist/./src/winter/Snowflake.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/autumn/AutumnTheme.cpp -o dist/./src/autumn/AutumnTheme.cpp.o",
- "file": "dist/./src/autumn/AutumnTheme.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/autumn/TreeShape.cpp -o dist/./src/autumn/TreeShape.cpp.o",
- "file": "dist/./src/autumn/TreeShape.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/autumn/LeafParticleRender.cpp -o dist/./src/autumn/LeafParticleRender.cpp.o",
- "file": "dist/./src/autumn/LeafParticleRender.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/shapes_2d.cpp -o dist/./src/shapes_2d.cpp.o",
- "file": "dist/./src/shapes_2d.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/Renderer2d.cpp -o dist/./src/Renderer2d.cpp.o",
- "file": "dist/./src/Renderer2d.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/main.cpp -o dist/./src/main.cpp.o",
- "file": "dist/./src/main.cpp.o"
- },
- {
- "directory": ".",
- "command": "g++ -I./src -I./src/spring -I./src/shaders -I./src/tools -I./src/summer -I./src/winter -I./src/autumn -I./src/_shaders -MMD -MP -c src/WebglContext.cpp -o dist/./src/WebglContext.cpp.o",
- "file": "dist/./src/WebglContext.cpp.o"
- }
-]
diff --git a/themes/compile_commands.sh b/themes/compile_commands.sh
deleted file mode 100755
index 08a9eed..0000000
--- a/themes/compile_commands.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-make --always-make --dry-run \
- | grep -wE 'em++|emcc|gcc|g\+\+|c\+\+' \
- | grep -w '\-c' \
- | jq -nR '[inputs|{directory:".", command:., file: match(" [^ ]+$").string[1:]}]' \
- > compile_commands.json
-
-sed -i -e 's/em++/g++/g' compile_commands.json
diff --git a/themes/dist/output.js b/themes/dist/output.js
index 13d1675..011ac68 100644
--- a/themes/dist/output.js
+++ b/themes/dist/output.js
@@ -2,7 +2,7 @@
// The Module object: Our interface to the outside world. We import
// and export values on it. There are various ways Module can be used:
// 1. Not defined. We create it here
-// 2. A function parameter, function(Module) { ..generated code.. }
+// 2. A function parameter, function(moduleArg) => Promise<Module>
// 3. pre-run appended it, var Module = {}; ..generated code..
// 4. External script tag defines var Module.
// We need to check if Module already exists (e.g. case 3 above).
@@ -14,6 +14,25 @@
// can continue to use Module afterwards as well.
var Module = typeof Module != 'undefined' ? Module : {};
+// Determine the runtime environment we are in. You can customize this by
+// setting the ENVIRONMENT setting at compile time (see settings.js).
+
+// Attempt to auto-detect the environment
+var ENVIRONMENT_IS_WEB = typeof window == 'object';
+var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function';
+// N.b. Electron.js environment is simultaneously a NODE-environment, but
+// also a web environment.
+var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string' && process.type != 'renderer';
+var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+
+if (ENVIRONMENT_IS_NODE) {
+ // `require()` is no-op in an ESM module, use `createRequire()` to construct
+ // the require()` function. This is only necessary for multi-environment
+ // builds, `-sENVIRONMENT=node` emits a static import declaration instead.
+ // TODO: Swap all `require()`'s with `import()`'s?
+
+}
+
// --pre-jses are emitted after the Module integration code, so that they can
// refer to Module (if they choose; they can also define Module)
@@ -31,21 +50,6 @@ var quit_ = (status, toThrow) => {
throw toThrow;
};
-// Determine the runtime environment we are in. You can customize this by
-// setting the ENVIRONMENT setting at compile time (see settings.js).
-
-// Attempt to auto-detect the environment
-var ENVIRONMENT_IS_WEB = typeof window == 'object';
-var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function';
-// N.b. Electron.js environment is simultaneously a NODE-environment, but
-// also a web environment.
-var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string';
-var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
-
-if (Module['ENVIRONMENT']) {
- throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)');
-}
-
// `/` should be present at the end if `scriptDirectory` is not empty
var scriptDirectory = '';
function locateFile(path) {
@@ -56,9 +60,7 @@ function locateFile(path) {
}
// Hooks that are implemented differently in different runtime environments.
-var read_,
- readAsync,
- readBinary;
+var readAsync, readBinary;
if (ENVIRONMENT_IS_NODE) {
if (typeof process == 'undefined' || !process.release || process.release.name !== 'node') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
@@ -71,44 +73,31 @@ if (ENVIRONMENT_IS_NODE) {
throw new Error('This emscripten-generated code requires node v16.0.0 (detected v' + nodeVersion + ')');
}
- // `require()` is no-op in an ESM module, use `createRequire()` to construct
- // the require()` function. This is only necessary for multi-environment
- // builds, `-sENVIRONMENT=node` emits a static import declaration instead.
- // TODO: Swap all `require()`'s with `import()`'s?
// These modules will usually be used on Node.js. Load them eagerly to avoid
// the complexity of lazy-loading.
var fs = require('fs');
var nodePath = require('path');
- if (ENVIRONMENT_IS_WORKER) {
- scriptDirectory = nodePath.dirname(scriptDirectory) + '/';
- } else {
- scriptDirectory = __dirname + '/';
- }
+ scriptDirectory = __dirname + '/';
// include: node_shell_read.js
-read_ = (filename, binary) => {
+readBinary = (filename) => {
// We need to re-wrap `file://` strings to URLs. Normalizing isn't
// necessary in that case, the path should already be absolute.
filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
- return fs.readFileSync(filename, binary ? undefined : 'utf8');
-};
-
-readBinary = (filename) => {
- var ret = read_(filename, true);
- if (!ret.buffer) {
- ret = new Uint8Array(ret);
- }
+ var ret = fs.readFileSync(filename);
assert(ret.buffer);
return ret;
};
-readAsync = (filename, onload, onerror, binary = true) => {
- // See the comment in the `read_` function.
+readAsync = (filename, binary = true) => {
+ // See the comment in the `readBinary` function.
filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename);
- fs.readFile(filename, binary ? undefined : 'utf8', (err, data) => {
- if (err) onerror(err);
- else onload(binary ? data.buffer : data);
+ return new Promise((resolve, reject) => {
+ fs.readFile(filename, binary ? undefined : 'utf8', (err, data) => {
+ if (err) reject(err);
+ else resolve(binary ? data.buffer : data);
+ });
});
};
// end include: node_shell_read.js
@@ -122,89 +111,16 @@ readAsync = (filename, onload, onerror, binary = true) => {
module['exports'] = Module;
}
- process.on('uncaughtException', (ex) => {
- // suppress ExitStatus exceptions from showing an error
- if (ex !== 'unwind' && !(ex instanceof ExitStatus) && !(ex.context instanceof ExitStatus)) {
- throw ex;
- }
- });
-
quit_ = (status, toThrow) => {
process.exitCode = status;
throw toThrow;
};
- Module['inspect'] = () => '[Emscripten Module object]';
-
} else
if (ENVIRONMENT_IS_SHELL) {
if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
- if (typeof read != 'undefined') {
- read_ = read;
- }
-
- readBinary = (f) => {
- if (typeof readbuffer == 'function') {
- return new Uint8Array(readbuffer(f));
- }
- let data = read(f, 'binary');
- assert(typeof data == 'object');
- return data;
- };
-
- readAsync = (f, onload, onerror) => {
- setTimeout(() => onload(readBinary(f)));
- };
-
- if (typeof clearTimeout == 'undefined') {
- globalThis.clearTimeout = (id) => {};
- }
-
- if (typeof setTimeout == 'undefined') {
- // spidermonkey lacks setTimeout but we use it above in readAsync.
- globalThis.setTimeout = (f) => (typeof f == 'function') ? f() : abort();
- }
-
- if (typeof scriptArgs != 'undefined') {
- arguments_ = scriptArgs;
- } else if (typeof arguments != 'undefined') {
- arguments_ = arguments;
- }
-
- if (typeof quit == 'function') {
- quit_ = (status, toThrow) => {
- // Unlike node which has process.exitCode, d8 has no such mechanism. So we
- // have no way to set the exit code and then let the program exit with
- // that code when it naturally stops running (say, when all setTimeouts
- // have completed). For that reason, we must call `quit` - the only way to
- // set the exit code - but quit also halts immediately. To increase
- // consistency with node (and the web) we schedule the actual quit call
- // using a setTimeout to give the current stack and any exception handlers
- // a chance to run. This enables features such as addOnPostRun (which
- // expected to be able to run code after main returns).
- setTimeout(() => {
- if (!(toThrow instanceof ExitStatus)) {
- let toLog = toThrow;
- if (toThrow && typeof toThrow == 'object' && toThrow.stack) {
- toLog = [toThrow, toThrow.stack];
- }
- err(`exiting due to exception: ${toLog}`);
- }
- quit(status);
- });
- throw toThrow;
- };
- }
-
- if (typeof print != 'undefined') {
- // Prefer to use print/printErr where they exist, as they usually work better.
- if (typeof console == 'undefined') console = /** @type{!Console} */({});
- console.log = /** @type{!function(this:Console, ...*): undefined} */ (print);
- console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr != 'undefined' ? printErr : print);
- }
-
} else
// Note that this includes Node.js workers when relevant (pthreads is enabled).
@@ -222,26 +138,17 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
// and scriptDirectory will correctly be replaced with an empty string.
// If scriptDirectory contains a query (starting with ?) or a fragment (starting with #),
// they are removed because they could contain a slash.
- if (scriptDirectory.indexOf('blob:') !== 0) {
- scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf('/')+1);
- } else {
+ if (scriptDirectory.startsWith('blob:')) {
scriptDirectory = '';
+ } else {
+ scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, '').lastIndexOf('/')+1);
}
if (!(typeof window == 'object' || typeof importScripts == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
- // Differentiate the Web Worker from the Node Worker case, as reading must
- // be done differently.
{
// include: web_or_worker_shell_read.js
-read_ = (url) => {
- var xhr = new XMLHttpRequest();
- xhr.open('GET', url, false);
- xhr.send(null);
- return xhr.responseText;
- }
-
- if (ENVIRONMENT_IS_WORKER) {
+if (ENVIRONMENT_IS_WORKER) {
readBinary = (url) => {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
@@ -251,21 +158,35 @@ read_ = (url) => {
};
}
- readAsync = (url, onload, onerror) => {
- var xhr = new XMLHttpRequest();
- xhr.open('GET', url, true);
- xhr.responseType = 'arraybuffer';
- xhr.onload = () => {
- if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
- onload(xhr.response);
- return;
- }
- onerror();
- };
- xhr.onerror = onerror;
- xhr.send(null);
- }
-
+ readAsync = (url) => {
+ // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
+ // See https://github.com/github/fetch/pull/92#issuecomment-140665932
+ // Cordova or Electron apps are typically loaded from a file:// url.
+ // So use XHR on webview if URL is a file URL.
+ if (isFileURI(url)) {
+ return new Promise((resolve, reject) => {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.onload = () => {
+ if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
+ resolve(xhr.response);
+ return;
+ }
+ reject(xhr.status);
+ };
+ xhr.onerror = reject;
+ xhr.send(null);
+ });
+ }
+ return fetch(url, { credentials: 'same-origin' })
+ .then((response) => {
+ if (response.ok) {
+ return response.arrayBuffer();
+ }
+ return Promise.reject(new Error(response.status + ' : ' + response.url));
+ })
+ };
// end include: web_or_worker_shell_read.js
}
} else
@@ -279,7 +200,7 @@ var err = Module['printErr'] || console.error.bind(console);
// Merge back in the overrides
Object.assign(Module, moduleOverrides);
// Free the object hierarchy contained in the overrides, this lets the GC
-// reclaim data used e.g. in memoryInitializerRequest, which is a large typed array.
+// reclaim data used.
moduleOverrides = null;
checkIncomingModuleAPI();
@@ -292,21 +213,18 @@ if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('argu
if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram');
-if (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_');
-
// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
// Assertions on removed incoming Module JS APIs.
assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead');
assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead');
assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead');
assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead');
-assert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)');
+assert(typeof Module['read'] == 'undefined', 'Module.read option was removed');
assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)');
assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)');
assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)');
assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY');
legacyModuleProp('asm', 'wasmExports');
-legacyModuleProp('read', 'read_');
legacyModuleProp('readAsync', 'readAsync');
legacyModuleProp('readBinary', 'readBinary');
legacyModuleProp('setWindowTitle', 'setWindowTitle');
@@ -320,10 +238,10 @@ var OPFS = 'OPFS is no longer included by default; build with -lopfs.js';
var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js';
-assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at build time. Add 'shell' to `-sENVIRONMENT` to enable.");
-
+assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.');
// end include: shell.js
+
// include: preamble.js
// === Preamble library stuff ===
@@ -335,12 +253,10 @@ assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at bui
// An online HTML version (which may be of a different version of Emscripten)
// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
-var wasmBinary;
-if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary');
-var noExitRuntime = Module['noExitRuntime'] || true;legacyModuleProp('noExitRuntime', 'noExitRuntime');
+var wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary');
if (typeof WebAssembly != 'object') {
- abort('no native wasm support detected');
+ err('no native wasm support detected');
}
// Wasm globals
@@ -360,6 +276,10 @@ var ABORT = false;
// but only when noExitRuntime is false.
var EXITSTATUS;
+// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we
+// don't define it at all in release modes. This matches the behaviour of
+// MINIMAL_RUNTIME.
+// TODO(sbc): Make this the default even without STRICT enabled.
/** @type {function(*, string=)} */
function assert(condition, text) {
if (!condition) {
@@ -390,6 +310,7 @@ var HEAP,
/** @type {!Float64Array} */
HEAPF64;
+// include: runtime_shared.js
function updateMemoryViews() {
var b = wasmMemory.buffer;
Module['HEAP8'] = HEAP8 = new Int8Array(b);
@@ -402,6 +323,7 @@ function updateMemoryViews() {
Module['HEAPF64'] = HEAPF64 = new Float64Array(b);
}
+// end include: runtime_shared.js
assert(!Module['STACK_SIZE'], 'STACK_SIZE can no longer be set at runtime. Use -sSTACK_SIZE at link time')
assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined,
@@ -449,16 +371,6 @@ function checkStackCookie() {
}
}
// end include: runtime_stack_check.js
-// include: runtime_assertions.js
-// Endianness check
-(function() {
- var h16 = new Int16Array(1);
- var h8 = new Int8Array(h16.buffer);
- h16[0] = 0x6373;
- if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)';
-})();
-
-// end include: runtime_assertions.js
var __ATPRERUN__ = []; // functions called before the runtime is initialized
var __ATINIT__ = []; // functions called during startup
var __ATMAIN__ = []; // functions called when main() is to be run
@@ -467,18 +379,11 @@ var __ATPOSTRUN__ = []; // functions called after the main() is called
var runtimeInitialized = false;
-var runtimeKeepaliveCounter = 0;
-
-function keepRuntimeAlive() {
- return noExitRuntime || runtimeKeepaliveCounter > 0;
-}
-
function preRun() {
- if (Module['preRun']) {
- if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
- while (Module['preRun'].length) {
- addOnPreRun(Module['preRun'].shift());
- }
+ var preRuns = Module['preRun'];
+ if (preRuns) {
+ if (typeof preRuns == 'function') preRuns = [preRuns];
+ preRuns.forEach(addOnPreRun);
}
callRuntimeCallbacks(__ATPRERUN__);
}
@@ -502,11 +407,10 @@ function preMain() {
function postRun() {
checkStackCookie();
- if (Module['postRun']) {
- if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
- while (Module['postRun'].length) {
- addOnPostRun(Module['postRun'].shift());
- }
+ var postRuns = Module['postRun'];
+ if (postRuns) {
+ if (typeof postRuns == 'function') postRuns = [postRuns];
+ postRuns.forEach(addOnPostRun);
}
callRuntimeCallbacks(__ATPOSTRUN__);
@@ -568,9 +472,7 @@ function getUniqueRunDependency(id) {
function addRunDependency(id) {
runDependencies++;
- if (Module['monitorRunDependencies']) {
- Module['monitorRunDependencies'](runDependencies);
- }
+ Module['monitorRunDependencies']?.(runDependencies);
if (id) {
assert(!runDependencyTracking[id]);
@@ -604,9 +506,7 @@ function addRunDependency(id) {
function removeRunDependency(id) {
runDependencies--;
- if (Module['monitorRunDependencies']) {
- Module['monitorRunDependencies'](runDependencies);
- }
+ Module['monitorRunDependencies']?.(runDependencies);
if (id) {
assert(runDependencyTracking[id]);
@@ -629,9 +529,7 @@ function removeRunDependency(id) {
/** @param {string|number=} what */
function abort(what) {
- if (Module['onAbort']) {
- Module['onAbort'](what);
- }
+ Module['onAbort']?.(what);
what = 'Aborted(' + what + ')';
// TODO(sbc): Should we remove printing and leave it up to whoever
@@ -639,7 +537,6 @@ function abort(what) {
err(what);
ABORT = true;
- EXITSTATUS = 1;
// Use a wasm runtime error, because a JS error might be seen as a foreign
// exception, which means we'd run destructors on it. We need the error to
@@ -651,7 +548,7 @@ function abort(what) {
// allows this in the wasm spec.
// Suppress closure compiler warning here. Closure compiler's builtin extern
- // defintion for WebAssembly.RuntimeError claims it takes no arguments even
+ // definition for WebAssembly.RuntimeError claims it takes no arguments even
// though it can.
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
/** @suppress {checkTypes} */
@@ -688,33 +585,40 @@ Module['FS_createPreloadedFile'] = FS.createPreloadedFile;
// Prefix of data URIs emitted by SINGLE_FILE and related options.
var dataURIPrefix = 'data:application/octet-stream;base64,';
-// Indicates whether filename is a base64 data URI.
-function isDataURI(filename) {
- // Prefix of data URIs emitted by SINGLE_FILE and related options.
- return filename.startsWith(dataURIPrefix);
-}
-
-// Indicates whether filename is delivered via file protocol (as opposed to http/https)
-function isFileURI(filename) {
- return filename.startsWith('file://');
-}
+/**
+ * Indicates whether filename is a base64 data URI.
+ * @noinline
+ */
+var isDataURI = (filename) => filename.startsWith(dataURIPrefix);
+
+/**
+ * Indicates whether filename is delivered via file protocol (as opposed to http/https)
+ * @noinline
+ */
+var isFileURI = (filename) => filename.startsWith('file://');
// end include: URIUtils.js
-function createExportWrapper(name) {
- return function() {
+function createExportWrapper(name, nargs) {
+ return (...args) => {
assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`);
var f = wasmExports[name];
assert(f, `exported native function \`${name}\` not found`);
- return f.apply(null, arguments);
+ // Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled.
+ assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`);
+ return f(...args);
};
}
// include: runtime_exceptions.js
// end include: runtime_exceptions.js
+function findWasmBinary() {
+ var f = 'output.wasm';
+ if (!isDataURI(f)) {
+ return locateFile(f);
+ }
+ return f;
+}
+
var wasmBinaryFile;
- wasmBinaryFile = 'output.wasm';
- if (!isDataURI(wasmBinaryFile)) {
- wasmBinaryFile = locateFile(wasmBinaryFile);
- }
function getBinarySync(file) {
if (file == wasmBinaryFile && wasmBinary) {
@@ -723,33 +627,19 @@ function getBinarySync(file) {
if (readBinary) {
return readBinary(file);
}
- throw "both async and sync fetching of the wasm failed";
+ throw 'both async and sync fetching of the wasm failed';
}
function getBinaryPromise(binaryFile) {
- // If we don't have the binary yet, try to load it asynchronously.
- // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
- // See https://github.com/github/fetch/pull/92#issuecomment-140665932
- // Cordova or Electron apps are typically loaded from a file:// url.
- // So use fetch if it is available and the url is not a file, otherwise fall back to XHR.
+ // If we don't have the binary yet, load it asynchronously using readAsync.
if (!wasmBinary
- && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
- if (typeof fetch == 'function'
- && !isFileURI(binaryFile)
- ) {
- return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => {
- if (!response['ok']) {
- throw "failed to load wasm binary file at '" + binaryFile + "'";
- }
- return response['arrayBuffer']();
- }).catch(() => getBinarySync(binaryFile));
- }
- else if (readAsync) {
- // fetch is not available or url is file => try XHR (readAsync uses XHR internally)
- return new Promise((resolve, reject) => {
- readAsync(binaryFile, (response) => resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))), reject)
- });
- }
+ ) {
+ // Fetch the binary using readAsync
+ return readAsync(binaryFile).then(
+ (response) => new Uint8Array(/** @type{!ArrayBuffer} */(response)),
+ // Fall back to getBinarySync if readAsync fails
+ () => getBinarySync(binaryFile)
+ );
}
// Otherwise, getBinarySync should be able to get it synchronously
@@ -759,8 +649,6 @@ function getBinaryPromise(binaryFile) {
function instantiateArrayBuffer(binaryFile, imports, receiver) {
return getBinaryPromise(binaryFile).then((binary) => {
return WebAssembly.instantiate(binary, imports);
- }).then((instance) => {
- return instance;
}).then(receiver, (reason) => {
err(`failed to asynchronously prepare wasm: ${reason}`);
@@ -808,14 +696,18 @@ function instantiateAsync(binary, binaryFile, imports, callback) {
return instantiateArrayBuffer(binaryFile, imports, callback);
}
-// Create the wasm instance.
-// Receives the wasm imports, returns the exports.
-function createWasm() {
+function getWasmImports() {
// prepare imports
- var info = {
+ return {
'env': wasmImports,
'wasi_snapshot_preview1': wasmImports,
- };
+ }
+}
+
+// Create the wasm instance.
+// Receives the wasm imports, returns the exports.
+function createWasm() {
+ var info = getWasmImports();
// Load the wasm module and create an instance of using native support in the JS engine.
// handle a generated wasm instance, receiving its exports and
// performing other necessary setup
@@ -827,16 +719,12 @@ function createWasm() {
wasmMemory = wasmExports['memory'];
- assert(wasmMemory, "memory not found in wasm exports");
- // This assertion doesn't hold when emscripten is run in --post-link
- // mode.
- // TODO(sbc): Read INITIAL_MEMORY out of the wasm file in post-link mode.
- //assert(wasmMemory.buffer.byteLength === 16777216);
+ assert(wasmMemory, 'memory not found in wasm exports');
updateMemoryViews();
wasmTable = wasmExports['__indirect_function_table'];
- assert(wasmTable, "table not found in wasm exports");
+ assert(wasmTable, 'table not found in wasm exports');
addOnInit(wasmExports['__wasm_call_ctors']);
@@ -868,7 +756,6 @@ function createWasm() {
// Also pthreads and wasm workers initialize the wasm instance through this
// path.
if (Module['instantiateWasm']) {
-
try {
return Module['instantiateWasm'](info, receiveInstance);
} catch(e) {
@@ -877,6 +764,8 @@ function createWasm() {
}
}
+ wasmBinaryFile ??= findWasmBinary();
+
instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult);
return {}; // no exports yet; we'll fill them in later
}
@@ -886,12 +775,24 @@ var tempDouble;
var tempI64;
// include: runtime_debug.js
-function legacyModuleProp(prop, newName, incomming=true) {
+// Endianness check
+(() => {
+ var h16 = new Int16Array(1);
+ var h8 = new Int8Array(h16.buffer);
+ h16[0] = 0x6373;
+ if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)';
+})();
+
+if (Module['ENVIRONMENT']) {
+ throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)');
+}
+
+function legacyModuleProp(prop, newName, incoming=true) {
if (!Object.getOwnPropertyDescriptor(Module, prop)) {
Object.defineProperty(Module, prop, {
configurable: true,
get() {
- let extra = incomming ? ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)' : '';
+ let extra = incoming ? ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)' : '';
abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra);
}
@@ -918,46 +819,52 @@ function isExportedByForceFilesystem(name) {
name === 'removeRunDependency';
}
-function missingGlobal(sym, msg) {
- if (typeof globalThis !== 'undefined') {
+/**
+ * Intercept access to a global symbol. This enables us to give informative
+ * warnings/errors when folks attempt to use symbols they did not include in
+ * their build, or no symbols that no longer exist.
+ */
+function hookGlobalSymbolAccess(sym, func) {
+ if (typeof globalThis != 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) {
Object.defineProperty(globalThis, sym, {
configurable: true,
get() {
- warnOnce('`' + sym + '` is not longer defined by emscripten. ' + msg);
+ func();
return undefined;
}
});
}
}
+function missingGlobal(sym, msg) {
+ hookGlobalSymbolAccess(sym, () => {
+ warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`);
+ });
+}
+
missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer');
missingGlobal('asm', 'Please use wasmExports instead');
function missingLibrarySymbol(sym) {
- if (typeof globalThis !== 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) {
- Object.defineProperty(globalThis, sym, {
- configurable: true,
- get() {
- // Can't `abort()` here because it would break code that does runtime
- // checks. e.g. `if (typeof SDL === 'undefined')`.
- var msg = '`' + sym + '` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line';
- // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in
- // library.js, which means $name for a JS name with no prefix, or name
- // for a JS name like _name.
- var librarySymbol = sym;
- if (!librarySymbol.startsWith('_')) {
- librarySymbol = '$' + sym;
- }
- msg += " (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='" + librarySymbol + "')";
- if (isExportedByForceFilesystem(sym)) {
- msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you';
- }
- warnOnce(msg);
- return undefined;
- }
- });
- }
- // Any symbol that is not included from the JS libary is also (by definition)
+ hookGlobalSymbolAccess(sym, () => {
+ // Can't `abort()` here because it would break code that does runtime
+ // checks. e.g. `if (typeof SDL === 'undefined')`.
+ var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`;
+ // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in
+ // library.js, which means $name for a JS name with no prefix, or name
+ // for a JS name like _name.
+ var librarySymbol = sym;
+ if (!librarySymbol.startsWith('_')) {
+ librarySymbol = '$' + sym;
+ }
+ msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`;
+ if (isExportedByForceFilesystem(sym)) {
+ msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you';
+ }
+ warnOnce(msg);
+ });
+
+ // Any symbol that is not included from the JS library is also (by definition)
// not exported on the Module object.
unexportedRuntimeSymbol(sym);
}
@@ -967,7 +874,7 @@ function unexportedRuntimeSymbol(sym) {
Object.defineProperty(Module, sym, {
configurable: true,
get() {
- var msg = "'" + sym + "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)";
+ var msg = `'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`;
if (isExportedByForceFilesystem(sym)) {
msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you';
}
@@ -978,16 +885,16 @@ function unexportedRuntimeSymbol(sym) {
}
// Used by XXXXX_DEBUG settings to output debug messages.
-function dbg(text) {
+function dbg(...args) {
// TODO(sbc): Make this configurable somehow. Its not always convenient for
// logging to show up as warnings.
- console.warn.apply(console, arguments);
+ console.warn(...args);
}
// end include: runtime_debug.js
// === Body ===
-
// end include: preamble.js
+
/** @constructor */
function ExitStatus(status) {
this.name = 'ExitStatus';
@@ -996,10 +903,8 @@ function dbg(text) {
}
var callRuntimeCallbacks = (callbacks) => {
- while (callbacks.length > 0) {
- // Pass the module as the first argument.
- callbacks.shift()(Module);
- }
+ // Pass the module as the first argument.
+ callbacks.forEach((f) => f(Module));
};
@@ -1010,8 +915,8 @@ function dbg(text) {
function getValue(ptr, type = 'i8') {
if (type.endsWith('*')) type = '*';
switch (type) {
- case 'i1': return HEAP8[((ptr)>>0)];
- case 'i8': return HEAP8[((ptr)>>0)];
+ case 'i1': return HEAP8[ptr];
+ case 'i8': return HEAP8[ptr];
case 'i16': return HEAP16[((ptr)>>1)];
case 'i32': return HEAP32[((ptr)>>2)];
case 'i64': abort('to do getValue(i64) use WASM_BIGINT');
@@ -1022,6 +927,8 @@ function dbg(text) {
}
}
+ var noExitRuntime = Module['noExitRuntime'] || true;
+
var ptrToString = (ptr) => {
assert(typeof ptr === 'number');
// With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
@@ -1038,8 +945,8 @@ function dbg(text) {
function setValue(ptr, value, type = 'i8') {
if (type.endsWith('*')) type = '*';
switch (type) {
- case 'i1': HEAP8[((ptr)>>0)] = value; break;
- case 'i8': HEAP8[((ptr)>>0)] = value; break;
+ case 'i1': HEAP8[ptr] = value; break;
+ case 'i8': HEAP8[ptr] = value; break;
case 'i16': HEAP16[((ptr)>>1)] = value; break;
case 'i32': HEAP32[((ptr)>>2)] = value; break;
case 'i64': abort('to do setValue(i64) use WASM_BIGINT');
@@ -1050,8 +957,12 @@ function dbg(text) {
}
}
+ var stackRestore = (val) => __emscripten_stack_restore(val);
+
+ var stackSave = () => _emscripten_stack_get_current();
+
var warnOnce = (text) => {
- if (!warnOnce.shown) warnOnce.shown = {};
+ warnOnce.shown ||= {};
if (!warnOnce.shown[text]) {
warnOnce.shown[text] = 1;
if (ENVIRONMENT_IS_NODE) text = 'warning: ' + text;
@@ -1059,6 +970,87 @@ function dbg(text) {
}
};
+ var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder() : undefined;
+
+ /**
+ * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
+ * array that contains uint8 values, returns a copy of that string as a
+ * Javascript String object.
+ * heapOrArray is either a regular array, or a JavaScript typed array view.
+ * @param {number=} idx
+ * @param {number=} maxBytesToRead
+ * @return {string}
+ */
+ var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead = NaN) => {
+ var endIdx = idx + maxBytesToRead;
+ var endPtr = idx;
+ // TextDecoder needs to know the byte length in advance, it doesn't stop on
+ // null terminator by itself. Also, use the length info to avoid running tiny
+ // strings through TextDecoder, since .subarray() allocates garbage.
+ // (As a tiny code save trick, compare endPtr against endIdx using a negation,
+ // so that undefined/NaN means Infinity)
+ while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
+
+ if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
+ return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
+ }
+ var str = '';
+ // If building with TextDecoder, we have already computed the string length
+ // above, so test loop end condition against that
+ while (idx < endPtr) {
+ // For UTF8 byte structure, see:
+ // http://en.wikipedia.org/wiki/UTF-8#Description
+ // https://www.ietf.org/rfc/rfc2279.txt
+ // https://tools.ietf.org/html/rfc3629
+ var u0 = heapOrArray[idx++];
+ if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
+ var u1 = heapOrArray[idx++] & 63;
+ if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
+ var u2 = heapOrArray[idx++] & 63;
+ if ((u0 & 0xF0) == 0xE0) {
+ u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
+ } else {
+ if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
+ u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
+ }
+
+ if (u0 < 0x10000) {
+ str += String.fromCharCode(u0);
+ } else {
+ var ch = u0 - 0x10000;
+ str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
+ }
+ }
+ return str;
+ };
+
+ /**
+ * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
+ * emscripten HEAP, returns a copy of that string as a Javascript String object.
+ *
+ * @param {number} ptr
+ * @param {number=} maxBytesToRead - An optional length that specifies the
+ * maximum number of bytes to read. You can omit this parameter to scan the
+ * string until the first 0 byte. If maxBytesToRead is passed, and the string
+ * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
+ * string will cut short at that byte index (i.e. maxBytesToRead will not
+ * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
+ * frequent uses of UTF8ToString() with and without maxBytesToRead may throw
+ * JS JIT optimizations off, so it is worth to consider consistently using one
+ * @return {string}
+ */
+ var UTF8ToString = (ptr, maxBytesToRead) => {
+ assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`);
+ return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
+ };
+ var ___assert_fail = (condition, filename, line, func) => {
+ abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
+ };
+
+ var __abort_js = () => {
+ abort('native code called abort()');
+ };
+
function __emscripten_fetch_free(id) {
if (Fetch.xhrs.has(id)) {
var xhr = Fetch.xhrs.get(id);
@@ -1070,9 +1062,9 @@ function dbg(text) {
}
}
- var isLeapYear = (year) => {
- return year%4 === 0 && (year%100 !== 0 || year%400 === 0);
- };
+ var __emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
+
+ 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];
@@ -1091,7 +1083,7 @@ function dbg(text) {
return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN;
};
function __localtime_js(time_low, time_high,tmPtr) {
- var time = convertI32PairToI53Checked(time_low, time_high);;
+ var time = convertI32PairToI53Checked(time_low, time_high);
var date = new Date(time*1000);
@@ -1116,29 +1108,8 @@ function dbg(text) {
;
}
- var lengthBytesUTF8 = (str) => {
- var len = 0;
- for (var i = 0; i < str.length; ++i) {
- // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
- // unit, not a Unicode code point of the character! So decode
- // UTF16->UTF32->UTF8.
- // See http://unicode.org/faq/utf_bom.html#utf16-3
- var c = str.charCodeAt(i); // possibly a lead surrogate
- if (c <= 0x7F) {
- len++;
- } else if (c <= 0x7FF) {
- len += 2;
- } else if (c >= 0xD800 && c <= 0xDFFF) {
- len += 4; ++i;
- } else {
- len += 3;
- }
- }
- return len;
- };
-
var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => {
- assert(typeof str === 'string');
+ assert(typeof str === 'string', `stringToUTF8Array expects a string (got ${typeof str})`);
// Parameter maxBytesToWrite is not optional. Negative values, 0, null,
// undefined and false each don't write out any bytes.
if (!(maxBytesToWrite > 0))
@@ -1189,13 +1160,27 @@ function dbg(text) {
return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
};
- var stringToNewUTF8 = (str) => {
- var size = lengthBytesUTF8(str) + 1;
- var ret = _malloc(size);
- if (ret) stringToUTF8(str, ret, size);
- return ret;
+ var lengthBytesUTF8 = (str) => {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code
+ // unit, not a Unicode code point of the character! So decode
+ // UTF16->UTF32->UTF8.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ var c = str.charCodeAt(i); // possibly a lead surrogate
+ if (c <= 0x7F) {
+ len++;
+ } else if (c <= 0x7FF) {
+ len += 2;
+ } else if (c >= 0xD800 && c <= 0xDFFF) {
+ len += 4; ++i;
+ } else {
+ len += 3;
+ }
+ }
+ return len;
};
- var __tzset_js = (timezone, daylight, tzname) => {
+ var __tzset_js = (timezone, daylight, std_name, dst_name) => {
// TODO: Use (malleable) environment variables instead of system settings.
var currentYear = new Date().getFullYear();
var winter = new Date(currentYear, 0, 1);
@@ -1203,9 +1188,12 @@ function dbg(text) {
var winterOffset = winter.getTimezoneOffset();
var summerOffset = summer.getTimezoneOffset();
- // Local standard timezone offset. Local standard time is not adjusted for daylight savings.
- // This code uses the fact that getTimezoneOffset returns a greater value during Standard Time versus Daylight Saving Time (DST).
- // Thus it determines the expected output during Standard Time, and it compares whether the output of the given date the same (Standard) or less (DST).
+ // Local standard timezone offset. Local standard time is not adjusted for
+ // daylight savings. This code uses the fact that getTimezoneOffset returns
+ // a greater value during Standard Time versus Daylight Saving Time (DST).
+ // Thus it determines the expected output during Standard Time, and it
+ // compares whether the output of the given date the same (Standard) or less
+ // (DST).
var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
// timezone is specified as seconds west of UTC ("The external variable
@@ -1217,51 +1205,44 @@ function dbg(text) {
HEAP32[((daylight)>>2)] = Number(winterOffset != summerOffset);
- function extractZone(date) {
- var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
- return match ? match[1] : "GMT";
- };
- var winterName = extractZone(winter);
- var summerName = extractZone(summer);
- var winterNamePtr = stringToNewUTF8(winterName);
- var summerNamePtr = stringToNewUTF8(summerName);
+ var extractZone = (timezoneOffset) => {
+ // Why inverse sign?
+ // Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
+ 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);
+ assert(winterName);
+ assert(summerName);
+ assert(lengthBytesUTF8(winterName) <= 16, `timezone name truncated to fit in TZNAME_MAX (${winterName})`);
+ assert(lengthBytesUTF8(summerName) <= 16, `timezone name truncated to fit in TZNAME_MAX (${summerName})`);
if (summerOffset < winterOffset) {
// Northern hemisphere
- HEAPU32[((tzname)>>2)] = winterNamePtr;
- HEAPU32[(((tzname)+(4))>>2)] = summerNamePtr;
+ stringToUTF8(winterName, std_name, 17);
+ stringToUTF8(summerName, dst_name, 17);
} else {
- HEAPU32[((tzname)>>2)] = summerNamePtr;
- HEAPU32[(((tzname)+(4))>>2)] = winterNamePtr;
+ stringToUTF8(winterName, dst_name, 17);
+ stringToUTF8(summerName, std_name, 17);
}
};
- var _abort = () => {
- abort('native code called abort()');
- };
-
var _emscripten_date_now = () => Date.now();
- var withStackSave = (f) => {
- var stack = stackSave();
- var ret = f();
- stackRestore(stack);
- return ret;
- };
var JSEvents = {
- inEventHandler:0,
removeAllEventListeners() {
- for (var i = JSEvents.eventHandlers.length-1; i >= 0; --i) {
- JSEvents._removeHandler(i);
+ while (JSEvents.eventHandlers.length) {
+ JSEvents._removeHandler(JSEvents.eventHandlers.length - 1);
}
- JSEvents.eventHandlers = [];
JSEvents.deferredCalls = [];
},
- registerRemoveEventListeners() {
- if (!JSEvents.removeEventListenersRegistered) {
- __ATEXIT__.push(JSEvents.removeAllEventListeners);
- JSEvents.removeEventListenersRegistered = true;
- }
- },
+ inEventHandler:0,
deferredCalls:[],
deferCall(targetFunction, precedence, argsList) {
function arraysHaveEqualContent(arrA, arrB) {
@@ -1273,8 +1254,7 @@ function dbg(text) {
return true;
}
// Test if the given call was already queued, and if so, don't add it again.
- for (var i in JSEvents.deferredCalls) {
- var call = JSEvents.deferredCalls[i];
+ for (var call of JSEvents.deferredCalls) {
if (call.targetFunction == targetFunction && arraysHaveEqualContent(call.argsList, argsList)) {
return;
}
@@ -1288,12 +1268,7 @@ function dbg(text) {
JSEvents.deferredCalls.sort((x,y) => x.precedence < y.precedence);
},
removeDeferredCalls(targetFunction) {
- for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
- if (JSEvents.deferredCalls[i].targetFunction == targetFunction) {
- JSEvents.deferredCalls.splice(i, 1);
- --i;
- }
- }
+ JSEvents.deferredCalls = JSEvents.deferredCalls.filter((call) => call.targetFunction != targetFunction);
},
canPerformEventHandlerRequests() {
if (navigator.userActivation) {
@@ -1311,11 +1286,10 @@ function dbg(text) {
if (!JSEvents.canPerformEventHandlerRequests()) {
return;
}
- for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
- var call = JSEvents.deferredCalls[i];
- JSEvents.deferredCalls.splice(i, 1);
- --i;
- call.targetFunction.apply(null, call.argsList);
+ var deferredCalls = JSEvents.deferredCalls;
+ JSEvents.deferredCalls = [];
+ for (var call of deferredCalls) {
+ call.targetFunction(...call.argsList);
}
},
eventHandlers:[],
@@ -1338,25 +1312,25 @@ function dbg(text) {
console.dir(eventHandler);
return -4;
}
- var jsEventHandler = function jsEventHandler(event) {
- // Increment nesting count for the event handler.
- ++JSEvents.inEventHandler;
- JSEvents.currentEventHandler = eventHandler;
- // Process any old deferred calls the user has placed.
- JSEvents.runDeferredCalls();
- // Process the actual event, calls back to user C code handler.
- eventHandler.handlerFunc(event);
- // Process any new deferred calls that were placed right now from this event handler.
- JSEvents.runDeferredCalls();
- // Out of event handler - restore nesting count.
- --JSEvents.inEventHandler;
- };
-
if (eventHandler.callbackfunc) {
- eventHandler.eventListenerFunc = jsEventHandler;
- eventHandler.target.addEventListener(eventHandler.eventTypeString, jsEventHandler, eventHandler.useCapture);
+ eventHandler.eventListenerFunc = function(event) {
+ // Increment nesting count for the event handler.
+ ++JSEvents.inEventHandler;
+ JSEvents.currentEventHandler = eventHandler;
+ // Process any old deferred calls the user has placed.
+ JSEvents.runDeferredCalls();
+ // Process the actual event, calls back to user C code handler.
+ eventHandler.handlerFunc(event);
+ // Process any new deferred calls that were placed right now from this event handler.
+ JSEvents.runDeferredCalls();
+ // Out of event handler - restore nesting count.
+ --JSEvents.inEventHandler;
+ };
+
+ eventHandler.target.addEventListener(eventHandler.eventTypeString,
+ eventHandler.eventListenerFunc,
+ eventHandler.useCapture);
JSEvents.eventHandlers.push(eventHandler);
- JSEvents.registerRemoveEventListeners();
} else {
for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
if (JSEvents.eventHandlers[i].target == eventHandler.target
@@ -1371,7 +1345,7 @@ function dbg(text) {
if (!target) return '';
if (target == window) return '#window';
if (target == screen) return '#screen';
- return (target && target.nodeName) ? target.nodeName : '';
+ return target?.nodeName || '';
},
fullscreenEnabled() {
return document.fullscreenEnabled
@@ -1382,79 +1356,6 @@ function dbg(text) {
},
};
- var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined;
-
- /**
- * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given
- * array that contains uint8 values, returns a copy of that string as a
- * Javascript String object.
- * heapOrArray is either a regular array, or a JavaScript typed array view.
- * @param {number} idx
- * @param {number=} maxBytesToRead
- * @return {string}
- */
- var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => {
- var endIdx = idx + maxBytesToRead;
- var endPtr = idx;
- // TextDecoder needs to know the byte length in advance, it doesn't stop on
- // null terminator by itself. Also, use the length info to avoid running tiny
- // strings through TextDecoder, since .subarray() allocates garbage.
- // (As a tiny code save trick, compare endPtr against endIdx using a negation,
- // so that undefined means Infinity)
- while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
-
- if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
- return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr));
- }
- var str = '';
- // If building with TextDecoder, we have already computed the string length
- // above, so test loop end condition against that
- while (idx < endPtr) {
- // For UTF8 byte structure, see:
- // http://en.wikipedia.org/wiki/UTF-8#Description
- // https://www.ietf.org/rfc/rfc2279.txt
- // https://tools.ietf.org/html/rfc3629
- var u0 = heapOrArray[idx++];
- if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
- var u1 = heapOrArray[idx++] & 63;
- if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
- var u2 = heapOrArray[idx++] & 63;
- if ((u0 & 0xF0) == 0xE0) {
- u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
- } else {
- if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
- u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
- }
-
- if (u0 < 0x10000) {
- str += String.fromCharCode(u0);
- } else {
- var ch = u0 - 0x10000;
- str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
- }
- }
- return str;
- };
-
- /**
- * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
- * emscripten HEAP, returns a copy of that string as a Javascript String object.
- *
- * @param {number} ptr
- * @param {number=} maxBytesToRead - An optional length that specifies the
- * maximum number of bytes to read. You can omit this parameter to scan the
- * string until the first 0 byte. If maxBytesToRead is passed, and the string
- * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
- * string will cut short at that byte index (i.e. maxBytesToRead will not
- * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
- * frequent uses of UTF8ToString() with and without maxBytesToRead may throw
- * JS JIT optimizations off, so it is worth to consider consistently using one
- * @return {string}
- */
- var UTF8ToString = (ptr, maxBytesToRead) => {
- assert(typeof ptr == 'number');
- return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
- };
var maybeCStringToJsString = (cString) => {
// "cString > 2" checks if the input is a number, and isn't of the special
// values we accept here, EMSCRIPTEN_EVENT_TARGET_* (which map to 0, 1, 2).
@@ -1463,6 +1364,7 @@ function dbg(text) {
return cString > 2 ? UTF8ToString(cString) : cString;
};
+ /** @type {Object} */
var specialHTMLTargets = [0, typeof document != 'undefined' ? document : 0, typeof window != 'undefined' ? window : 0];
var findEventTarget = (target) => {
target = maybeCStringToJsString(target);
@@ -1485,10 +1387,9 @@ function dbg(text) {
var _emscripten_is_main_browser_thread = () =>
!ENVIRONMENT_IS_WORKER;
- var _emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
-
var wasmTableMirror = [];
+ /** @type {WebAssembly.Table} */
var wasmTable;
var getWasmTableEntry = (funcPtr) => {
var func = wasmTableMirror[funcPtr];
@@ -1496,7 +1397,7 @@ function dbg(text) {
if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;
wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
}
- assert(wasmTable.get(funcPtr) == func, "JavaScript-side Wasm function table mirror is out of date!");
+ assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!');
return func;
};
var _emscripten_request_animation_frame_loop = (cb, userData) => {
@@ -1515,9 +1416,14 @@ function dbg(text) {
// casing all heap size related code to treat 0 specially.
2147483648;
+ var alignMemory = (size, alignment) => {
+ assert(alignment, "alignment argument is required");
+ return Math.ceil(size / alignment) * alignment;
+ };
+
var growMemory = (size) => {
var b = wasmMemory.buffer;
- var pages = (size - b.byteLength + 65535) / 65536;
+ var pages = ((size - b.byteLength + 65535) / 65536) | 0;
try {
// round size grow request up to wasm page size (fixed 64KB per spec)
wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size
@@ -1562,8 +1468,6 @@ function dbg(text) {
return false;
}
- var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
-
// Loop through potential heap size increases. If we attempt a too eager
// reservation that fails, cut down on the attempted size and reserve a
// smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
@@ -1572,7 +1476,7 @@ function dbg(text) {
// but limit overreserving (default to capping at +96MB overgrowth at most)
overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 );
- var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
+ var newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536));
var replacement = growMemory(newSize);
if (replacement) {
@@ -1585,7 +1489,7 @@ function dbg(text) {
};
- var findCanvasEventTarget = (target) => findEventTarget(target);
+ var findCanvasEventTarget = findEventTarget;
var _emscripten_set_canvas_element_size = (target, width, height) => {
var canvas = findCanvasEventTarget(target);
if (!canvas) return -4;
@@ -1600,34 +1504,35 @@ function dbg(text) {
var fillMouseEventData = (eventStruct, e, target) => {
assert(eventStruct % 4 == 0);
HEAPF64[((eventStruct)>>3)] = e.timeStamp;
- var idx = eventStruct >> 2;
+ var idx = ((eventStruct)>>2);
HEAP32[idx + 2] = e.screenX;
HEAP32[idx + 3] = e.screenY;
HEAP32[idx + 4] = e.clientX;
HEAP32[idx + 5] = e.clientY;
- HEAP32[idx + 6] = e.ctrlKey;
- HEAP32[idx + 7] = e.shiftKey;
- HEAP32[idx + 8] = e.altKey;
- HEAP32[idx + 9] = e.metaKey;
- HEAP16[idx*2 + 20] = e.button;
- HEAP16[idx*2 + 21] = e.buttons;
-
- HEAP32[idx + 11] = e["movementX"]
+ HEAP8[eventStruct + 24] = e.ctrlKey;
+ HEAP8[eventStruct + 25] = e.shiftKey;
+ HEAP8[eventStruct + 26] = e.altKey;
+ HEAP8[eventStruct + 27] = e.metaKey;
+ HEAP16[idx*2 + 14] = e.button;
+ HEAP16[idx*2 + 15] = e.buttons;
+
+ HEAP32[idx + 8] = e["movementX"]
;
- HEAP32[idx + 12] = e["movementY"]
+ HEAP32[idx + 9] = e["movementY"]
;
+ // Note: rect contains doubles (truncated to placate SAFE_HEAP, which is the same behaviour when writing to HEAP32 anyway)
var rect = getBoundingClientRect(target);
- HEAP32[idx + 13] = e.clientX - rect.left;
- HEAP32[idx + 14] = e.clientY - rect.top;
+ HEAP32[idx + 10] = e.clientX - (rect.left | 0);
+ HEAP32[idx + 11] = e.clientY - (rect.top | 0);
};
var registerMouseEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- if (!JSEvents.mouseEvent) JSEvents.mouseEvent = _malloc(72);
+ JSEvents.mouseEvent ||= _malloc(64);
target = findEventTarget(target);
var mouseEventHandlerFunc = (e = event) => {
@@ -1654,7 +1559,7 @@ function dbg(text) {
var registerUiEventCallback = (target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) => {
- if (!JSEvents.uiEvent) JSEvents.uiEvent = _malloc(36);
+ JSEvents.uiEvent ||= _malloc(36);
target = findEventTarget(target);
@@ -1672,15 +1577,15 @@ function dbg(text) {
return;
}
var uiEvent = JSEvents.uiEvent;
- HEAP32[((uiEvent)>>2)] = e.detail;
+ HEAP32[((uiEvent)>>2)] = 0; // always zero for resize and scroll
HEAP32[(((uiEvent)+(4))>>2)] = b.clientWidth;
HEAP32[(((uiEvent)+(8))>>2)] = b.clientHeight;
HEAP32[(((uiEvent)+(12))>>2)] = innerWidth;
HEAP32[(((uiEvent)+(16))>>2)] = innerHeight;
HEAP32[(((uiEvent)+(20))>>2)] = outerWidth;
HEAP32[(((uiEvent)+(24))>>2)] = outerHeight;
- HEAP32[(((uiEvent)+(28))>>2)] = pageXOffset;
- HEAP32[(((uiEvent)+(32))>>2)] = pageYOffset;
+ HEAP32[(((uiEvent)+(28))>>2)] = pageXOffset | 0; // scroll offsets are float
+ HEAP32[(((uiEvent)+(32))>>2)] = pageYOffset | 0;
if (getWasmTableEntry(callbackfunc)(eventTypeId, uiEvent, userData)) e.preventDefault();
};
@@ -1698,40 +1603,40 @@ function dbg(text) {
- function handleAllocatorInit() {
- Object.assign(HandleAllocator.prototype, /** @lends {HandleAllocator.prototype} */ {
- get(id) {
- assert(this.allocated[id] !== undefined, `invalid handle: ${id}`);
- return this.allocated[id];
- },
- has(id) {
- return this.allocated[id] !== undefined;
- },
- allocate(handle) {
- var id = this.freelist.pop() || this.allocated.length;
- this.allocated[id] = handle;
- return id;
- },
- free(id) {
- assert(this.allocated[id] !== undefined);
- // Set the slot to `undefined` rather than using `delete` here since
- // apparently arrays with holes in them can be less efficient.
- this.allocated[id] = undefined;
- this.freelist.push(id);
- }
- });
- }
- /** @constructor */
- function HandleAllocator() {
- // Reserve slot 0 so that 0 is always an invalid handle
- this.allocated = [undefined];
- this.freelist = [];
+ class HandleAllocator {
+ constructor() {
+ // TODO(https://github.com/emscripten-core/emscripten/issues/21414):
+ // Use inline field declarations.
+ this.allocated = [undefined];
+ this.freelist = [];
+ }
+ get(id) {
+ assert(this.allocated[id] !== undefined, `invalid handle: ${id}`);
+ return this.allocated[id];
+ }
+ has(id) {
+ return this.allocated[id] !== undefined;
+ }
+ allocate(handle) {
+ var id = this.freelist.pop() || this.allocated.length;
+ this.allocated[id] = handle;
+ return id;
+ }
+ free(id) {
+ assert(this.allocated[id] !== undefined);
+ // Set the slot to `undefined` rather than using `delete` here since
+ // apparently arrays with holes in them can be less efficient.
+ this.allocated[id] = undefined;
+ this.freelist.push(id);
+ }
}
var Fetch = {
openDatabase(dbname, dbversion, onsuccess, onerror) {
try {
var openRequest = indexedDB.open(dbname, dbversion);
- } catch (e) { return onerror(e); }
+ } catch (e) {
+ return onerror(e);
+ }
openRequest.onupgradeneeded = (event) => {
var db = /** @type {IDBDatabase} */ (event.target.result);
@@ -1741,7 +1646,7 @@ function dbg(text) {
db.createObjectStore('FILES');
};
openRequest.onsuccess = (event) => onsuccess(event.target.result);
- openRequest.onerror = (error) => onerror(error);
+ openRequest.onerror = onerror;
},
init() {
Fetch.xhrs = new HandleAllocator();
@@ -1768,9 +1673,9 @@ function dbg(text) {
}
var url_ = UTF8ToString(url);
- var fetch_attr = fetch + 112;
+ var fetch_attr = fetch + 108;
var requestMethod = UTF8ToString(fetch_attr + 0);
- if (!requestMethod) requestMethod = 'GET';
+ requestMethod ||= 'GET';
var timeoutMsecs = HEAPU32[(((fetch_attr)+(56))>>2)];
var userName = HEAPU32[(((fetch_attr)+(68))>>2)];
var password = HEAPU32[(((fetch_attr)+(72))>>2)];
@@ -1788,7 +1693,7 @@ function dbg(text) {
var passwordStr = password ? UTF8ToString(password) : undefined;
var xhr = new XMLHttpRequest();
- xhr.withCredentials = !!HEAPU8[(((fetch_attr)+(60))>>0)];;
+ xhr.withCredentials = !!HEAPU8[(fetch_attr)+(60)];;
xhr.open(requestMethod, url_, !fetchAttrSynchronous, userNameStr, passwordStr);
if (!fetchAttrSynchronous) xhr.timeout = timeoutMsecs; // XHR timeout field is only accessible in async XHRs, and must be set after .open() but before .send().
xhr.url_ = url_; // Save the url for debugging purposes (and for comparing to the responseURL that server side advertised)
@@ -1824,7 +1729,7 @@ function dbg(text) {
function saveResponseAndStatus() {
var ptr = 0;
var ptrLen = 0;
- if (xhr.response && fetchAttrLoadToMemory && HEAPU32[fetch + 12 >> 2] === 0) {
+ if (xhr.response && fetchAttrLoadToMemory && HEAPU32[(((fetch)+(12))>>2)] === 0) {
ptrLen = xhr.response.byteLength;
}
if (ptrLen > 0) {
@@ -1833,7 +1738,7 @@ function dbg(text) {
ptr = _malloc(ptrLen);
HEAPU8.set(new Uint8Array(/** @type{Array<number>} */(xhr.response)), ptr);
}
- HEAPU32[fetch + 12 >> 2] = ptr;
+ HEAPU32[(((fetch)+(12))>>2)] = ptr
writeI53ToI64(fetch + 16, ptrLen);
writeI53ToI64(fetch + 24, 0);
var len = xhr.response ? xhr.response.byteLength : 0;
@@ -1843,8 +1748,8 @@ function dbg(text) {
// the most recent XHR.onprogress handler.
writeI53ToI64(fetch + 32, len);
}
- HEAPU16[fetch + 40 >> 1] = xhr.readyState;
- HEAPU16[fetch + 42 >> 1] = xhr.status;
+ HEAP16[(((fetch)+(40))>>1)] = xhr.readyState
+ HEAP16[(((fetch)+(42))>>1)] = xhr.status
if (xhr.statusText) stringToUTF8(xhr.statusText, fetch + 44, 64);
}
@@ -1855,9 +1760,9 @@ function dbg(text) {
}
saveResponseAndStatus();
if (xhr.status >= 200 && xhr.status < 300) {
- if (onsuccess) onsuccess(fetch, xhr, e);
+ onsuccess?.(fetch, xhr, e);
} else {
- if (onerror) onerror(fetch, xhr, e);
+ onerror?.(fetch, xhr, e);
}
};
xhr.onerror = (e) => {
@@ -1866,14 +1771,14 @@ function dbg(text) {
return;
}
saveResponseAndStatus();
- if (onerror) onerror(fetch, xhr, e);
+ onerror?.(fetch, xhr, e);
};
xhr.ontimeout = (e) => {
// check if xhr was aborted by user and don't try to call back
if (!Fetch.xhrs.has(id)) {
return;
}
- if (onerror) onerror(fetch, xhr, e);
+ onerror?.(fetch, xhr, e);
};
xhr.onprogress = (e) => {
// check if xhr was aborted by user and don't try to call back
@@ -1888,16 +1793,16 @@ function dbg(text) {
ptr = _malloc(ptrLen);
HEAPU8.set(new Uint8Array(/** @type{Array<number>} */(xhr.response)), ptr);
}
- HEAPU32[fetch + 12 >> 2] = ptr;
+ HEAPU32[(((fetch)+(12))>>2)] = ptr
writeI53ToI64(fetch + 16, ptrLen);
writeI53ToI64(fetch + 24, e.loaded - ptrLen);
writeI53ToI64(fetch + 32, e.total);
- HEAPU16[fetch + 40 >> 1] = xhr.readyState;
+ HEAP16[(((fetch)+(40))>>1)] = xhr.readyState
// If loading files from a source that does not give HTTP status code, assume success if we get data bytes
if (xhr.readyState >= 3 && xhr.status === 0 && e.loaded > 0) xhr.status = 200;
- HEAPU16[fetch + 42 >> 1] = xhr.status;
+ HEAP16[(((fetch)+(42))>>1)] = xhr.status
if (xhr.statusText) stringToUTF8(xhr.statusText, fetch + 44, 64);
- if (onprogress) onprogress(fetch, xhr, e);
+ onprogress?.(fetch, xhr, e);
if (ptr) {
_free(ptr);
}
@@ -1908,16 +1813,16 @@ function dbg(text) {
return;
}
- HEAPU16[fetch + 40 >> 1] = xhr.readyState;
+ HEAP16[(((fetch)+(40))>>1)] = xhr.readyState
if (xhr.readyState >= 2) {
- HEAPU16[fetch + 42 >> 1] = xhr.status;
+ HEAP16[(((fetch)+(42))>>1)] = xhr.status
}
- if (onreadystatechange) onreadystatechange(fetch, xhr, e);
+ onreadystatechange?.(fetch, xhr, e);
};
try {
xhr.send(data);
} catch(e) {
- if (onerror) onerror(fetch, xhr, e);
+ onerror?.(fetch, xhr, e);
}
}
@@ -1940,29 +1845,17 @@ function dbg(text) {
};
- var SYSCALLS = {
- varargs:undefined,
- get() {
- assert(SYSCALLS.varargs != undefined);
- // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number.
- var ret = HEAP32[((+SYSCALLS.varargs)>>2)];
- SYSCALLS.varargs += 4;
- return ret;
- },
- getp() { return SYSCALLS.get() },
- getStr(ptr) {
- var ret = UTF8ToString(ptr);
- return ret;
- },
- };
+ var runtimeKeepaliveCounter = 0;
+ var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
var _proc_exit = (code) => {
EXITSTATUS = code;
if (!keepRuntimeAlive()) {
- if (Module['onExit']) Module['onExit'](code);
+ Module['onExit']?.(code);
ABORT = true;
}
quit_(code, new ExitStatus(code));
};
+
/** @suppress {duplicate } */
/** @param {boolean|number=} implicit */
var exitJS = (status, implicit) => {
@@ -1980,6 +1873,7 @@ function dbg(text) {
};
var _exit = exitJS;
+
var maybeExit = () => {
if (!keepRuntimeAlive()) {
try {
@@ -2025,9 +1919,9 @@ function dbg(text) {
return;
}
- var fetch_attr = fetch + 112;
- var destinationPath = HEAPU32[fetch_attr + 64 >> 2];
- if (!destinationPath) destinationPath = HEAPU32[fetch + 8 >> 2];
+ var fetch_attr = fetch + 108;
+ var destinationPath = HEAPU32[(((fetch_attr)+(64))>>2)];
+ destinationPath ||= HEAPU32[(((fetch)+(8))>>2)];
var destinationPathStr = UTF8ToString(destinationPath);
try {
@@ -2035,8 +1929,8 @@ function dbg(text) {
var packages = transaction.objectStore('FILES');
var putRequest = packages.put(data, destinationPathStr);
putRequest.onsuccess = (event) => {
- HEAPU16[fetch + 40 >> 1] = 4; // Mimic XHR readyState 4 === 'DONE: The operation is complete'
- HEAPU16[fetch + 42 >> 1] = 200; // Mimic XHR HTTP status code 200 "OK"
+ HEAP16[(((fetch)+(40))>>1)] = 4 // Mimic XHR readyState 4 === 'DONE: The operation is complete'
+ HEAP16[(((fetch)+(42))>>1)] = 200 // Mimic XHR HTTP status code 200 "OK"
stringToUTF8("OK", fetch + 44, 64);
onsuccess(fetch, 0, destinationPathStr);
};
@@ -2044,8 +1938,8 @@ function dbg(text) {
// Most likely we got an error if IndexedDB is unwilling to store any more data for this page.
// TODO: Can we identify and break down different IndexedDB-provided errors and convert those
// to more HTTP status codes for more information?
- HEAPU16[fetch + 40 >> 1] = 4; // Mimic XHR readyState 4 === 'DONE: The operation is complete'
- HEAPU16[fetch + 42 >> 1] = 413; // Mimic XHR HTTP status code 413 "Payload Too Large"
+ HEAP16[(((fetch)+(40))>>1)] = 4 // Mimic XHR readyState 4 === 'DONE: The operation is complete'
+ HEAP16[(((fetch)+(42))>>1)] = 413 // Mimic XHR HTTP status code 413 "Payload Too Large"
stringToUTF8("Payload Too Large", fetch + 44, 64);
onerror(fetch, 0, error);
};
@@ -2060,9 +1954,9 @@ function dbg(text) {
return;
}
- var fetch_attr = fetch + 112;
- var path = HEAPU32[fetch_attr + 64 >> 2];
- if (!path) path = HEAPU32[fetch + 8 >> 2];
+ var fetch_attr = fetch + 108;
+ var path = HEAPU32[(((fetch_attr)+(64))>>2)];
+ path ||= HEAPU32[(((fetch)+(8))>>2)];
var pathStr = UTF8ToString(path);
try {
@@ -2077,25 +1971,25 @@ function dbg(text) {
// freed when emscripten_fetch_close() is called.
var ptr = _malloc(len);
HEAPU8.set(new Uint8Array(value), ptr);
- HEAPU32[fetch + 12 >> 2] = ptr;
+ HEAPU32[(((fetch)+(12))>>2)] = ptr;
writeI53ToI64(fetch + 16, len);
writeI53ToI64(fetch + 24, 0);
writeI53ToI64(fetch + 32, len);
- HEAPU16[fetch + 40 >> 1] = 4; // Mimic XHR readyState 4 === 'DONE: The operation is complete'
- HEAPU16[fetch + 42 >> 1] = 200; // Mimic XHR HTTP status code 200 "OK"
+ HEAP16[(((fetch)+(40))>>1)] = 4 // Mimic XHR readyState 4 === 'DONE: The operation is complete'
+ HEAP16[(((fetch)+(42))>>1)] = 200 // Mimic XHR HTTP status code 200 "OK"
stringToUTF8("OK", fetch + 44, 64);
onsuccess(fetch, 0, value);
} else {
// Succeeded to load, but the load came back with the value of undefined, treat that as an error since we never store undefined in db.
- HEAPU16[fetch + 40 >> 1] = 4; // Mimic XHR readyState 4 === 'DONE: The operation is complete'
- HEAPU16[fetch + 42 >> 1] = 404; // Mimic XHR HTTP status code 404 "Not Found"
+ HEAP16[(((fetch)+(40))>>1)] = 4 // Mimic XHR readyState 4 === 'DONE: The operation is complete'
+ HEAP16[(((fetch)+(42))>>1)] = 404 // Mimic XHR HTTP status code 404 "Not Found"
stringToUTF8("Not Found", fetch + 44, 64);
onerror(fetch, 0, 'no data');
}
};
getRequest.onerror = (error) => {
- HEAPU16[fetch + 40 >> 1] = 4; // Mimic XHR readyState 4 === 'DONE: The operation is complete'
- HEAPU16[fetch + 42 >> 1] = 404; // Mimic XHR HTTP status code 404 "Not Found"
+ HEAP16[(((fetch)+(40))>>1)] = 4 // Mimic XHR readyState 4 === 'DONE: The operation is complete'
+ HEAP16[(((fetch)+(42))>>1)] = 404 // Mimic XHR HTTP status code 404 "Not Found"
stringToUTF8("Not Found", fetch + 44, 64);
onerror(fetch, 0, error);
};
@@ -2110,9 +2004,10 @@ function dbg(text) {
return;
}
- var fetch_attr = fetch + 112;
- var path = HEAPU32[fetch_attr + 64 >> 2];
- if (!path) path = HEAPU32[fetch + 8 >> 2];
+ var fetch_attr = fetch + 108;
+ var path = HEAPU32[(((fetch_attr)+(64))>>2)];
+ path ||= HEAPU32[(((fetch)+(8))>>2)];
+
var pathStr = UTF8ToString(path);
try {
@@ -2121,18 +2016,20 @@ function dbg(text) {
var request = packages.delete(pathStr);
request.onsuccess = (event) => {
var value = event.target.result;
- HEAPU32[fetch + 12 >> 2] = 0;
+ HEAPU32[(((fetch)+(12))>>2)] = 0;
writeI53ToI64(fetch + 16, 0);
writeI53ToI64(fetch + 24, 0);
writeI53ToI64(fetch + 32, 0);
- HEAPU16[fetch + 40 >> 1] = 4; // Mimic XHR readyState 4 === 'DONE: The operation is complete'
- HEAPU16[fetch + 42 >> 1] = 200; // Mimic XHR HTTP status code 200 "OK"
+ // Mimic XHR readyState 4 === 'DONE: The operation is complete'
+ HEAP16[(((fetch)+(40))>>1)] = 4;
+ // Mimic XHR HTTP status code 200 "OK"
+ HEAP16[(((fetch)+(42))>>1)] = 200;
stringToUTF8("OK", fetch + 44, 64);
onsuccess(fetch, 0, value);
};
request.onerror = (error) => {
- HEAPU16[fetch + 40 >> 1] = 4; // Mimic XHR readyState 4 === 'DONE: The operation is complete'
- HEAPU16[fetch + 42 >> 1] = 404; // Mimic XHR HTTP status code 404 "Not Found"
+ HEAP16[(((fetch)+(40))>>1)] = 4 // Mimic XHR readyState 4 === 'DONE: The operation is complete'
+ HEAP16[(((fetch)+(42))>>1)] = 404 // Mimic XHR HTTP status code 404 "Not Found"
stringToUTF8("Not Found", fetch + 44, 64);
onerror(fetch, 0, error);
};
@@ -2147,12 +2044,12 @@ function dbg(text) {
// response.
- var fetch_attr = fetch + 112;
- var onsuccess = HEAPU32[fetch_attr + 36 >> 2];
- var onerror = HEAPU32[fetch_attr + 40 >> 2];
- var onprogress = HEAPU32[fetch_attr + 44 >> 2];
- var onreadystatechange = HEAPU32[fetch_attr + 48 >> 2];
- var fetchAttributes = HEAPU32[fetch_attr + 52 >> 2];
+ var fetch_attr = fetch + 108;
+ var onsuccess = HEAPU32[(((fetch_attr)+(36))>>2)];
+ var onerror = HEAPU32[(((fetch_attr)+(40))>>2)];
+ var onprogress = HEAPU32[(((fetch_attr)+(44))>>2)];
+ var onreadystatechange = HEAPU32[(((fetch_attr)+(48))>>2)];
+ var fetchAttributes = HEAPU32[(((fetch_attr)+(52))>>2)];
var fetchAttrSynchronous = !!(fetchAttributes & 64);
function doCallback(f) {
@@ -2167,14 +2064,14 @@ function dbg(text) {
doCallback(() => {
if (onsuccess) getWasmTableEntry(onsuccess)(fetch);
- else if (successcb) successcb(fetch);
+ else successcb?.(fetch);
});
};
var reportProgress = (fetch, xhr, e) => {
doCallback(() => {
if (onprogress) getWasmTableEntry(onprogress)(fetch);
- else if (progresscb) progresscb(fetch);
+ else progresscb?.(fetch);
});
};
@@ -2182,14 +2079,14 @@ function dbg(text) {
doCallback(() => {
if (onerror) getWasmTableEntry(onerror)(fetch);
- else if (errorcb) errorcb(fetch);
+ else errorcb?.(fetch);
});
};
var reportReadyStateChange = (fetch, xhr, e) => {
doCallback(() => {
if (onreadystatechange) getWasmTableEntry(onreadystatechange)(fetch);
- else if (readystatechangecb) readystatechangecb(fetch);
+ else readystatechangecb?.(fetch);
});
};
@@ -2202,14 +2099,14 @@ function dbg(text) {
doCallback(() => {
if (onsuccess) getWasmTableEntry(onsuccess)(fetch);
- else if (successcb) successcb(fetch);
+ else successcb?.(fetch);
});
};
var storeError = (fetch, xhr, e) => {
doCallback(() => {
if (onsuccess) getWasmTableEntry(onsuccess)(fetch);
- else if (successcb) successcb(fetch);
+ else successcb?.(fetch);
});
};
fetchCacheData(Fetch.dbInstance, fetch, xhr.response, storeSuccess, storeError);
@@ -2240,9 +2137,14 @@ function dbg(text) {
return fetch;
}
+ var GLctx;
+
var webgl_enable_ANGLE_instanced_arrays = (ctx) => {
// Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2.
var ext = ctx.getExtension('ANGLE_instanced_arrays');
+ // Because this extension is a core function in WebGL 2, assign the extension entry points in place of
+ // where the core functions will reside in WebGL 2. This way the calling code can call these without
+ // having to dynamically branch depending if running against WebGL 1 or WebGL 2.
if (ext) {
ctx['vertexAttribDivisor'] = (index, divisor) => ext['vertexAttribDivisorANGLE'](index, divisor);
ctx['drawArraysInstanced'] = (mode, first, count, primcount) => ext['drawArraysInstancedANGLE'](mode, first, count, primcount);
@@ -2281,11 +2183,83 @@ function dbg(text) {
return !!(ctx.mdibvbi = ctx.getExtension('WEBGL_multi_draw_instanced_base_vertex_base_instance'));
};
+ var webgl_enable_EXT_polygon_offset_clamp = (ctx) => {
+ return !!(ctx.extPolygonOffsetClamp = ctx.getExtension('EXT_polygon_offset_clamp'));
+ };
+
+ var webgl_enable_EXT_clip_control = (ctx) => {
+ return !!(ctx.extClipControl = ctx.getExtension('EXT_clip_control'));
+ };
+
+ var webgl_enable_WEBGL_polygon_mode = (ctx) => {
+ return !!(ctx.webglPolygonMode = ctx.getExtension('WEBGL_polygon_mode'));
+ };
+
var webgl_enable_WEBGL_multi_draw = (ctx) => {
// Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted.
return !!(ctx.multiDrawWebgl = ctx.getExtension('WEBGL_multi_draw'));
};
+ var getEmscriptenSupportedExtensions = (ctx) => {
+ // Restrict the list of advertised extensions to those that we actually
+ // support.
+ var supportedExtensions = [
+ // WebGL 1 extensions
+ 'ANGLE_instanced_arrays',
+ 'EXT_blend_minmax',
+ 'EXT_disjoint_timer_query',
+ 'EXT_frag_depth',
+ 'EXT_shader_texture_lod',
+ 'EXT_sRGB',
+ 'OES_element_index_uint',
+ 'OES_fbo_render_mipmap',
+ 'OES_standard_derivatives',
+ 'OES_texture_float',
+ 'OES_texture_half_float',
+ 'OES_texture_half_float_linear',
+ 'OES_vertex_array_object',
+ 'WEBGL_color_buffer_float',
+ 'WEBGL_depth_texture',
+ 'WEBGL_draw_buffers',
+ // WebGL 2 extensions
+ 'EXT_color_buffer_float',
+ 'EXT_conservative_depth',
+ 'EXT_disjoint_timer_query_webgl2',
+ 'EXT_texture_norm16',
+ 'NV_shader_noperspective_interpolation',
+ 'WEBGL_clip_cull_distance',
+ // WebGL 1 and WebGL 2 extensions
+ 'EXT_clip_control',
+ 'EXT_color_buffer_half_float',
+ 'EXT_depth_clamp',
+ 'EXT_float_blend',
+ 'EXT_polygon_offset_clamp',
+ 'EXT_texture_compression_bptc',
+ 'EXT_texture_compression_rgtc',
+ 'EXT_texture_filter_anisotropic',
+ 'KHR_parallel_shader_compile',
+ 'OES_texture_float_linear',
+ 'WEBGL_blend_func_extended',
+ 'WEBGL_compressed_texture_astc',
+ 'WEBGL_compressed_texture_etc',
+ 'WEBGL_compressed_texture_etc1',
+ 'WEBGL_compressed_texture_s3tc',
+ 'WEBGL_compressed_texture_s3tc_srgb',
+ 'WEBGL_debug_renderer_info',
+ 'WEBGL_debug_shaders',
+ 'WEBGL_lose_context',
+ 'WEBGL_multi_draw',
+ 'WEBGL_polygon_mode'
+ ];
+ // .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
+ return (ctx.getSupportedExtensions() || []).filter(ext => supportedExtensions.includes(ext));
+ };
+
+ var registerPreMainLoop = (f) => {
+ // Does nothing unless $MainLoop is included/used.
+ typeof MainLoop != 'undefined' && MainLoop.preMainLoop.push(f);
+ };
+
var GL = {
counter:1,
@@ -2312,7 +2286,8 @@ function dbg(text) {
stringiCache:{
},
unpackAlignment:4,
- recordError:function recordError(errorCode) {
+ unpackRowLength:0,
+ recordError:(errorCode) => {
if (!GL.lastError) {
GL.lastError = errorCode;
}
@@ -2324,11 +2299,23 @@ function dbg(text) {
}
return ret;
},
+ genObject:(n, buffers, createFunction, objectTable
+ ) => {
+ for (var i = 0; i < n; i++) {
+ var buffer = GLctx[createFunction]();
+ var id = buffer && GL.getNewId(objectTable);
+ if (buffer) {
+ buffer.name = id;
+ objectTable[id] = buffer;
+ } else {
+ GL.recordError(0x502 /* GL_INVALID_OPERATION */);
+ }
+ HEAP32[(((buffers)+(i*4))>>2)] = id;
+ }
+ },
MAX_TEMP_BUFFER_SIZE:2097152,
numTempVertexBuffersPerSize:64,
- log2ceilLookup:(i) => {
- return 32 - Math.clz32(i === 0 ? 0 : i - 1);
- },
+ log2ceilLookup:(i) => 32 - Math.clz32(i === 0 ? 0 : i - 1),
generateTempBuffers:(quads, context) => {
var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
context.tempVertexBufferCounters1 = [];
@@ -2379,7 +2366,7 @@ function dbg(text) {
context.GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, null);
}
},
- getTempVertexBuffer:function getTempVertexBuffer(sizeBytes) {
+ getTempVertexBuffer:(sizeBytes) => {
var idx = GL.log2ceilLookup(sizeBytes);
var ringbuffer = GL.currentContext.tempVertexBuffers1[idx];
var nextFreeBufferIndex = GL.currentContext.tempVertexBufferCounters1[idx];
@@ -2395,7 +2382,7 @@ function dbg(text) {
GLctx.bindBuffer(0x8892 /*GL_ARRAY_BUFFER*/, prevVBO);
return ringbuffer[nextFreeBufferIndex];
},
- getTempIndexBuffer:function getTempIndexBuffer(sizeBytes) {
+ getTempIndexBuffer:(sizeBytes) => {
var idx = GL.log2ceilLookup(sizeBytes);
var ibo = GL.currentContext.tempIndexBuffers[idx];
if (ibo) {
@@ -2408,7 +2395,7 @@ function dbg(text) {
GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, prevIBO);
return GL.currentContext.tempIndexBuffers[idx];
},
- newRenderingFrameStarted:function newRenderingFrameStarted() {
+ newRenderingFrameStarted:() => {
if (!GL.currentContext) {
return;
}
@@ -2426,12 +2413,12 @@ function dbg(text) {
getSource:(shader, count, string, length) => {
var source = '';
for (var i = 0; i < count; ++i) {
- var len = length ? HEAP32[(((length)+(i*4))>>2)] : -1;
- source += UTF8ToString(HEAP32[(((string)+(i*4))>>2)], len < 0 ? undefined : len);
+ var len = length ? HEAPU32[(((length)+(i*4))>>2)] : undefined;
+ source += UTF8ToString(HEAPU32[(((string)+(i*4))>>2)], len);
}
return source;
},
- calcBufLength:function calcBufLength(size, type, stride, count) {
+ calcBufLength:(size, type, stride, count) => {
if (stride > 0) {
return count * stride; // XXXvlad this is not exactly correct I don't think
}
@@ -2439,10 +2426,11 @@ function dbg(text) {
return size * typeSize * count;
},
usedTempBuffers:[],
- preDrawHandleClientVertexAttribBindings:function preDrawHandleClientVertexAttribBindings(count) {
+ preDrawHandleClientVertexAttribBindings:(count) => {
GL.resetBufferBinding = false;
- // TODO: initial pass to detect ranges we need to upload, might not need an upload per attrib
+ // TODO: initial pass to detect ranges we need to upload, might not need
+ // an upload per attrib
for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) {
var cb = GL.currentContext.clientBuffers[i];
if (!cb.clientside || !cb.enabled) continue;
@@ -2458,18 +2446,22 @@ function dbg(text) {
cb.vertexAttribPointerAdaptor.call(GLctx, i, cb.size, cb.type, cb.normalized, cb.stride, 0);
}
},
- postDrawHandleClientVertexAttribBindings:function postDrawHandleClientVertexAttribBindings() {
+ postDrawHandleClientVertexAttribBindings:() => {
if (GL.resetBufferBinding) {
GLctx.bindBuffer(0x8892 /*GL_ARRAY_BUFFER*/, GL.buffers[GLctx.currentArrayBufferBinding]);
}
},
createContext:(/** @type {HTMLCanvasElement} */ canvas, webGLContextAttributes) => {
- // BUG: Workaround Safari WebGL issue: After successfully acquiring WebGL context on a canvas,
- // calling .getContext() will always return that context independent of which 'webgl' or 'webgl2'
- // context version was passed. See https://bugs.webkit.org/show_bug.cgi?id=222758 and
- // https://github.com/emscripten-core/emscripten/issues/13295.
- // TODO: Once the bug is fixed and shipped in Safari, adjust the Safari version field in above check.
+ // BUG: Workaround Safari WebGL issue: After successfully acquiring WebGL
+ // context on a canvas, calling .getContext() will always return that
+ // context independent of which 'webgl' or 'webgl2'
+ // context version was passed. See:
+ // https://bugs.webkit.org/show_bug.cgi?id=222758
+ // and:
+ // https://github.com/emscripten-core/emscripten/issues/13295.
+ // TODO: Once the bug is fixed and shipped in Safari, adjust the Safari
+ // version field in above check.
if (!canvas.getContextSafariWebGL2Fixed) {
canvas.getContextSafariWebGL2Fixed = canvas.getContext;
/** @type {function(this:HTMLCanvasElement, string, (Object|null)=): (Object|null)} */
@@ -2506,7 +2498,8 @@ function dbg(text) {
GLctx: ctx
};
- // Store the created context object so that we can access the context given a canvas without having to pass the parameters again.
+ // Store the created context object so that we can access the context
+ // given a canvas without having to pass the parameters again.
if (ctx.canvas) ctx.canvas.GLctxObject = context;
GL.contexts[handle] = context;
if (typeof webGLContextAttributes.enableExtensionsByDefault == 'undefined' || webGLContextAttributes.enableExtensionsByDefault) {
@@ -2516,7 +2509,16 @@ function dbg(text) {
context.maxVertexAttribs = context.GLctx.getParameter(0x8869 /*GL_MAX_VERTEX_ATTRIBS*/);
context.clientBuffers = [];
for (var i = 0; i < context.maxVertexAttribs; i++) {
- context.clientBuffers[i] = { enabled: false, clientside: false, size: 0, type: 0, normalized: 0, stride: 0, ptr: 0, vertexAttribPointerAdaptor: null };
+ context.clientBuffers[i] = {
+ enabled: false,
+ clientside: false,
+ size: 0,
+ type: 0,
+ normalized: 0,
+ stride: 0,
+ ptr: 0,
+ vertexAttribPointerAdaptor: null,
+ };
}
GL.generateTempBuffers(false, context);
@@ -2525,31 +2527,51 @@ function dbg(text) {
},
makeContextCurrent:(contextHandle) => {
- GL.currentContext = GL.contexts[contextHandle]; // Active Emscripten GL layer context object.
- Module.ctx = GLctx = GL.currentContext && GL.currentContext.GLctx; // Active WebGL context object.
+ // Active Emscripten GL layer context object.
+ GL.currentContext = GL.contexts[contextHandle];
+ // Active WebGL context object.
+ Module.ctx = GLctx = GL.currentContext?.GLctx;
return !(contextHandle && !GLctx);
},
getContext:(contextHandle) => {
return GL.contexts[contextHandle];
},
deleteContext:(contextHandle) => {
- if (GL.currentContext === GL.contexts[contextHandle]) GL.currentContext = null;
- if (typeof JSEvents == 'object') JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas); // Release all JS event handlers on the DOM element that the GL context is associated with since the context is now deleted.
- if (GL.contexts[contextHandle] && GL.contexts[contextHandle].GLctx.canvas) GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined; // Make sure the canvas object no longer refers to the context object so there are no GC surprises.
+ if (GL.currentContext === GL.contexts[contextHandle]) {
+ GL.currentContext = null;
+ }
+ if (typeof JSEvents == 'object') {
+ // Release all JS event handlers on the DOM element that the GL context is
+ // associated with since the context is now deleted.
+ JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);
+ }
+ // Make sure the canvas object no longer refers to the context object so
+ // there are no GC surprises.
+ if (GL.contexts[contextHandle] && GL.contexts[contextHandle].GLctx.canvas) {
+ GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined;
+ }
GL.contexts[contextHandle] = null;
},
initExtensions:(context) => {
- // If this function is called without a specific context object, init the extensions of the currently active context.
- if (!context) context = GL.currentContext;
+ // If this function is called without a specific context object, init the
+ // extensions of the currently active context.
+ context ||= GL.currentContext;
if (context.initExtensionsDone) return;
context.initExtensionsDone = true;
var GLctx = context.GLctx;
- // Detect the presence of a few extensions manually, ction GL interop layer itself will need to know if they exist.
+ // Detect the presence of a few extensions manually, ction GL interop
+ // layer itself will need to know if they exist.
- // Extensions that are only available in WebGL 1 (the calls will be no-ops if called on a WebGL 2 context active)
+ // Extensions that are available in both WebGL 1 and WebGL 2
+ webgl_enable_WEBGL_multi_draw(GLctx);
+ webgl_enable_EXT_polygon_offset_clamp(GLctx);
+ webgl_enable_EXT_clip_control(GLctx);
+ webgl_enable_WEBGL_polygon_mode(GLctx);
+ // Extensions that are only available in WebGL 1 (the calls will be no-ops
+ // if called on a WebGL 2 context active)
webgl_enable_ANGLE_instanced_arrays(GLctx);
webgl_enable_OES_vertex_array_object(GLctx);
webgl_enable_WEBGL_draw_buffers(GLctx);
@@ -2572,12 +2594,9 @@ function dbg(text) {
GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
}
- webgl_enable_WEBGL_multi_draw(GLctx);
-
- // .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
- var exts = GLctx.getSupportedExtensions() || [];
- exts.forEach((ext) => {
- // WEBGL_lose_context, WEBGL_debug_renderer_info and WEBGL_debug_shaders are not enabled by default.
+ getEmscriptenSupportedExtensions(GLctx).forEach((ext) => {
+ // WEBGL_lose_context, WEBGL_debug_renderer_info and WEBGL_debug_shaders
+ // are not enabled by default.
if (!ext.includes('lose_context') && !ext.includes('debug')) {
// Call .getExtension() to enable that extension permanently.
GLctx.getExtension(ext);
@@ -2587,31 +2606,31 @@ function dbg(text) {
};
- var emscripten_webgl_power_preferences = ['default', 'low-power', 'high-performance'];
+ var webglPowerPreferences = ["default","low-power","high-performance"];
/** @suppress {duplicate } */
var _emscripten_webgl_do_create_context = (target, attributes) => {
assert(attributes);
- var a = attributes >> 2;
- var powerPreference = HEAP32[a + (24>>2)];
+ var attr32 = ((attributes)>>2);
+ var powerPreference = HEAP32[attr32 + (8>>2)];
var contextAttributes = {
- 'alpha': !!HEAP32[a + (0>>2)],
- 'depth': !!HEAP32[a + (4>>2)],
- 'stencil': !!HEAP32[a + (8>>2)],
- 'antialias': !!HEAP32[a + (12>>2)],
- 'premultipliedAlpha': !!HEAP32[a + (16>>2)],
- 'preserveDrawingBuffer': !!HEAP32[a + (20>>2)],
- 'powerPreference': emscripten_webgl_power_preferences[powerPreference],
- 'failIfMajorPerformanceCaveat': !!HEAP32[a + (28>>2)],
+ 'alpha': !!HEAP8[attributes + 0],
+ 'depth': !!HEAP8[attributes + 1],
+ 'stencil': !!HEAP8[attributes + 2],
+ 'antialias': !!HEAP8[attributes + 3],
+ 'premultipliedAlpha': !!HEAP8[attributes + 4],
+ 'preserveDrawingBuffer': !!HEAP8[attributes + 5],
+ 'powerPreference': webglPowerPreferences[powerPreference],
+ 'failIfMajorPerformanceCaveat': !!HEAP8[attributes + 12],
// The following are not predefined WebGL context attributes in the WebGL specification, so the property names can be minified by Closure.
- majorVersion: HEAP32[a + (32>>2)],
- minorVersion: HEAP32[a + (36>>2)],
- enableExtensionsByDefault: HEAP32[a + (40>>2)],
- explicitSwapControl: HEAP32[a + (44>>2)],
- proxyContextToMainThread: HEAP32[a + (48>>2)],
- renderViaOffscreenBackBuffer: HEAP32[a + (52>>2)]
+ majorVersion: HEAP32[attr32 + (16>>2)],
+ minorVersion: HEAP32[attr32 + (20>>2)],
+ enableExtensionsByDefault: HEAP8[attributes + 24],
+ explicitSwapControl: HEAP8[attributes + 25],
+ proxyContextToMainThread: HEAP32[attr32 + (28>>2)],
+ renderViaOffscreenBackBuffer: HEAP8[attributes + 32]
};
var canvas = findCanvasEventTarget(target);
@@ -2629,34 +2648,24 @@ function dbg(text) {
};
var _emscripten_webgl_create_context = _emscripten_webgl_do_create_context;
- var _emscripten_webgl_init_context_attributes = (attributes) => {
- assert(attributes);
- var a = attributes >> 2;
- for (var i = 0; i < (56>>2); ++i) {
- HEAP32[a+i] = 0;
- }
-
- HEAP32[a + (0>>2)] =
- HEAP32[a + (4>>2)] =
- HEAP32[a + (12>>2)] =
- HEAP32[a + (16>>2)] =
- HEAP32[a + (32>>2)] =
- HEAP32[a + (40>>2)] = 1;
-
- };
-
var _emscripten_webgl_make_context_current = (contextHandle) => {
var success = GL.makeContextCurrent(contextHandle);
return success ? 0 : -5;
};
+ var SYSCALLS = {
+ varargs:undefined,
+ getStr(ptr) {
+ var ret = UTF8ToString(ptr);
+ return ret;
+ },
+ };
var _fd_close = (fd) => {
abort('fd_close called without SYSCALLS_REQUIRE_FILESYSTEM');
};
-
function _fd_seek(fd,offset_low, offset_high,whence,newOffset) {
- var offset = convertI32PairToI53Checked(offset_low, offset_high);;
+ var offset = convertI32PairToI53Checked(offset_low, offset_high);
return 70;
@@ -2669,7 +2678,7 @@ function dbg(text) {
var buffer = printCharBuffers[stream];
assert(buffer);
if (curr === 0 || curr === 10) {
- (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0));
+ (stream === 1 ? out : err)(UTF8ArrayToString(buffer));
buffer.length = 0;
} else {
buffer.push(curr);
@@ -2712,9 +2721,11 @@ function dbg(text) {
}
if (target == 0x88EB /*GL_PIXEL_PACK_BUFFER*/) {
- // In WebGL 2 glReadPixels entry point, we need to use a different WebGL 2 API function call when a buffer is bound to
- // GL_PIXEL_PACK_BUFFER_BINDING point, so must keep track whether that binding point is non-null to know what is
- // the proper API function to call.
+ // In WebGL 2 glReadPixels entry point, we need to use a different WebGL 2
+ // API function call when a buffer is bound to
+ // GL_PIXEL_PACK_BUFFER_BINDING point, so must keep track whether that
+ // binding point is non-null to know what is the proper API function to
+ // call.
GLctx.currentPixelPackBufferBinding = buffer;
} else if (target == 0x88EC /*GL_PIXEL_UNPACK_BUFFER*/) {
// In WebGL 2 gl(Compressed)Tex(Sub)Image[23]D entry points, we need to
@@ -2733,39 +2744,42 @@ function dbg(text) {
GLctx.currentElementArrayBufferBinding = ibo ? (ibo.name | 0) : 0;
};
- function _glBlendFunc(x0, x1) { GLctx.blendFunc(x0, x1) }
+ var _glBlendFunc = (x0, x1) => GLctx.blendFunc(x0, x1);
var _glBufferData = (target, size, data, usage) => {
- if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible.
- // If size is zero, WebGL would interpret uploading the whole input arraybuffer (starting from given offset), which would
- // not make sense in WebAssembly, so avoid uploading if size is zero. However we must still call bufferData to establish a
- // backing storage of zero bytes.
+ if (GL.currentContext.version >= 2) {
+ // If size is zero, WebGL would interpret uploading the whole input
+ // arraybuffer (starting from given offset), which would not make sense in
+ // WebAssembly, so avoid uploading if size is zero. However we must still
+ // call bufferData to establish a backing storage of zero bytes.
if (data && size) {
GLctx.bufferData(target, HEAPU8, usage, data, size);
} else {
GLctx.bufferData(target, size, usage);
}
- } else {
- // N.b. here first form specifies a heap subarray, second form an integer size, so the ?: code here is polymorphic. It is advised to avoid
- // randomly mixing both uses in calling code, to avoid any potential JS engine JIT issues.
- GLctx.bufferData(target, data ? HEAPU8.subarray(data, data+size) : size, usage);
+ return;
}
+ // N.b. here first form specifies a heap subarray, second form an integer
+ // size, so the ?: code here is polymorphic. It is advised to avoid
+ // randomly mixing both uses in calling code, to avoid any potential JS
+ // engine JIT issues.
+ GLctx.bufferData(target, data ? HEAPU8.subarray(data, data+size) : size, usage);
};
var _glBufferSubData = (target, offset, size, data) => {
- if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible.
+ if (GL.currentContext.version >= 2) {
size && GLctx.bufferSubData(target, offset, HEAPU8, data, size);
return;
}
GLctx.bufferSubData(target, offset, HEAPU8.subarray(data, data+size));
};
- function _glClear(x0) { GLctx.clear(x0) }
+ var _glClear = (x0) => GLctx.clear(x0);
- function _glClearColor(x0, x1, x2, x3) { GLctx.clearColor(x0, x1, x2, x3) }
+ var _glClearColor = (x0, x1, x2, x3) => GLctx.clearColor(x0, x1, x2, x3);
- function _glClearDepth(x0) { GLctx.clearDepth(x0) }
+ var _glClearDepth = (x0) => GLctx.clearDepth(x0);
var _glCompileShader = (shader) => {
GLctx.compileShader(GL.shaders[shader]);
@@ -2776,7 +2790,8 @@ function dbg(text) {
var program = GLctx.createProgram();
// Store additional information needed for each shader program:
program.name = id;
- // Lazy cache results of glGetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH/GL_ACTIVE_ATTRIBUTE_MAX_LENGTH/GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH)
+ // Lazy cache results of
+ // glGetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH/GL_ACTIVE_ATTRIBUTE_MAX_LENGTH/GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH)
program.maxUniformLength = program.maxAttributeLength = program.maxUniformBlockNameLength = 0;
program.uniformIdCounter = 1;
GL.programs[id] = program;
@@ -2813,7 +2828,9 @@ function dbg(text) {
var _glDeleteProgram = (id) => {
if (!id) return;
var program = GL.programs[id];
- if (!program) { // glDeleteProgram actually signals an error when deleting a nonexisting object, unlike some other GL delete functions.
+ if (!program) {
+ // glDeleteProgram actually signals an error when deleting a nonexisting
+ // object, unlike some other GL delete functions.
GL.recordError(0x501 /* GL_INVALID_VALUE */);
return;
}
@@ -2825,7 +2842,9 @@ function dbg(text) {
var _glDeleteShader = (id) => {
if (!id) return;
var shader = GL.shaders[id];
- if (!shader) { // glDeleteShader actually signals an error when deleting a nonexisting object, unlike some other GL delete functions.
+ if (!shader) {
+ // glDeleteShader actually signals an error when deleting a nonexisting
+ // object, unlike some other GL delete functions.
GL.recordError(0x501 /* GL_INVALID_VALUE */);
return;
}
@@ -2841,7 +2860,7 @@ function dbg(text) {
}
};
- function _glDepthFunc(x0) { GLctx.depthFunc(x0) }
+ var _glDepthFunc = (x0) => GLctx.depthFunc(x0);
var _glDepthMask = (flag) => {
GLctx.depthMask(!!flag);
@@ -2858,19 +2877,42 @@ function dbg(text) {
var _glDrawElements = (mode, count, type, indices) => {
var buf;
+ var vertexes = 0;
if (!GLctx.currentElementArrayBufferBinding) {
var size = GL.calcBufLength(1, type, 0, count);
buf = GL.getTempIndexBuffer(size);
GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, buf);
GLctx.bufferSubData(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/,
- 0,
- HEAPU8.subarray(indices, indices + size));
+ 0,
+ HEAPU8.subarray(indices, indices + size));
+
+ // Calculating vertex count if shader's attribute data is on client side
+ if (count > 0) {
+ for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) {
+ var cb = GL.currentContext.clientBuffers[i];
+ if (cb.clientside && cb.enabled) {
+ let arrayClass;
+ switch(type) {
+ case 0x1401 /* GL_UNSIGNED_BYTE */: arrayClass = Uint8Array; break;
+ case 0x1403 /* GL_UNSIGNED_SHORT */: arrayClass = Uint16Array; break;
+ case 0x1405 /* GL_UNSIGNED_INT */: arrayClass = Uint32Array; break;
+ default:
+ GL.recordError(0x502 /* GL_INVALID_OPERATION */);
+ return;
+ }
+
+ vertexes = new arrayClass(HEAPU8.buffer, indices, count).reduce((max, current) => Math.max(max, current)) + 1;
+ break;
+ }
+ }
+ }
+
// the index is now 0
indices = 0;
}
// bind any client-side buffers
- GL.preDrawHandleClientVertexAttribBindings(count);
+ GL.preDrawHandleClientVertexAttribBindings(vertexes);
GLctx.drawElements(mode, count, type, indices);
@@ -2881,7 +2923,7 @@ function dbg(text) {
}
};
- function _glEnable(x0) { GLctx.enable(x0) }
+ var _glEnable = (x0) => GLctx.enable(x0);
var _glEnableVertexAttribArray = (index) => {
var cb = GL.currentContext.clientBuffers[index];
@@ -2889,31 +2931,15 @@ function dbg(text) {
GLctx.enableVertexAttribArray(index);
};
- var __glGenObject = (n, buffers, createFunction, objectTable
- ) => {
- for (var i = 0; i < n; i++) {
- var buffer = GLctx[createFunction]();
- var id = buffer && GL.getNewId(objectTable);
- if (buffer) {
- buffer.name = id;
- objectTable[id] = buffer;
- } else {
- GL.recordError(0x502 /* GL_INVALID_OPERATION */);
- }
- HEAP32[(((buffers)+(i*4))>>2)] = id;
- }
- };
-
var _glGenBuffers = (n, buffers) => {
- __glGenObject(n, buffers, 'createBuffer', GL.buffers
+ GL.genObject(n, buffers, 'createBuffer', GL.buffers
);
};
-
- function _glGenVertexArrays(n, arrays) {
- __glGenObject(n, arrays, 'createVertexArray', GL.vaos
+ var _glGenVertexArrays = (n, arrays) => {
+ GL.genObject(n, arrays, 'createVertexArray', GL.vaos
);
- }
+ };
var _glGetAttribLocation = (program, name) => {
@@ -2929,8 +2955,9 @@ function dbg(text) {
var _glGetProgramiv = (program, pname, p) => {
if (!p) {
- // GLES2 specification does not specify how to behave if p is a null pointer. Since calling this function does not make sense
- // if p == null, issue a GL error to notify user about it.
+ // GLES2 specification does not specify how to behave if p is a null
+ // pointer. Since calling this function does not make sense if p == null,
+ // issue a GL error to notify user about it.
GL.recordError(0x501 /* GL_INVALID_VALUE */);
return;
}
@@ -2948,21 +2975,24 @@ function dbg(text) {
HEAP32[((p)>>2)] = log.length + 1;
} else if (pname == 0x8B87 /* GL_ACTIVE_UNIFORM_MAX_LENGTH */) {
if (!program.maxUniformLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/); ++i) {
+ var numActiveUniforms = GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/);
+ for (var i = 0; i < numActiveUniforms; ++i) {
program.maxUniformLength = Math.max(program.maxUniformLength, GLctx.getActiveUniform(program, i).name.length+1);
}
}
HEAP32[((p)>>2)] = program.maxUniformLength;
} else if (pname == 0x8B8A /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */) {
if (!program.maxAttributeLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/); ++i) {
+ var numActiveAttributes = GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/);
+ for (var i = 0; i < numActiveAttributes; ++i) {
program.maxAttributeLength = Math.max(program.maxAttributeLength, GLctx.getActiveAttrib(program, i).name.length+1);
}
}
HEAP32[((p)>>2)] = program.maxAttributeLength;
} else if (pname == 0x8A35 /* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH */) {
if (!program.maxUniformBlockNameLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/); ++i) {
+ var numActiveUniformBlocks = GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/);
+ for (var i = 0; i < numActiveUniformBlocks; ++i) {
program.maxUniformBlockNameLength = Math.max(program.maxUniformBlockNameLength, GLctx.getActiveUniformBlockName(program, i).length+1);
}
}
@@ -2982,8 +3012,9 @@ function dbg(text) {
var _glGetShaderiv = (shader, pname, p) => {
if (!p) {
- // GLES2 specification does not specify how to behave if p is a null pointer. Since calling this function does not make sense
- // if p == null, issue a GL error to notify user about it.
+ // GLES2 specification does not specify how to behave if p is a null
+ // pointer. Since calling this function does not make sense if p == null,
+ // issue a GL error to notify user about it.
GL.recordError(0x501 /* GL_INVALID_VALUE */);
return;
}
@@ -3011,9 +3042,7 @@ function dbg(text) {
var jstoi_q = (str) => parseInt(str);
/** @noinline */
- var webglGetLeftBracePos = (name) => {
- return name.slice(-1) == ']' && name.lastIndexOf('[');
- };
+ var webglGetLeftBracePos = (name) => name.slice(-1) == ']' && name.lastIndexOf('[');
var webglPrepareUniformLocationsBeforeFirstUse = (program) => {
var uniformLocsById = program.uniformLocsById, // Maps GLuint -> WebGLUniformLocation
@@ -3028,7 +3057,8 @@ function dbg(text) {
// maps integer locations back to uniform name strings, so that we can lazily fetch uniform array locations
program.uniformArrayNamesById = {};
- for (i = 0; i < GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/); ++i) {
+ var numActiveUniforms = GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/);
+ for (i = 0; i < numActiveUniforms; ++i) {
var u = GLctx.getActiveUniform(program, i);
var nm = u.name;
var sz = u.size;
@@ -3067,11 +3097,14 @@ function dbg(text) {
var arrayIndex = 0;
var uniformBaseName = name;
- // Invariant: when populating integer IDs for uniform locations, we must maintain the precondition that
- // arrays reside in contiguous addresses, i.e. for a 'vec4 colors[10];', colors[4] must be at location colors[0]+4.
- // However, user might call glGetUniformLocation(program, "colors") for an array, so we cannot discover based on the user
- // input arguments whether the uniform we are dealing with is an array. The only way to discover which uniforms are arrays
- // is to enumerate over all the active uniforms in the program.
+ // Invariant: when populating integer IDs for uniform locations, we must
+ // maintain the precondition that arrays reside in contiguous addresses,
+ // i.e. for a 'vec4 colors[10];', colors[4] must be at location
+ // colors[0]+4. However, user might call glGetUniformLocation(program,
+ // "colors") for an array, so we cannot discover based on the user input
+ // arguments whether the uniform we are dealing with is an array. The only
+ // way to discover which uniforms are arrays is to enumerate over all the
+ // active uniforms in the program.
var leftBrace = webglGetLeftBracePos(name);
// If user passed an array accessor "[index]", parse the array index off the accessor.
@@ -3081,10 +3114,12 @@ function dbg(text) {
}
// Have we cached the location of this uniform before?
- var sizeAndId = program.uniformSizeAndIdsByName[uniformBaseName]; // A pair [array length, GLint of the uniform location]
+ // A pair [array length, GLint of the uniform location]
+ var sizeAndId = program.uniformSizeAndIdsByName[uniformBaseName];
- // If an uniform with this name exists, and if its index is within the array limits (if it's even an array),
- // query the WebGLlocation, or return an existing cached location.
+ // If an uniform with this name exists, and if its index is within the
+ // array limits (if it's even an array), query the WebGLlocation, or
+ // return an existing cached location.
if (sizeAndId && arrayIndex < sizeAndId[0]) {
arrayIndex += sizeAndId[1]; // Add the base location of the uniform to the array index offset.
if ((uniformLocsById[arrayIndex] = uniformLocsById[arrayIndex] || GLctx.getUniformLocation(program, name))) {
@@ -3093,8 +3128,9 @@ function dbg(text) {
}
}
else {
- // N.b. we are currently unable to distinguish between GL program IDs that never existed vs GL program IDs that have been deleted,
- // so report GL_INVALID_VALUE in both cases.
+ // N.b. we are currently unable to distinguish between GL program IDs that
+ // never existed vs GL program IDs that have been deleted, so report
+ // GL_INVALID_VALUE in both cases.
GL.recordError(0x501 /* GL_INVALID_VALUE */);
}
return -1;
@@ -3120,12 +3156,12 @@ function dbg(text) {
if (p) {
var webglLoc = p.uniformLocsById[location];
- // p.uniformLocsById[location] stores either an integer, or a WebGLUniformLocation.
-
- // If an integer, we have not yet bound the location, so do it now. The integer value specifies the array index
- // we should bind to.
+ // p.uniformLocsById[location] stores either an integer, or a
+ // WebGLUniformLocation.
+ // If an integer, we have not yet bound the location, so do it now. The
+ // integer value specifies the array index we should bind to.
if (typeof webglLoc == 'number') {
- p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(p, p.uniformArrayNamesById[location] + (webglLoc > 0 ? '[' + webglLoc + ']' : ''));
+ p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(p, p.uniformArrayNamesById[location] + (webglLoc > 0 ? `[${webglLoc}]` : ''));
}
// Else an already cached WebGLUniformLocation, return it.
return webglLoc;
@@ -3134,22 +3170,28 @@ function dbg(text) {
}
};
+ var _glUniform1f = (location, v0) => {
+ GLctx.uniform1f(webglGetUniformLocation(location), v0);
+ };
+
+
var miniTempWebGLFloatBuffers = [];
var _glUniformMatrix4fv = (location, count, transpose, value) => {
- if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible.
- count && GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*16);
+ if (GL.currentContext.version >= 2) {
+ count && GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, ((value)>>2), count*16);
return;
}
if (count <= 18) {
// avoid allocation when uploading few enough uniforms
- var view = miniTempWebGLFloatBuffers[16*count-1];
+ var view = miniTempWebGLFloatBuffers[16*count];
// hoist the heap out of the loop for size and for pthreads+growth.
var heap = HEAPF32;
- value >>= 2;
- for (var i = 0; i < 16 * count; i += 16) {
+ value = ((value)>>2);
+ count *= 16;
+ for (var i = 0; i < count; i += 16) {
var dst = value + i;
view[i] = heap[dst];
view[i + 1] = heap[dst + 1];
@@ -3170,7 +3212,7 @@ function dbg(text) {
}
} else
{
- var view = HEAPF32.subarray((value)>>2, (value+count*64)>>2);
+ var view = HEAPF32.subarray((((value)>>2)), ((value+count*64)>>2));
}
GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, view);
};
@@ -3207,34 +3249,39 @@ function dbg(text) {
Fetch.init();;
-handleAllocatorInit();
-var GLctx;;
+
+ // Signal GL rendering layer that processing of a new frame is about to
+ // start. This helps it optimize VBO double-buffering and reduce GPU stalls.
+ registerPreMainLoop(() => GL.newRenderingFrameStarted());
+ ;
var miniTempWebGLFloatBuffersStorage = new Float32Array(288);
- for (/**@suppress{duplicate}*/var i = 0; i < 288; ++i) {
- miniTempWebGLFloatBuffers[i] = miniTempWebGLFloatBuffersStorage.subarray(0, i+1);
- }
- ;
+ // Create GL_POOL_TEMP_BUFFERS_SIZE+1 temporary buffers, for uploads of size 0 through GL_POOL_TEMP_BUFFERS_SIZE inclusive
+ for (/**@suppress{duplicate}*/var i = 0; i <= 288; ++i) {
+ miniTempWebGLFloatBuffers[i] = miniTempWebGLFloatBuffersStorage.subarray(0, i);
+ };
function checkIncomingModuleAPI() {
ignoredModuleProp('fetchSettings');
}
var wasmImports = {
/** @export */
+ __assert_fail: ___assert_fail,
+ /** @export */
+ _abort_js: __abort_js,
+ /** @export */
_emscripten_fetch_free: __emscripten_fetch_free,
/** @export */
+ _emscripten_memcpy_js: __emscripten_memcpy_js,
+ /** @export */
_localtime_js: __localtime_js,
/** @export */
_tzset_js: __tzset_js,
/** @export */
- abort: _abort,
- /** @export */
emscripten_date_now: _emscripten_date_now,
/** @export */
emscripten_get_element_css_size: _emscripten_get_element_css_size,
/** @export */
emscripten_is_main_browser_thread: _emscripten_is_main_browser_thread,
/** @export */
- emscripten_memcpy_js: _emscripten_memcpy_js,
- /** @export */
emscripten_request_animation_frame_loop: _emscripten_request_animation_frame_loop,
/** @export */
emscripten_resize_heap: _emscripten_resize_heap,
@@ -3249,8 +3296,6 @@ var wasmImports = {
/** @export */
emscripten_webgl_create_context: _emscripten_webgl_create_context,
/** @export */
- emscripten_webgl_init_context_attributes: _emscripten_webgl_init_context_attributes,
- /** @export */
emscripten_webgl_make_context_current: _emscripten_webgl_make_context_current,
/** @export */
fd_close: _fd_close,
@@ -3323,6 +3368,8 @@ var wasmImports = {
/** @export */
glShaderSource: _glShaderSource,
/** @export */
+ glUniform1f: _glUniform1f,
+ /** @export */
glUniformMatrix4fv: _glUniformMatrix4fv,
/** @export */
glUseProgram: _glUseProgram,
@@ -3332,22 +3379,22 @@ var wasmImports = {
glVertexAttribPointer: _glVertexAttribPointer
};
var wasmExports = createWasm();
-var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors');
-var _malloc = createExportWrapper('malloc');
-var _free = createExportWrapper('free');
-var _main = Module['_main'] = createExportWrapper('main');
-var ___errno_location = createExportWrapper('__errno_location');
-var _fflush = Module['_fflush'] = createExportWrapper('fflush');
-var setTempRet0 = createExportWrapper('setTempRet0');
+var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors', 0);
+var _main = Module['_main'] = createExportWrapper('main', 2);
+var _free = createExportWrapper('free', 1);
+var _malloc = createExportWrapper('malloc', 1);
+var _fflush = createExportWrapper('fflush', 1);
+var _strerror = createExportWrapper('strerror', 1);
+var __emscripten_tempret_set = createExportWrapper('_emscripten_tempret_set', 1);
+var __emscripten_tempret_get = createExportWrapper('_emscripten_tempret_get', 0);
var _emscripten_stack_init = () => (_emscripten_stack_init = wasmExports['emscripten_stack_init'])();
var _emscripten_stack_get_free = () => (_emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'])();
var _emscripten_stack_get_base = () => (_emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'])();
var _emscripten_stack_get_end = () => (_emscripten_stack_get_end = wasmExports['emscripten_stack_get_end'])();
-var stackSave = createExportWrapper('stackSave');
-var stackRestore = createExportWrapper('stackRestore');
-var stackAlloc = createExportWrapper('stackAlloc');
+var __emscripten_stack_restore = (a0) => (__emscripten_stack_restore = wasmExports['_emscripten_stack_restore'])(a0);
+var __emscripten_stack_alloc = (a0) => (__emscripten_stack_alloc = wasmExports['_emscripten_stack_alloc'])(a0);
var _emscripten_stack_get_current = () => (_emscripten_stack_get_current = wasmExports['emscripten_stack_get_current'])();
-var dynCall_jiji = Module['dynCall_jiji'] = createExportWrapper('dynCall_jiji');
+var dynCall_jiji = Module['dynCall_jiji'] = createExportWrapper('dynCall_jiji', 5);
// include: postamble.js
@@ -3360,24 +3407,21 @@ var missingLibrarySymbols = [
'writeI53ToU64Signaling',
'convertI32PairToI53',
'convertU32PairToI53',
+ 'stackAlloc',
+ 'getTempRet0',
+ 'setTempRet0',
'zeroMemory',
- 'arraySum',
- 'addDays',
- 'setErrNo',
+ 'strError',
'inetPton4',
'inetNtop4',
'inetPton6',
'inetNtop6',
'readSockaddr',
'writeSockaddr',
- 'getHostByName',
'initRandomFill',
'randomFill',
- 'getCallstack',
'emscriptenLog',
- 'convertPCtoSourceLocation',
'readEmAsmArgs',
- 'jstoi_s',
'getExecutableName',
'listenOnce',
'autoResumeAudioContext',
@@ -3386,10 +3430,8 @@ var missingLibrarySymbols = [
'dynCall',
'runtimeKeepalivePush',
'runtimeKeepalivePop',
- 'safeSetTimeout',
'asmjsMangle',
'asyncLoad',
- 'alignMemory',
'mmapAlloc',
'getNativeTypeSize',
'STACK_SIZE',
@@ -3423,6 +3465,7 @@ var missingLibrarySymbols = [
'UTF32ToString',
'stringToUTF32',
'lengthBytesUTF32',
+ 'stringToNewUTF8',
'stringToUTF8OnStack',
'writeArrayToMemory',
'registerKeyEventCallback',
@@ -3460,37 +3503,41 @@ var missingLibrarySymbols = [
'registerBatteryEventCallback',
'setCanvasElementSize',
'getCanvasElementSize',
- 'demangle',
- 'demangleAll',
'jsStackTrace',
- 'stackTrace',
+ 'getCallstack',
+ 'convertPCtoSourceLocation',
'getEnvStrings',
'checkWasiClock',
'wasiRightsToMuslOFlags',
'wasiOFlagsToMuslOFlags',
'createDyncallWrapper',
+ 'safeSetTimeout',
'setImmediateWrapped',
'clearImmediateWrapped',
'polyfillSetImmediate',
+ 'registerPostMainLoop',
'getPromise',
'makePromise',
'idsToPromises',
'makePromiseCallback',
'ExceptionInfo',
'findMatchingCatch',
- 'setMainLoop',
+ 'Browser_asyncPrepareDataCounter',
+ 'safeRequestAnimationFrame',
+ 'arraySum',
+ 'addDays',
'getSocketFromFD',
'getSocketAddress',
'FS_createPreloadedFile',
'FS_modeStringToFlags',
'FS_getMode',
'FS_stdin_getChar',
- 'FS_createDataFile',
'FS_unlink',
+ 'FS_createDataFile',
'FS_mkdirTree',
'_setNetworkCallback',
'heapObjectForWebGLType',
- 'heapAccessShiftForWebGLHeap',
+ 'toTypedArrayIndex',
'emscriptenWebGLGet',
'computeUnpackAlignedImageSize',
'colorChannelsInGlTextureFormat',
@@ -3503,15 +3550,15 @@ var missingLibrarySymbols = [
'writeGLArray',
'registerWebGlEventCallback',
'runAndAbortIfError',
- 'SDL_unicode',
- 'SDL_ttfContext',
- 'SDL_audio',
'emscriptenWebGLGetIndexed',
'ALLOC_NORMAL',
'ALLOC_STACK',
'allocate',
'writeStringToMemory',
'writeAsciiToMemory',
+ 'setErrNo',
+ 'demangle',
+ 'stackTrace',
];
missingLibrarySymbols.forEach(missingLibrarySymbol)
@@ -3524,57 +3571,42 @@ var unexportedSymbols = [
'addOnPostRun',
'addRunDependency',
'removeRunDependency',
- 'FS_createFolder',
- 'FS_createPath',
- 'FS_createLazyFile',
- 'FS_createLink',
- 'FS_createDevice',
- 'FS_readFile',
'out',
'err',
'callMain',
'abort',
- 'keepRuntimeAlive',
'wasmMemory',
'wasmExports',
- 'stackAlloc',
- 'stackSave',
- 'stackRestore',
- 'getTempRet0',
- 'setTempRet0',
'writeStackCookie',
'checkStackCookie',
'writeI53ToI64',
'readI53FromI64',
'readI53FromU64',
'convertI32PairToI53Checked',
+ 'stackSave',
+ 'stackRestore',
'ptrToString',
'exitJS',
'getHeapMax',
'growMemory',
'ENV',
- 'MONTH_DAYS_REGULAR',
- 'MONTH_DAYS_LEAP',
- 'MONTH_DAYS_REGULAR_CUMULATIVE',
- 'MONTH_DAYS_LEAP_CUMULATIVE',
- 'isLeapYear',
- 'ydayFromDate',
'ERRNO_CODES',
- 'ERRNO_MESSAGES',
'DNS',
'Protocols',
'Sockets',
'timers',
'warnOnce',
- 'UNWIND_CACHE',
'readEmAsmArgsArray',
'jstoi_q',
+ 'jstoi_s',
'handleException',
+ 'keepRuntimeAlive',
'callUserCallback',
'maybeExit',
- 'handleAllocatorInit',
+ 'alignMemory',
'HandleAllocator',
'wasmTable',
+ 'noExitRuntime',
'freeTableIndexes',
'functionsInTableMap',
'setValue',
@@ -3588,7 +3620,6 @@ var unexportedSymbols = [
'stringToUTF8',
'lengthBytesUTF8',
'UTF16Decoder',
- 'stringToNewUTF8',
'JSEvents',
'specialHTMLTargets',
'maybeCStringToJsString',
@@ -3600,18 +3631,31 @@ var unexportedSymbols = [
'registerUiEventCallback',
'currentFullscreenStrategy',
'restoreOldWindowedStyle',
+ 'UNWIND_CACHE',
'ExitStatus',
'flush_NO_FILESYSTEM',
+ 'registerPreMainLoop',
'promiseMap',
'uncaughtExceptionCount',
'exceptionLast',
'exceptionCaught',
'Browser',
+ 'getPreloadedImageData__data',
'wget',
+ 'MONTH_DAYS_REGULAR',
+ 'MONTH_DAYS_LEAP',
+ 'MONTH_DAYS_REGULAR_CUMULATIVE',
+ 'MONTH_DAYS_LEAP_CUMULATIVE',
+ 'isLeapYear',
+ 'ydayFromDate',
'SYSCALLS',
'preloadPlugins',
'FS_stdin_getChar_buffer',
+ 'FS_createPath',
+ 'FS_createDevice',
+ 'FS_readFile',
'FS',
+ 'FS_createLazyFile',
'MEMFS',
'TTY',
'PIPEFS',
@@ -3623,12 +3667,13 @@ var unexportedSymbols = [
'webgl_enable_OES_vertex_array_object',
'webgl_enable_WEBGL_draw_buffers',
'webgl_enable_WEBGL_multi_draw',
+ 'webgl_enable_EXT_polygon_offset_clamp',
+ 'webgl_enable_EXT_clip_control',
+ 'webgl_enable_WEBGL_polygon_mode',
'GL',
- '__glGenObject',
'webglGetUniformLocation',
'webglPrepareUniformLocationsBeforeFirstUse',
'webglGetLeftBracePos',
- 'emscripten_webgl_power_preferences',
'AL',
'GLUT',
'EGL',
@@ -3640,6 +3685,8 @@ var unexportedSymbols = [
'webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance',
'allocateUTF8',
'allocateUTF8OnStack',
+ 'print',
+ 'printErr',
'Fetch',
'fetchDeleteCachedData',
'fetchLoadCachedData',
@@ -3651,6 +3698,7 @@ unexportedSymbols.forEach(unexportedRuntimeSymbol);
var calledRun;
+var calledPrerun;
dependenciesFulfilled = function runCaller() {
// If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
@@ -3660,7 +3708,7 @@ dependenciesFulfilled = function runCaller() {
function callMain() {
assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');
- assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called');
+ assert(calledPrerun, 'cannot call main without calling preRun first');
var entryFunction = _main;
@@ -3697,19 +3745,22 @@ function run() {
stackCheckInit();
- preRun();
+ if (!calledPrerun) {
+ calledPrerun = 1;
+ preRun();
- // a preRun added a dependency, run will be called later
- if (runDependencies > 0) {
- return;
+ // a preRun added a dependency, run will be called later
+ if (runDependencies > 0) {
+ return;
+ }
}
function doRun() {
// run may have just been called through dependencies being fulfilled just in this very frame,
// or while the async setStatus time below was happening
if (calledRun) return;
- calledRun = true;
- Module['calledRun'] = true;
+ calledRun = 1;
+ Module['calledRun'] = 1;
if (ABORT) return;
@@ -3717,7 +3768,7 @@ function run() {
preMain();
- if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
+ Module['onRuntimeInitialized']?.();
if (shouldRunNow) callMain();
@@ -3726,10 +3777,8 @@ function run() {
if (Module['setStatus']) {
Module['setStatus']('Running...');
- setTimeout(function() {
- setTimeout(function() {
- Module['setStatus']('');
- }, 1);
+ setTimeout(() => {
+ setTimeout(() => Module['setStatus'](''), 1);
doRun();
}, 1);
} else
@@ -3782,5 +3831,5 @@ if (Module['noInitialRun']) shouldRunNow = false;
run();
-
// end include: postamble.js
+
diff --git a/themes/dist/output.wasm b/themes/dist/output.wasm
index 925d783..4c88053 100755
--- a/themes/dist/output.wasm
+++ b/themes/dist/output.wasm
Binary files differ
diff --git a/themes/emscripten.ini b/themes/emscripten.ini
new file mode 100644
index 0000000..5824ce6
--- /dev/null
+++ b/themes/emscripten.ini
@@ -0,0 +1,14 @@
+[binaries]
+c = 'emcc'
+cpp = 'em++'
+ar = 'emar'
+ranlib = 'emranlib'
+
+[host_machine]
+system = 'emscripten'
+cpu_family = 'wasm32'
+cpu = 'wasm32'
+endian = 'little'
+
+[properties]
+needs_exe_wrapper = true
diff --git a/themes/meson.build b/themes/meson.build
new file mode 100644
index 0000000..1e4c9f1
--- /dev/null
+++ b/themes/meson.build
@@ -0,0 +1,122 @@
+project('themes', 'cpp',
+ version: '1.0.0',
+ default_options: [
+ 'cpp_std=c++17',
+ 'buildtype=release',
+ 'warning_level=2'
+ ]
+)
+
+# Emscripten link flags
+emscripten_link_args = [
+ '-s', 'ALLOW_MEMORY_GROWTH=1',
+ '-s', 'USE_WEBGL2=1',
+ '-s', 'FULL_ES3=1',
+ '-s', 'WASM=1',
+ '-s', 'NO_EXIT_RUNTIME=1',
+ '-s', 'FETCH'
+]
+
+# Source files
+sources = files(
+ # Main
+ 'src/main.cpp',
+ 'src/main_loop.cpp',
+ 'src/mathlib.cpp',
+ 'src/logger.cpp',
+ 'src/shader.cpp',
+ 'src/shader_fetcher.cpp',
+ 'src/shapes_2d.cpp',
+ 'src/webgl_context.cpp',
+ 'src/renderer_2d.cpp',
+ 'src/renderer_3d.cpp',
+
+ # Shaders
+ 'src/shaders/renderer2d_frag.cpp',
+ 'src/shaders/renderer2d_vert.cpp',
+ 'src/shaders/renderer3d_frag.cpp',
+ 'src/shaders/renderer3d_vert.cpp',
+ 'src/shaders/sun_frag.cpp',
+ 'src/shaders/sun_vert.cpp',
+
+ # Autumn theme
+ 'src/autumn/autumn_theme.cpp',
+ 'src/autumn/leaf_particle_render.cpp',
+ 'src/autumn/tree_shape.cpp',
+
+ # Winter theme
+ 'src/winter/winter_theme.cpp',
+ 'src/winter/snowflake.cpp',
+ 'src/winter/windfield.cpp',
+
+ # Spring theme
+ 'src/spring/spring_theme.cpp',
+ 'src/spring/grass_renderer.cpp',
+
+ # Summer theme
+ 'src/summer/summer_theme.cpp'
+)
+
+# Include directories
+inc = include_directories(
+ 'src',
+ 'src/autumn',
+ 'src/winter',
+ 'src/spring',
+ 'src/summer',
+ 'src/shaders',
+ 'src/_shaders',
+ 'src/tools'
+)
+
+# Custom target to build shaders from GLSL files
+node = find_program('node')
+shader_script = meson.project_source_root() + '/src/tools/shader.js'
+
+# List all GLSL shader files as inputs
+shader_inputs = files(
+ 'src/_shaders/renderer2d.frag',
+ 'src/_shaders/renderer2d.vert',
+ 'src/_shaders/renderer3d.frag',
+ 'src/_shaders/renderer3d.vert',
+ 'src/_shaders/sun.frag',
+ 'src/_shaders/sun.vert'
+)
+
+# Custom target that runs whenever shader files change
+sh = find_program('sh')
+build_shaders = custom_target('build_shaders',
+ input: shader_inputs,
+ output: 'shaders.stamp',
+ command: [sh, '-c', node.full_path() + ' ' + shader_script + ' && touch @OUTPUT@'],
+ build_always_stale: true,
+ build_by_default: true
+)
+
+# Build the executable
+output_exe = executable('output',
+ sources,
+ include_directories: inc,
+ link_args: emscripten_link_args,
+ name_suffix: 'js'
+)
+
+# Custom target to copy output files to dist directory
+copy_script = find_program('sh')
+copy_to_dist = custom_target('copy_to_dist',
+ output: ['copy_to_dist.stamp'],
+ input: output_exe,
+ command: [
+ copy_script, '-c',
+ 'mkdir -p ' + meson.project_source_root() + '/dist && ' +
+ 'cp $1 ' + meson.project_source_root() + '/dist/output.js && ' +
+ 'cp $2/output.wasm ' + meson.project_source_root() + '/dist/output.wasm && ' +
+ 'touch $3',
+ '--', '@INPUT@', meson.current_build_dir(), '@OUTPUT@'
+ ],
+ build_by_default: true,
+ install: false
+)
+
+# Add an alias target for convenience
+alias_target('copy-dist', copy_to_dist)
diff --git a/themes/src/_shaders/sun.frag b/themes/src/_shaders/sun.frag
index 8463e06..2170b39 100644
--- a/themes/src/_shaders/sun.frag
+++ b/themes/src/_shaders/sun.frag
@@ -1,5 +1,43 @@
varying lowp vec4 VertexColor;
+varying lowp vec2 TexCoord;
+uniform lowp float time;
+
+// Simple noise function for edge distortion
+lowp float noise(lowp vec2 p) {
+ return sin(p.x * 10.0 + time) * cos(p.y * 10.0 + time * 0.5) * 0.5 + 0.5;
+}
void main() {
- gl_FragColor = VertexColor;
+ // TexCoord is now normalized: center is (0,0), edges are at distance ~1
+ lowp float dist = length(TexCoord);
+
+ // Add animated noise to the edge
+ lowp float angle = atan(TexCoord.y, TexCoord.x);
+ lowp float wave = sin(angle * 8.0 + time * 2.0) * 0.05 + sin(angle * 4.0 - time * 1.5) * 0.03;
+ lowp float noiseValue = noise(TexCoord + time * 0.1) * 0.02;
+
+ // Create soft edge using smoothstep - ensure fade reaches zero at the actual edge
+ lowp float innerEdge = 0.8;
+ lowp float outerEdge = 1.0;
+ lowp float alpha = 1.0 - smoothstep(innerEdge, outerEdge, dist);
+
+ // Apply wave distortion to the edge
+ alpha *= 1.0 - smoothstep(0.85 + wave + noiseValue * 2.0, 1.0, dist);
+
+ // Make edges more transparent but not too much
+ alpha = alpha * alpha;
+
+ // Add slight glow effect at the edge
+ lowp float glow = smoothstep(0.5, 0.8, dist) * (1.0 - smoothstep(0.8, 1.0, dist));
+
+ // Create orange gradient from center
+ lowp vec3 orangeColor = vec3(1.0, 0.5, 0.1);
+ lowp float centerGradient = smoothstep(0.6, 0.0, dist);
+ lowp vec3 baseColor = mix(VertexColor.rgb, orangeColor, centerGradient * 0.6);
+
+ // Mix in the glow with a brighter color
+ lowp vec3 glowColor = baseColor * 1.3;
+ lowp vec3 finalColor = mix(baseColor, glowColor, glow * 0.5);
+
+ gl_FragColor = vec4(finalColor, VertexColor.a * alpha);
}
diff --git a/themes/src/_shaders/sun.vert b/themes/src/_shaders/sun.vert
index 76150f0..5ed77d7 100644
--- a/themes/src/_shaders/sun.vert
+++ b/themes/src/_shaders/sun.vert
@@ -1,13 +1,22 @@
-attribute vec2 position;
-attribute vec4 color;
-attribute mat4 vMatrix;
-uniform mat4 projection;
-uniform mat4 model;
+attribute vec2 position;
+attribute vec4 color;
+attribute mat4 vMatrix;
+uniform mat4 projection;
+uniform mat4 model;
varying lowp vec4 VertexColor;
+varying lowp vec2 TexCoord;
-void main() {
- vec4 fragmentPosition = projection * model * vMatrix * vec4(position.x, position.y, 0, 1);
- gl_Position = fragmentPosition;
- VertexColor = color;
+void main() {
+ vec4 fragmentPosition = projection * model * vMatrix * vec4(position.x, position.y, 0, 1);
+ gl_Position = fragmentPosition;
+ VertexColor = color;
+ // Normalize the position - the center is at (0,0) and edge vertices are at distance 'radius'
+ // We want TexCoord to be in the range roughly [-1, 1] at the edges
+ lowp float maxDist = length(position);
+ if (maxDist > 0.1) {
+ TexCoord = position / maxDist;
+ } else {
+ TexCoord = vec2(0.0, 0.0);
+ }
}
diff --git a/themes/src/autumn/AutumnTheme.cpp b/themes/src/autumn/autumn_theme.cpp
index 4b7a2e2..d88b265 100644
--- a/themes/src/autumn/AutumnTheme.cpp
+++ b/themes/src/autumn/autumn_theme.cpp
@@ -1,4 +1,4 @@
-#include "AutumnTheme.hpp"
+#include "autumn_theme.hpp"
#include "../shapes_2d.h"
#include <memory>
diff --git a/themes/src/autumn/AutumnTheme.hpp b/themes/src/autumn/autumn_theme.hpp
index e3f5748..b61c0f3 100644
--- a/themes/src/autumn/AutumnTheme.hpp
+++ b/themes/src/autumn/autumn_theme.hpp
@@ -1,11 +1,11 @@
#ifndef AUTUMN_THEME_HPP
#define AUTUMN_THEME_HPP
-#include "TreeShape.h"
-#include "LeafParticleRender.h"
+#include "tree_shape.h"
+#include "leaf_particle_render.h"
#include "../types.h"
#include "../theme.h"
-#include "../Renderer2d.h"
+#include "../renderer_2d.h"
#include <memory>
#include <vector>
diff --git a/themes/src/autumn/LeafParticleRender.cpp b/themes/src/autumn/leaf_particle_render.cpp
index fee3df2..569bb2d 100644
--- a/themes/src/autumn/LeafParticleRender.cpp
+++ b/themes/src/autumn/leaf_particle_render.cpp
@@ -1,7 +1,7 @@
-#include "LeafParticleRender.h"
-#include "../Renderer2d.h"
+#include "leaf_particle_render.h"
+#include "../renderer_2d.h"
#include "../mathlib.h"
-#include "TreeShape.h"
+#include "tree_shape.h"
#include "../types.h"
#include <math.h>
diff --git a/themes/src/autumn/LeafParticleRender.h b/themes/src/autumn/leaf_particle_render.h
index f6efe1f..1209e1b 100644
--- a/themes/src/autumn/LeafParticleRender.h
+++ b/themes/src/autumn/leaf_particle_render.h
@@ -1,4 +1,4 @@
-#include "../Renderer2d.h"
+#include "../renderer_2d.h"
#include "../mathlib.h"
#include "../types.h"
diff --git a/themes/src/autumn/TreeShape.cpp b/themes/src/autumn/tree_shape.cpp
index 7c80929..622751b 100644
--- a/themes/src/autumn/TreeShape.cpp
+++ b/themes/src/autumn/tree_shape.cpp
@@ -1,4 +1,4 @@
-#include "TreeShape.h"
+#include "tree_shape.h"
#include "../mathlib.h"
#include <cstdio>
#include <cstdlib>
diff --git a/themes/src/autumn/TreeShape.h b/themes/src/autumn/tree_shape.h
index fc0d11e..0d18415 100644
--- a/themes/src/autumn/TreeShape.h
+++ b/themes/src/autumn/tree_shape.h
@@ -1,4 +1,4 @@
-#include "../Renderer2d.h"
+#include "../renderer_2d.h"
#include "../types.h"
#include "../mathlib.h"
diff --git a/themes/src/list.h b/themes/src/list.h
index 25b236a..9b6a719 100644
--- a/themes/src/list.h
+++ b/themes/src/list.h
@@ -1,7 +1,7 @@
#pragma once
#include <cstdlib>
#include <cstring>
-#include "Logger.h"
+#include "logger.h"
#define FOREACH(list) \
for (i32 idx = 0; idx < list.numElements; idx++) \
diff --git a/themes/src/Logger.cpp b/themes/src/logger.cpp
index 1068d88..bead282 100644
--- a/themes/src/Logger.cpp
+++ b/themes/src/logger.cpp
@@ -1,4 +1,4 @@
-#include "Logger.h"
+#include "logger.h"
#include <chrono>
#include <cstdarg>
#include <cstdio>
diff --git a/themes/src/Logger.h b/themes/src/logger.h
index 7596b6f..7596b6f 100644
--- a/themes/src/Logger.h
+++ b/themes/src/logger.h
diff --git a/themes/src/main.cpp b/themes/src/main.cpp
index 14227c9..60e6aed 100644
--- a/themes/src/main.cpp
+++ b/themes/src/main.cpp
@@ -1,13 +1,13 @@
-#include "WebglContext.h"
-#include "MainLoop.h"
-#include "Renderer2d.h"
+#include "webgl_context.h"
+#include "main_loop.h"
+#include "renderer_2d.h"
#include "mathlib.h"
#include "theme.h"
#include "types.h"
-#include "summer/SummerTheme.h"
-#include "autumn/AutumnTheme.hpp"
-#include "spring/SpringTheme.hpp"
-#include "winter/WinterTheme.hpp"
+#include "summer/summer_theme.h"
+#include "autumn/autumn_theme.hpp"
+#include "spring/spring_theme.hpp"
+#include "winter/winter_theme.hpp"
#include <cstdio>
#include <emscripten/fetch.h>
@@ -67,14 +67,19 @@ void load(ThemeType theme) {
}
void update(f32 dtSeconds, void* userData) {
+ if (!active_theme)
+ return;
active_theme->update(dtSeconds);
active_theme->render();
}
void unload() {
delete active_theme;
+ active_theme = nullptr;
type = ThemeType::Default;
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
if (mainLoop.isRunning) {
mainLoop.stop();
}
@@ -84,7 +89,7 @@ void unload() {
EM_BOOL selectNone(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) {
printf("Default theme selected\n");
unload();
- return true;
+ return true;
}
EM_BOOL selectAutumn(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) {
diff --git a/themes/src/MainLoop.cpp b/themes/src/main_loop.cpp
index 09aa643..e5397ca 100644
--- a/themes/src/MainLoop.cpp
+++ b/themes/src/main_loop.cpp
@@ -1,4 +1,4 @@
-#include "MainLoop.h"
+#include "main_loop.h"
#include <cstdio>
#include <cstdlib>
diff --git a/themes/src/MainLoop.h b/themes/src/main_loop.h
index 2573bb8..07520a2 100644
--- a/themes/src/MainLoop.h
+++ b/themes/src/main_loop.h
@@ -26,4 +26,4 @@ struct MainLoop {
void stop() {
isRunning = false;
}
-}; \ No newline at end of file
+};
diff --git a/themes/src/Renderer2d.cpp b/themes/src/renderer_2d.cpp
index f1d78e3..7200669 100644
--- a/themes/src/Renderer2d.cpp
+++ b/themes/src/renderer_2d.cpp
@@ -1,6 +1,6 @@
-#include "Renderer2d.h"
-#include "Shader.h"
-#include "WebglContext.h"
+#include "renderer_2d.h"
+#include "shader.h"
+#include "webgl_context.h"
#include "mathlib.h"
#include <cstdio>
#include "shaders/renderer2d_vert.h"
diff --git a/themes/src/Renderer2d.h b/themes/src/renderer_2d.h
index 7432894..d572533 100644
--- a/themes/src/Renderer2d.h
+++ b/themes/src/renderer_2d.h
@@ -1,8 +1,8 @@
#pragma once
-#include "WebglContext.h"
+#include "webgl_context.h"
#include "types.h"
-#include "Shader.h"
+#include "shader.h"
#include "mathlib.h"
struct WebglContext;
diff --git a/themes/src/Renderer3d.cpp b/themes/src/renderer_3d.cpp
index 00315de..cc79940 100644
--- a/themes/src/Renderer3d.cpp
+++ b/themes/src/renderer_3d.cpp
@@ -1,9 +1,9 @@
-#include "Renderer3d.h"
-#include "Shader.h"
+#include "renderer_3d.h"
+#include "shader.h"
#include "list.h"
#include "mathlib.h"
-#include "WebglContext.h"
-#include "Logger.h"
+#include "webgl_context.h"
+#include "logger.h"
#include <cstdio>
// Note: In the 'transform' attribute, the transform.x is the scale,
diff --git a/themes/src/Renderer3d.h b/themes/src/renderer_3d.h
index 5b2c8c8..5b2c8c8 100644
--- a/themes/src/Renderer3d.h
+++ b/themes/src/renderer_3d.h
diff --git a/themes/src/Shader.cpp b/themes/src/shader.cpp
index 5f2b00e..ed2cab5 100644
--- a/themes/src/Shader.cpp
+++ b/themes/src/shader.cpp
@@ -1,4 +1,4 @@
-#include "Shader.h"
+#include "shader.h"
#include <string>
GLuint loadIndividualShader(GLenum shaderType, const GLchar* cCode) {
diff --git a/themes/src/Shader.h b/themes/src/shader.h
index bc81764..bc81764 100644
--- a/themes/src/Shader.h
+++ b/themes/src/shader.h
diff --git a/themes/src/shaders/sun_frag.cpp b/themes/src/shaders/sun_frag.cpp
index d1ea160..696b3b9 100644
--- a/themes/src/shaders/sun_frag.cpp
+++ b/themes/src/shaders/sun_frag.cpp
@@ -1,8 +1,46 @@
#include "sun_frag.h"
const char* shader_sun_frag = "varying lowp vec4 VertexColor; \n"
+"varying lowp vec2 TexCoord; \n"
+"uniform lowp float time; \n"
+" \n"
+"// Simple noise function for edge distortion \n"
+"lowp float noise(lowp vec2 p) { \n"
+" return sin(p.x * 10.0 + time) * cos(p.y * 10.0 + time * 0.5) * 0.5 + 0.5; \n"
+"} \n"
" \n"
"void main() { \n"
-" gl_FragColor = VertexColor; \n"
+" // TexCoord is now normalized: center is (0,0), edges are at distance ~1 \n"
+" lowp float dist = length(TexCoord); \n"
+" \n"
+" // Add animated noise to the edge \n"
+" lowp float angle = atan(TexCoord.y, TexCoord.x); \n"
+" lowp float wave = sin(angle * 8.0 + time * 2.0) * 0.05 + sin(angle * 4.0 - time * 1.5) * 0.03; \n"
+" lowp float noiseValue = noise(TexCoord + time * 0.1) * 0.02; \n"
+" \n"
+" // Create soft edge using smoothstep - ensure fade reaches zero at the actual edge \n"
+" lowp float innerEdge = 0.8; \n"
+" lowp float outerEdge = 1.0; \n"
+" lowp float alpha = 1.0 - smoothstep(innerEdge, outerEdge, dist); \n"
+" \n"
+" // Apply wave distortion to the edge \n"
+" alpha *= 1.0 - smoothstep(0.85 + wave + noiseValue * 2.0, 1.0, dist); \n"
+" \n"
+" // Make edges more transparent but not too much \n"
+" alpha = alpha * alpha; \n"
+" \n"
+" // Add slight glow effect at the edge \n"
+" lowp float glow = smoothstep(0.5, 0.8, dist) * (1.0 - smoothstep(0.8, 1.0, dist)); \n"
+" \n"
+" // Create orange gradient from center \n"
+" lowp vec3 orangeColor = vec3(1.0, 0.5, 0.1); \n"
+" lowp float centerGradient = smoothstep(0.6, 0.0, dist); \n"
+" lowp vec3 baseColor = mix(VertexColor.rgb, orangeColor, centerGradient * 0.6); \n"
+" \n"
+" // Mix in the glow with a brighter color \n"
+" lowp vec3 glowColor = baseColor * 1.3; \n"
+" lowp vec3 finalColor = mix(baseColor, glowColor, glow * 0.5); \n"
+" \n"
+" gl_FragColor = vec4(finalColor, VertexColor.a * alpha); \n"
"} \n"
" \n";
diff --git a/themes/src/shaders/sun_vert.cpp b/themes/src/shaders/sun_vert.cpp
index ca617c0..bacf3a6 100644
--- a/themes/src/shaders/sun_vert.cpp
+++ b/themes/src/shaders/sun_vert.cpp
@@ -1,16 +1,25 @@
#include "sun_vert.h"
const char* shader_sun_vert = " \n"
-"attribute vec2 position; \n"
-"attribute vec4 color; \n"
-"attribute mat4 vMatrix; \n"
-"uniform mat4 projection; \n"
-"uniform mat4 model; \n"
+"attribute vec2 position; \n"
+"attribute vec4 color; \n"
+"attribute mat4 vMatrix; \n"
+"uniform mat4 projection; \n"
+"uniform mat4 model; \n"
"varying lowp vec4 VertexColor; \n"
+"varying lowp vec2 TexCoord; \n"
" \n"
-"void main() { \n"
-" vec4 fragmentPosition = projection * model * vMatrix * vec4(position.x, position.y, 0, 1); \n"
-" gl_Position = fragmentPosition; \n"
-" VertexColor = color; \n"
+"void main() { \n"
+" vec4 fragmentPosition = projection * model * vMatrix * vec4(position.x, position.y, 0, 1); \n"
+" gl_Position = fragmentPosition; \n"
+" VertexColor = color; \n"
+" // Normalize the position - the center is at (0,0) and edge vertices are at distance 'radius' \n"
+" // We want TexCoord to be in the range roughly [-1, 1] at the edges \n"
+" lowp float maxDist = length(position); \n"
+" if (maxDist > 0.1) { \n"
+" TexCoord = position / maxDist; \n"
+" } else { \n"
+" TexCoord = vec2(0.0, 0.0); \n"
+" } \n"
"} \n"
" \n";
diff --git a/themes/src/shapes_2d.cpp b/themes/src/shapes_2d.cpp
index d5a29ed..e00c521 100644
--- a/themes/src/shapes_2d.cpp
+++ b/themes/src/shapes_2d.cpp
@@ -1,5 +1,5 @@
#include "shapes_2d.h"
-#include "Renderer2d.h"
+#include "renderer_2d.h"
#include "mathlib.h"
#include "list.h"
diff --git a/themes/src/shapes_2d.h b/themes/src/shapes_2d.h
index 8e08504..325d525 100644
--- a/themes/src/shapes_2d.h
+++ b/themes/src/shapes_2d.h
@@ -2,7 +2,7 @@
#define SHAPES_2D
#include "mathlib.h"
-#include "Renderer2d.h"
+#include "renderer_2d.h"
#include "types.h"
class RectangularGradient
diff --git a/themes/src/spring/GrassRenderer.cpp b/themes/src/spring/grass_renderer.cpp
index b69d111..685f733 100644
--- a/themes/src/spring/GrassRenderer.cpp
+++ b/themes/src/spring/grass_renderer.cpp
@@ -1,5 +1,5 @@
-#include "GrassRenderer.hpp"
-#include "Renderer3d.h"
+#include "grass_renderer.hpp"
+#include "../renderer_3d.h"
void GrassRenderer::load(GrassRendererLoadData params, Renderer3d* renderer) {
const f32 COLUMN_INCREMENT = GRASS_BLADES_PER_COL / params.area.x;
diff --git a/themes/src/spring/GrassRenderer.hpp b/themes/src/spring/grass_renderer.hpp
index 8c96724..88879f3 100644
--- a/themes/src/spring/GrassRenderer.hpp
+++ b/themes/src/spring/grass_renderer.hpp
@@ -1,7 +1,7 @@
#ifndef GRASS_RENDERER_HPP
#define GRASS_RENDERER_HPP
-#include "Renderer3d.h"
+#include "../renderer_3d.h"
#include "mathlib.h"
#include "types.h"
diff --git a/themes/src/spring/SpringTheme.cpp b/themes/src/spring/spring_theme.cpp
index e39c138..8507194 100644
--- a/themes/src/spring/SpringTheme.cpp
+++ b/themes/src/spring/spring_theme.cpp
@@ -1,5 +1,5 @@
-#include "SpringTheme.hpp"
-#include "../Renderer3d.h"
+#include "spring_theme.hpp"
+#include "../renderer_3d.h"
#include "../shader_fetcher.hpp"
#include <cstdio>
#include <emscripten/fetch.h>
diff --git a/themes/src/spring/SpringTheme.hpp b/themes/src/spring/spring_theme.hpp
index 64f9cb5..6079958 100644
--- a/themes/src/spring/SpringTheme.hpp
+++ b/themes/src/spring/spring_theme.hpp
@@ -3,7 +3,7 @@
#include "../mathlib.h"
#include "../types.h"
-#include "../Renderer3d.h"
+#include "../renderer_3d.h"
#include "../theme.h"
diff --git a/themes/src/summer/SummerTheme.cpp b/themes/src/summer/summer_theme.cpp
index 1f76b56..6d2cfec 100644
--- a/themes/src/summer/SummerTheme.cpp
+++ b/themes/src/summer/summer_theme.cpp
@@ -1,5 +1,5 @@
-#include "SummerTheme.h"
-#include "../Renderer2d.h"
+#include "summer_theme.h"
+#include "../renderer_2d.h"
#include "../list.h"
#include "../mathlib.h"
#include "../shaders/sun_frag.h"
@@ -59,19 +59,23 @@ void Sun::load(Renderer2d* renderer) {
indices.add(second);
indices.add(third);
}
-
+
mesh.load(&vertices.data[0], vertices.numElements, &indices.data[0], indices.numElements, renderer);
mesh.model = Mat4x4().translateByVec2(Vector2(renderer->context->width / 2.f, renderer->context->height / 2.f));
+
+ timeUniform = getShaderUniform(renderer->shader, "time");
+
vertices.deallocate();
indices.deallocate();
}
void Sun::update(f32 dtSeconds) {
-
+ elapsedTime += dtSeconds;
}
void Sun::render(Renderer2d* renderer) {
setShaderMat4(renderer->uniforms.model, mesh.model);
+ glUniform1f(timeUniform, elapsedTime);
glBindVertexArray(mesh.vao);
glDrawElements(GL_TRIANGLES, mesh.numIndices, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
diff --git a/themes/src/summer/SummerTheme.h b/themes/src/summer/summer_theme.h
index 2ce6b7f..eb404fd 100644
--- a/themes/src/summer/SummerTheme.h
+++ b/themes/src/summer/summer_theme.h
@@ -1,6 +1,6 @@
#pragma once
#include "../types.h"
-#include "../Renderer2d.h"
+#include "../renderer_2d.h"
#include "../theme.h"
#include <vector>
@@ -8,6 +8,8 @@ struct Sun {
f32 radius = 20.f;
i32 sectors = 180;
Mesh2D mesh;
+ f32 elapsedTime = 0.f;
+ i32 timeUniform = -1;
void load(Renderer2d* renderer);
void update(f32 dtSeconds);
diff --git a/themes/src/WebglContext.cpp b/themes/src/webgl_context.cpp
index df49c2d..71b983e 100644
--- a/themes/src/WebglContext.cpp
+++ b/themes/src/webgl_context.cpp
@@ -1,4 +1,4 @@
-#include "WebglContext.h"
+#include "webgl_context.h"
#include <cstdio>
diff --git a/themes/src/WebglContext.h b/themes/src/webgl_context.h
index 1956092..1956092 100644
--- a/themes/src/WebglContext.h
+++ b/themes/src/webgl_context.h
diff --git a/themes/src/winter/Snowflake.cpp b/themes/src/winter/snowflake.cpp
index 57f1a8f..4ce8f3a 100644
--- a/themes/src/winter/Snowflake.cpp
+++ b/themes/src/winter/snowflake.cpp
@@ -1,5 +1,5 @@
-#include "Snowflake.h"
-#include "../Renderer2d.h"
+#include "snowflake.h"
+#include "../renderer_2d.h"
#include "../mathlib.h"
#include "../list.h"
#include <cstdio>
diff --git a/themes/src/winter/Snowflake.h b/themes/src/winter/snowflake.h
index ad027f6..11a1438 100644
--- a/themes/src/winter/Snowflake.h
+++ b/themes/src/winter/snowflake.h
@@ -4,7 +4,7 @@
#include "../types.h"
#include "../mathlib.h"
#include "../list.h"
-#include "Windfield.hpp"
+#include "windfield.hpp"
struct Renderer2d;
struct Vertex2D;
diff --git a/themes/src/winter/Windfield.cpp b/themes/src/winter/windfield.cpp
index 88fb74b..f6c3be3 100644
--- a/themes/src/winter/Windfield.cpp
+++ b/themes/src/winter/windfield.cpp
@@ -1,4 +1,4 @@
-#include "Windfield.hpp"
+#include "windfield.hpp"
template <i32 Width, i32 Height, i32 CellDimension>
diff --git a/themes/src/winter/Windfield.hpp b/themes/src/winter/windfield.hpp
index 5bf0c38..5bf0c38 100644
--- a/themes/src/winter/Windfield.hpp
+++ b/themes/src/winter/windfield.hpp
diff --git a/themes/src/winter/WinterTheme.cpp b/themes/src/winter/winter_theme.cpp
index 052670e..a628f18 100644
--- a/themes/src/winter/WinterTheme.cpp
+++ b/themes/src/winter/winter_theme.cpp
@@ -1,5 +1,5 @@
-#include "WinterTheme.hpp"
-#include "../Renderer2d.h"
+#include "winter_theme.hpp"
+#include "../renderer_2d.h"
WinterTheme::WinterTheme(WebglContext* context)
{
diff --git a/themes/src/winter/WinterTheme.hpp b/themes/src/winter/winter_theme.hpp
index 5ba6d94..d1c3e05 100644
--- a/themes/src/winter/WinterTheme.hpp
+++ b/themes/src/winter/winter_theme.hpp
@@ -1,10 +1,10 @@
#ifndef WINTER_THEME_HPP
#define WINTER_THEME_HPP
-#include "Snowflake.h"
+#include "snowflake.h"
#include "../types.h"
#include "../theme.h"
-#include "../Renderer2d.h"
+#include "../renderer_2d.h"
struct WebglContext;