summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md29
-rw-r--r--_posts/hello.org46
-rw-r--r--_posts/june_08_2025.org25
-rw-r--r--_posts/may_06_2025.org17
-rw-r--r--_posts/sitemap.org12
-rw-r--r--index.css18
-rw-r--r--index.html8
-rw-r--r--posts.css58
-rw-r--r--posts.html54
-rw-r--r--posts/feed.xml26
-rw-r--r--posts/hello.html91
-rw-r--r--posts/june_08_2025.html67
-rw-r--r--posts/may_06_2025.html55
-rw-r--r--posts/sitemap.html23
-rw-r--r--publish.el3
-rwxr-xr-xresume.css4
-rwxr-xr-xresume.html2
-rw-r--r--resume.mobile.css2
-rw-r--r--themes/compile_commands.json98
-rw-r--r--themes/dist/output.js1913
-rwxr-xr-xthemes/dist/output.wasmbin157180 -> 171370 bytes
-rw-r--r--themes/src/MainLoop.h2
-rw-r--r--themes/src/main.cpp7
23 files changed, 1349 insertions, 1211 deletions
diff --git a/README.md b/README.md
index 0a29a8d..70670c4 100644
--- a/README.md
+++ b/README.md
@@ -9,26 +9,27 @@ If you are on Github, this is a mirror of: https://git.matthewkosarek.xyz/matthe
firefox localhost:8080
```
-## Building
+## Build Themes
+1. Install emscripten: https://emscripten.org/docs/getting_started/downloads.html
-### Themes
-```sh
-# Compile the shaders
-cd themes/src
-node tools/shaders.js
-
-# Build the project
-cd ..
-./compile-commands.sh
-make
-```
+2. Compile the shaders
+ ```sh
+ cd themes/src
+ node tools/shaders.js
+ ```
+3. Build the project
+ ```sh
+ cd ..
+ ./compile-commands.sh
+ make
+ ```
-### Posts
+## Update Posts
```sh
./publish.sh
```
-## Upload
+## Publish New Version
```sh
./upload.sh
```
diff --git a/_posts/hello.org b/_posts/hello.org
index 38a4fc7..3a7a9c6 100644
--- a/_posts/hello.org
+++ b/_posts/hello.org
@@ -8,6 +8,10 @@
* TLDR
+:PROPERTIES:
+:ID: b15846be-b33b-4233-86b1-b56a76622478
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
- Create a new folder
- Put [[https://raw.githubusercontent.com/mattkae/matthewkosarek-xyz/master/index.css][index.css]], [[https://raw.githubusercontent.com/mattkae/matthewkosarek-xyz/master/publish.el][publish.el]], and [[https://github.com/mattkae/matthewkosarek-xyz/blob/master/publish.sh][publish.sh]] in the folder
- Create a folder called ~_posts~ (this is where blog posts are written)
@@ -19,6 +23,10 @@
- Navigate to ~localhost:8080/posts/sitemap.html~ to see your posts
* Introduction
+:PROPERTIES:
+:ID: 39f1ddfb-72e3-4894-9c4c-b160c6e224fe
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
I've recently fallen in love with ~org-mode~, specifically when I use it with [[https://www.orgroam.com/][org-roam]]. I find the whole workflow of creating, tagging, and - later on - searching for information on my computer to be very elegant. On top of that, now that I have the time, I want to begin writing blog posts to better work out my thoughts. With both of these things in mind, I am again turning to the universal tool for human prospering: ~org-mode~. This time, I want to see how it can help me turn a simple org file into a blog post on my website. My requirements are:
1. Org files must get published to HTML files in a particular format with a preset stylesheet
@@ -33,6 +41,10 @@ And that's pretty much it for now. Without further ado, let's jump into getting
(Note: I will be heavily inspired by [[https://systemcrafters.net/publishing-websites-with-org-mode/building-the-site/#creating-the-build-script][this post from System Crafters]]. I highly recommend that you read his post first before you follow my post, as he provides more details about the ~org-publish-project-alist~ command than I am willing to go into in this post.)
* Basic HTML File
+:PROPERTIES:
+:ID: fbd6c42a-45cf-4c16-81fc-e99df88e2389
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
As a pilot, we are going to use this org file that I am currently writing (~hello.org~) as our guinea pig. The goal is to have this org file be our very first blog post.
Emacs ships with org export goodies out of the box via the ~ox-publish.el~ package (which you can find [[https://github.com/emacs-mirror/emacs/blob/master/lisp/org/ox-publish.el][here]]). In our case, we will want to use this package to write a script that exports all the ~./_posts/*.org~ files and outputs them to a corresponding ~./posts/*.html~. Leaning heavily on the System Crafters information, we can create a file called ~publish.el~ and write the following inside of it:
@@ -62,6 +74,10 @@ emacs -Q --script publish.el
We then do a ~chmod +x publish.sh~ to make it an executable and run it with ~./publish.sh~. If everything went according to plan, we should see a new file at ~posts/hello.html~.
* Disabling features that we don't want
+:PROPERTIES:
+:ID: 393f268d-3200-4857-9c78-097468330437
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
The next thing will be to remove some of the generated items that I didn't ask for, namely the table of contents, author, section numbers, creation time stamp, and the validation link.
#+BEGIN_SRC emacs-lisp
@@ -87,6 +103,10 @@ The next thing will be to remove some of the generated items that I didn't ask f
#+END_SRC
* Styling & Code Highlighting
+:PROPERTIES:
+:ID: 25bb1f38-ad48-4513-9238-229955db4328
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
Next thing on our list is custom styling. This can be achieved by first installing the ~htmlize~ package from ~melpa~ / ~elpa~. The EmacsWiki describes this as "a package for exporting the contents of an Emacs buffer to HTML while respecting display properties such as colors, fonts, underlining, invisibility, etc" ([[https://www.emacswiki.org/emacs/Htmlize][reference]]). If used "out-of-the-box", the buffer will be exported to HTML with all of the styles inlined (e.g. if you underline something in your org file, you will generate a ~<span style="text-decoration: underline">...</span>~). However, we are more interested in styling everything by ourselves: we don't want ~htmlize~ making assumptions about what underlining means to us! Luckily, ~htmlize~ gives us the option to export with class names instead of inline styles so that we can specify each style for ourselves.
#+BEGIN_SRC emacs-lisp
@@ -241,6 +261,10 @@ Finally, we need to tell org mode to include our two CSS files when the page is
If we run the publish again, we can see that we have full styling on our code snippets and everything else on our website.
* Images
+:PROPERTIES:
+:ID: 1ca21e46-c212-41ad-b9a7-34fa9909014a
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
Our first two criteria have been met! Next on the list is solving images. As an example, let's use this [[/_posts/assets/squirrel.jpg][squirrel image]] that I found online with an open source license. The ideal situation would be:
1. The squirrel image lives closely to this org document (~hello.org~)
@@ -273,6 +297,10 @@ That's all there is to it! There are simpler ways as well, but that should do it
* Creation Date
+:PROPERTIES:
+:ID: f061a150-b8bc-41cf-8c50-77338ac47c80
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
Let's add the creation date below the title next. To start, we will modify the publish command to remove the title (~:with-title nil~) and, in its place, show a preamble bit of HTML that contains a formatted ~div~ with the title and the "last modified" span.z
#+BEGIN_SRC emacs-lisp
@@ -317,6 +345,10 @@ If you want to see the full list of which values can be included in the ~html-pr
Note that the downside of this is that the created date will change whenever you next save the buffer. This isn't a huge deal for my purposes, but you may need to come up with a more sophisticated mechanism for the exact "creation" date for your use case.
* Generating the Directory
+:PROPERTIES:
+:ID: e2226b35-d9ed-4758-8471-71a5c82331f1
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
For every org file in my ~_posts~ folder, I would like to create a link to the generated HTML file at the ~/posts.html~ page of my website. You can think of this as the "directory" of all posts. My criteria is:
1. Posts should appear in order from newest to oldest
2. Posts should be searchable by tags (covered in the next section)
@@ -360,6 +392,9 @@ If you open the ~sitemap.html~ file in your browser, you will see a bulleted lis
From here, you may customize it however you like. The following are my customizations.
** Sitemap Title
+:PROPERTIES:
+:ID: 47f964f9-15d7-4370-9483-a76dafd79f4c
+:END:
I changed the title to "Matthew's Blog Posts".
#+BEGIN_SRC emacs-lisp
@@ -379,6 +414,9 @@ I changed the title to "Matthew's Blog Posts".
** Format blog entries in the list
+:PROPERTIES:
+:ID: a1c2f9b9-085a-4540-a9f1-7f7388334191
+:END:
I like to include the creation date on the blog posts. To do this, we can use ~org-publish-find-property~ to find the date property of the org file. Afterward, we can format a string that includes our formatted timestamp and the ~org-publish-sitemap-default-entry~, which is just a link with the title of the post.
#+BEGIN_SRC emacs-lisp
(defun get-org-file-title(entry style project)
@@ -395,6 +433,10 @@ I like to include the creation date on the blog posts. To do this, we can use ~o
#+END_SRC
* Tags & Filtering
+:PROPERTIES:
+:ID: bb278140-4b5c-4025-a267-693820251199
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
I use [[https://www.orgroam.com/][Org-roam]] for all of my note-taking and, in the next blog post, I plan to demonstrate how I will hook up my Org-roam note-taking workflow to my blogging. In the meantime, just know that we can add tags to the top of our org files like this:
#+BEGIN_SRC org
@@ -585,4 +627,8 @@ Finally, let's append the following to ~posts/posts.css~ so that our tag list is
#+END_SRC
* Conclusion
+:PROPERTIES:
+:ID: 0612cef6-bdb4-4f43-8ba7-86e2c22120fd
+:PUBDATE: 2025-05-06 Tue 14:32
+:END:
There are many more customizations that I plan to do on this system in the future, but I plan to leave this for now so that I can actually get to some blogging. I will proofread and fix my mistakes as time goes on, but this should be a good jumping off point for anyone interested in using org for their own blogging system.
diff --git a/_posts/june_08_2025.org b/_posts/june_08_2025.org
new file mode 100644
index 0000000..0a9bc8f
--- /dev/null
+++ b/_posts/june_08_2025.org
@@ -0,0 +1,25 @@
+:PROPERTIES:
+:ID: c397a1c8-5980-419d-88d4-a3c9782343d5
+:END:
+#+TITLE: Update June 08, 2025
+#+DATE: <2025-06-08 Sun 15:30>
+#+filetags: :update:
+
+* What have I been up to?
+Another month has gone by, so I guess it's time to see what I've been up to.
+
+Canonical hosted our company's sprint in Frankfurt, Germany during the month of May. It was a very productive time for the whole team. I always enjoy seeing everyone in person, talking through big issues face-to-face, and exploring a new city. I also got to spend some time in Zurich, Switzerland before the sprint began. Zurich is pretty awesome πŸ”οΈ!
+
+In miracle-wm, I have been going down quite the rabbit-holeπŸ‡! What began as a plan to fix the remaining warnings in the source code has snowballed into me implemnenting the rest of the IPC mechanism and testing the entire thing. This has been no small feat, as both sway and i3 implement a _lot_ of different commands, and a failure to implement any one of them often leads to half-broken clients. I've had to make some "executive" decisions to ignore parts of the protocol that I deem irrelevant now (especially many of the X-specific bits), but it is a mostly compatible implementation. The good news is that I've nearly completed this journey and should be ready to release version ~0.6.0~ some time in the middle of June.
+
+Miracle is getting closer-and-closer to my vision of it every day. The only problem right now is finding the bandwidth to implement everything that I have in my head :)
+
+On the Mir side of things, I am still implementing the magnifier glass accessibility feature from before, but with a much-improved technical direction that we arrived at during our time in Frankfurt. Unfortunately, this required a quick detour to properly implement the ~overlay_cursor~ flag of [[https://wayland.app/protocols/wlr-screencopy-unstable-v1#zwlr_screencopy_manager_v1:request:capture_output:arg:overlay_cursor][zwlr_screencopy_manager_v1::capture_output_region]], as both screencopy and magnification rely on this same code path. The good news is that I'm quite close on this and it should be landing in full any day now 🀞
+
+I also fixed [[https://github.com/canonical/mir/pull/3968][this very breaking bug]] that was actively preventing miracle from rendering on my second monitor, so that's good.
+
+On addition to these two projects, I am also reinvolving myself in the Flutter multi-window work. For those who don't know, we're trying to make it so that the Flutter toolkit can render to multiple surfaces. This is no small feat, as Flutter was originally written with the assumption that only a single "view" would ever be drawn too. However we've managed to make some great progress on it thus far, and we're very excited to land the first pull request imminently with the help of the folks over a Google!
+
+I hope you're having a great and productive summer 😎
+
+
diff --git a/_posts/may_06_2025.org b/_posts/may_06_2025.org
new file mode 100644
index 0000000..2b90752
--- /dev/null
+++ b/_posts/may_06_2025.org
@@ -0,0 +1,17 @@
+:PROPERTIES:
+:ID: fe8e0951-3201-496f-aa0b-21578e269036
+:END:
+#+TITLE: Update May 06, 2025
+#+DATE: <2025-05-06 Tue 17:00>
+#+filetags: :update:
+
+* What have I been up to?
+I've been meaning to do these little blog-post type updates for a while, and I figured now is as good a time as any. So let's start :)
+
+In the world of miracle-wm, I've been hard at work writing a new settings application for the compositor called [[https://github.com/miracle-wm-org/miracle-settings][miracle-settings]]. While the application is written in Flutter, the logic behind the application is entirely implemented in ~libmiracle-wm-config.so~, a new library that will ship with miracle as part of ~v0.6.0~. If Flutter isn't your cup of tea, you should be able to implement your own settings app for miracle in the language/toolkit of your choice by simply binding to the C (or C++!) API.
+
+I also implemented [[https://wayland.app/protocols/wlr-output-management-unstable-v1][wlr-output-management]] in miracle and changed how we do display configuration in a big way. The display configuration will now always be loaded from ~$HOME/.config/miracle-wm/display.yaml~. Users should now be able to use apps like [[https://github.com/artizirk/wdisplays][wdisplays]] to change the output configuration at runtime, which is pretty cool!
+
+On the Mir project, I've been working on accessibility features (e.g. magnification) in addition to exposing some facilities for compositor authors to write end-to-end tests for Mir-based compositors. These new testing facilities should help us write tests in miracle in a big way.
+
+Also - my cat who ate a sewing needle last year has turned two! 🐱
diff --git a/_posts/sitemap.org b/_posts/sitemap.org
index b5e96d9..4cef4e1 100644
--- a/_posts/sitemap.org
+++ b/_posts/sitemap.org
@@ -1,12 +1,20 @@
#+TITLE: Matthew's Blog Posts
-#+DATE: 2024-05-01 at 14:07
+#+DATE: 2025-06-08 at 15:35
#+HTML_LINK_HOME: /
#+HTML_LINK_UP: /
+- [[file:june_08_2025.org][Update June 08, 2025]] created on June 08, 2025
+ #+begin_sitemap_tag
+ update
+ #+end_sitemap_tag
+- [[file:may_06_2025.org][Update May 06, 2025]] created on May 06, 2025
+ #+begin_sitemap_tag
+ update
+ #+end_sitemap_tag
- [[file:hello.org][Hello, Org]] created on June 20, 2023
#+begin_sitemap_tag
technology,home
- #+end_sitemap_tag \ No newline at end of file
+ #+end_sitemap_tag
diff --git a/index.css b/index.css
index 385fd5c..628d91d 100644
--- a/index.css
+++ b/index.css
@@ -23,7 +23,7 @@ header > h1 {
}
header > nav {
- margin-top: 0.5rem;
+ margin-top: 2rem;
margin-bottom: 1rem;
padding-left: 0.25rem;
}
@@ -57,7 +57,7 @@ h1 {
}
h2 {
- font-size: 1.875rem;
+ font-size: 1.5rem;
margin-bottom: 0rem;
margin-top: 2rem;
}
@@ -172,14 +172,14 @@ input:focus {
}
/* Theme Selector */
-#theme_selector {;
+#theme_selector {
display: flex;
align-items: center;
justify-content: center;
bottom: 1rem;
- pointer-events: all;
- opacity: 1;
- transition: opacity 150ms linear;
+ pointer-events: all;
+ opacity: 1;
+ transition: opacity 150ms linear;
gap: 2rem;
}
@@ -238,6 +238,12 @@ only screen and (max-width:1440px) {
only screen and (max-width:960px) {
#theme_selector {
padding-bottom: 2rem !important;
+ flex-direction: column;
+ gap: 1rem;
+ }
+
+ #theme_selector > button {
+ width: 100%;
}
.image_item_expanded_container > .image_item {
diff --git a/index.html b/index.html
index 883f230..23af4bc 100644
--- a/index.html
+++ b/index.html
@@ -5,6 +5,7 @@
<meta charset="utf-8">
<link rel="stylesheet" href="/index.css">
<title>Matthew Kosarek</title>
+ <link href='https://fonts.googleapis.com/css?family=Noto Sans' rel='stylesheet'>
<link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
<meta name="description" content="The personal website of Matthew kosarek">
</head>
@@ -15,7 +16,6 @@
</div>
<header>
- <h1>Matthew Kosarek</h1>
<nav>
<ul>
<li><a href='/'>&#127969; Home</a></li>
@@ -62,9 +62,9 @@
<h2>About Me</h2>
<p>
Hi there 🌊 My name is Matthew Kosarek.
- I am a computer programmer from northern New Jersey and I currently live Philadelphia, PA. I work at Canonical on the
- <a href="https://github.com/canonical/mir">Mir display server</a> and I am currently building
- <a href="https://github.com/mattkae/miracle-wm">miracle-wm</a>, a Mir-based tiling window manager.
+ I am a computer programmer from northern New Jersey and I currently live in Philadelphia, PA. I work at Canonical on
+ <a href="https://github.com/canonical/mir">Mir</a> and I am currently building
+ <a href="https://github.com/miracle-wm-org/miracle-wm">miracle-wm</a>, a Mir-based tiling window manager.
</p>
</section>
<section>
diff --git a/posts.css b/posts.css
deleted file mode 100644
index f07381c..0000000
--- a/posts.css
+++ /dev/null
@@ -1,58 +0,0 @@
-#tag_list {
- width: 65%;
- display: grid;
- margin: auto;
- grid-template-columns: repeat(3, 1fr);
- column-gap: 8px;
- row-gap: 16px
-}
-
-@media (max-width: 767.98px) {
- #tag_list {
- width: 100%;
- }
-}
-
-#tag_list button {
- padding: 12px 0px;
- cursor: pointer;
- border: 1px solid transparent;
- border-radius: 3px;
- font-family: inherit;
- font-size: 14px;
- width: 100%;
- height: 100%;
- color: black;
- background-color: transparent;
- border: 2px solid black;
-}
-
-#tag_list button:hover {
- background-color: lightgray;
-}
-
-#post_list {
- display: flex;
- flex-direction: column;
-}
-
-article {
- width: 100%;
- text-align: left;
- padding-top: 1rem;
-}
-
-article > h2 {
- color: black;
- padding: 0;
- margin: 0;
-}
-
-article > h3 {
- margin: 0;
- margin-top: 12px;
- color: gray;
- font-size: 12px;
- font-weight: normal;
- padding: 0;
-}
diff --git a/posts.html b/posts.html
deleted file mode 100644
index d63d29a..0000000
--- a/posts.html
+++ /dev/null
@@ -1,54 +0,0 @@
-
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta charset="utf-8">
- <link rel="stylesheet" href="/index.css">
- <link rel="stylesheet" href="/posts.css">
- <title>Matthew Kosarek</title>
- <link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
- </head>
- <body>
- <header>
- <h1>Matthew Kosarek</h1>
- <nav>
- <ul>
- <li><a href='/'>&#127969; Home</a></li>
- <li><a href='/resume.html'>&#128216; CV</a></li>
- <li><a href='/posts.html'>&#128221; Posts</a></li>
- </ul>
- </nav>
- </header>
-
- <section>
- <h2>Tags</h2>
-
- <div id='tag_list'>
-
- <a href="/posts/tag_personal.html"><button id="personal">Personal πŸ‘¨</button></a>
-
-
- <a href="/posts/tag_programming.html"><button id="programming">Programming πŸ’»</button></a>
-
-
- <a href="/posts/tag_books.html"><button id="books">Books πŸ“–</button></a>
-
-
- <a href="/posts/tag_food.html"><button id="food">Food 🍲</button></a>
-
- </div>
- </section
-
- <section>
- <h2>Posts</h2>
- <ul id='post_list'>
-
- <li><a href="/posts/hello_world.html">Hello, World!</a></li>
-
- <li><a href="/posts/plato_1.html">Euthyphro: the pious and the god-loved</a></li>
-
- </ul>
- </section>
- </body>
-</html>
diff --git a/posts/feed.xml b/posts/feed.xml
new file mode 100644
index 0000000..5341f95
--- /dev/null
+++ b/posts/feed.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rss version="2.0">
+ <channel>
+ <title>Matthew&apos;s Blog</title>
+ <link>https://matthewkosarek.xyz/</link>
+ <description>The RSS feed for Matthew Kosarek's Blog</description>
+ <language>en-us</language>
+ <lastBuildDate>Tue, 06 May 2025 17:00:00 -0400</lastBuildDate>
+
+ <item>
+ <title>Update May 06, 2025</title>
+ <link>https://matthewkosarek.xyz/posts/may_06_2025.html</link>
+ <guid>https://matthewkosarek.xyz/posts/may_06_2025.html</guid>
+ <pubDate>Tue, 06 May 2025 17:00:00 -0400</pubDate>
+ <description>Update May 06, 2025</description>
+ </item>
+
+ <item>
+ <title>Hello, Org</title>
+ <link>https://matthewkosarek.xyz/posts/hello.html</link>
+ <guid>https://matthewkosarek.xyz/posts/hello.html</guid>
+ <pubDate>Tue, 20 Jun 2023 11:45:00 -0400</pubDate>
+ <description>Hello, Org</description>
+ </item>
+ </channel>
+</rss>
diff --git a/posts/hello.html b/posts/hello.html
index 8469f4e..ec10db2 100644
--- a/posts/hello.html
+++ b/posts/hello.html
@@ -22,15 +22,13 @@
<div class="org-article-title">
<h1>Hello, Org</h1>
<span>Last modified: 2023-06-20 Tue 11:45</span>
+ <span><a href="/posts/feed.xml">RSS Feed</a></span>
</div>
</div>
<div id="content" class="content">
-
-
-
-<div id="outline-container-org8ca89e4" class="outline-2">
-<h2 id="org8ca89e4">TLDR</h2>
-<div class="outline-text-2" id="text-org8ca89e4">
+<div id="outline-container-orgbec5765" class="outline-2">
+<h2 id="orgbec5765">TLDR</h2>
+<div class="outline-text-2" id="text-orgbec5765">
<ul class="org-ul">
<li>Create a new folder</li>
<li>Put <a href="https://raw.githubusercontent.com/mattkae/matthewkosarek-xyz/master/index.css">index.css</a>, <a href="https://raw.githubusercontent.com/mattkae/matthewkosarek-xyz/master/publish.el">publish.el</a>, and <a href="https://github.com/mattkae/matthewkosarek-xyz/blob/master/publish.sh">publish.sh</a> in the folder</li>
@@ -44,10 +42,9 @@
</ul>
</div>
</div>
-
-<div id="outline-container-orgdbe8752" class="outline-2">
-<h2 id="orgdbe8752">Introduction</h2>
-<div class="outline-text-2" id="text-orgdbe8752">
+<div id="outline-container-orgb717615" class="outline-2">
+<h2 id="orgb717615">Introduction</h2>
+<div class="outline-text-2" id="text-orgb717615">
<p>
I've recently fallen in love with <code>org-mode</code>, specifically when I use it with <a href="https://www.orgroam.com/">org-roam</a>. I find the whole workflow of creating, tagging, and - later on - searching for information on my computer to be very elegant. On top of that, now that I have the time, I want to begin writing blog posts to better work out my thoughts. With both of these things in mind, I am again turning to the universal tool for human prospering: <code>org-mode</code>. This time, I want to see how it can help me turn a simple org file into a blog post on my website. My requirements are:
</p>
@@ -70,10 +67,9 @@ And that's pretty much it for now. Without further ado, let's jump into getting
</p>
</div>
</div>
-
-<div id="outline-container-orgaada31d" class="outline-2">
-<h2 id="orgaada31d">Basic HTML File</h2>
-<div class="outline-text-2" id="text-orgaada31d">
+<div id="outline-container-org1ccbbae" class="outline-2">
+<h2 id="org1ccbbae">Basic HTML File</h2>
+<div class="outline-text-2" id="text-org1ccbbae">
<p>
As a pilot, we are going to use this org file that I am currently writing (<code>hello.org</code>) as our guinea pig. The goal is to have this org file be our very first blog post.
</p>
@@ -113,10 +109,9 @@ We then do a <code>chmod +x publish.sh</code> to make it an executable and run i
</p>
</div>
</div>
-
-<div id="outline-container-orgd7e6626" class="outline-2">
-<h2 id="orgd7e6626">Disabling features that we don't want</h2>
-<div class="outline-text-2" id="text-orgd7e6626">
+<div id="outline-container-orga8b7149" class="outline-2">
+<h2 id="orga8b7149">Disabling features that we don't want</h2>
+<div class="outline-text-2" id="text-orga8b7149">
<p>
The next thing will be to remove some of the generated items that I didn't ask for, namely the table of contents, author, section numbers, creation time stamp, and the validation link.
</p>
@@ -145,10 +140,9 @@ The next thing will be to remove some of the generated items that I didn't ask f
</div>
</div>
</div>
-
-<div id="outline-container-orgfe549f7" class="outline-2">
-<h2 id="orgfe549f7">Styling &amp; Code Highlighting</h2>
-<div class="outline-text-2" id="text-orgfe549f7">
+<div id="outline-container-org0d2b040" class="outline-2">
+<h2 id="org0d2b040">Styling &amp; Code Highlighting</h2>
+<div class="outline-text-2" id="text-org0d2b040">
<p>
Next thing on our list is custom styling. This can be achieved by first installing the <code>htmlize</code> package from <code>melpa</code> / <code>elpa</code>. The EmacsWiki describes this as "a package for exporting the contents of an Emacs buffer to HTML while respecting display properties such as colors, fonts, underlining, invisibility, etc" (<a href="https://www.emacswiki.org/emacs/Htmlize">reference</a>). If used "out-of-the-box", the buffer will be exported to HTML with all of the styles inlined (e.g. if you underline something in your org file, you will generate a <code>&lt;span style="text-decoration: underline"&gt;...&lt;/span&gt;</code>). However, we are more interested in styling everything by ourselves: we don't want <code>htmlize</code> making assumptions about what underlining means to us! Luckily, <code>htmlize</code> gives us the option to export with class names instead of inline styles so that we can specify each style for ourselves.
</p>
@@ -318,10 +312,9 @@ If we run the publish again, we can see that we have full styling on our code sn
</p>
</div>
</div>
-
-<div id="outline-container-org854b984" class="outline-2">
-<h2 id="org854b984">Images</h2>
-<div class="outline-text-2" id="text-org854b984">
+<div id="outline-container-org338b6ac" class="outline-2">
+<h2 id="org338b6ac">Images</h2>
+<div class="outline-text-2" id="text-org338b6ac">
<p>
Our first two criteria have been met! Next on the list is solving images. As an example, let's use this <a href="file:///_posts/assets/squirrel.jpg">squirrel image</a> that I found online with an open source license. The ideal situation would be:
</p>
@@ -366,18 +359,16 @@ So what's the fix here? Well, we have two options, but I am going to go with the
That's all there is to it! There are simpler ways as well, but that should do it:
</p>
-<div id="org9f865ab" class="figure">
+<div id="org70c1fa6" class="figure">
<p><img src="/_posts/assets/squirrel.jpg" alt="squirrel.jpg" width="300" />
</p>
<p><span class="figure-number">Figure 1: </span>A Cute Squirrel</p>
</div>
</div>
</div>
-
-
-<div id="outline-container-orgd7096b3" class="outline-2">
-<h2 id="orgd7096b3">Creation Date</h2>
-<div class="outline-text-2" id="text-orgd7096b3">
+<div id="outline-container-org396f39b" class="outline-2">
+<h2 id="org396f39b">Creation Date</h2>
+<div class="outline-text-2" id="text-org396f39b">
<p>
Let's add the creation date below the title next. To start, we will modify the publish command to remove the title (<code>:with-title nil</code>) and, in its place, show a preamble bit of HTML that contains a formatted <code>div</code> with the title and the "last modified" span.z
</p>
@@ -436,10 +427,9 @@ Note that the downside of this is that the created date will change whenever you
</p>
</div>
</div>
-
-<div id="outline-container-org5fd9dcc" class="outline-2">
-<h2 id="org5fd9dcc">Generating the Directory</h2>
-<div class="outline-text-2" id="text-org5fd9dcc">
+<div id="outline-container-orgb732174" class="outline-2">
+<h2 id="orgb732174">Generating the Directory</h2>
+<div class="outline-text-2" id="text-orgb732174">
<p>
For every org file in my <code>_posts</code> folder, I would like to create a link to the generated HTML file at the <code>/posts.html</code> page of my website. You can think of this as the "directory" of all posts. My criteria is:
</p>
@@ -499,10 +489,9 @@ If you open the <code>sitemap.html</code> file in your browser, you will see a b
From here, you may customize it however you like. The following are my customizations.
</p>
</div>
-
-<div id="outline-container-orga131ca9" class="outline-3">
-<h3 id="orga131ca9">Sitemap Title</h3>
-<div class="outline-text-3" id="text-orga131ca9">
+<div id="outline-container-org7ed3bbf" class="outline-3">
+<h3 id="org7ed3bbf">Sitemap Title</h3>
+<div class="outline-text-3" id="text-org7ed3bbf">
<p>
I changed the title to "Matthew's Blog Posts".
</p>
@@ -524,11 +513,9 @@ I changed the title to "Matthew's Blog Posts".
</div>
</div>
</div>
-
-
-<div id="outline-container-org39e11a9" class="outline-3">
-<h3 id="org39e11a9">Format blog entries in the list</h3>
-<div class="outline-text-3" id="text-org39e11a9">
+<div id="outline-container-org5647f3c" class="outline-3">
+<h3 id="org5647f3c">Format blog entries in the list</h3>
+<div class="outline-text-3" id="text-org5647f3c">
<p>
I like to include the creation date on the blog posts. To do this, we can use <code>org-publish-find-property</code> to find the date property of the org file. Afterward, we can format a string that includes our formatted timestamp and the <code>org-publish-sitemap-default-entry</code>, which is just a link with the title of the post.
</p>
@@ -549,10 +536,9 @@ I like to include the creation date on the blog posts. To do this, we can use <c
</div>
</div>
</div>
-
-<div id="outline-container-org22c8fbe" class="outline-2">
-<h2 id="org22c8fbe">Tags &amp; Filtering</h2>
-<div class="outline-text-2" id="text-org22c8fbe">
+<div id="outline-container-org10b4190" class="outline-2">
+<h2 id="org10b4190">Tags &amp; Filtering</h2>
+<div class="outline-text-2" id="text-org10b4190">
<p>
I use <a href="https://www.orgroam.com/">Org-roam</a> for all of my note-taking and, in the next blog post, I plan to demonstrate how I will hook up my Org-roam note-taking workflow to my blogging. In the meantime, just know that we can add tags to the top of our org files like this:
</p>
@@ -772,10 +758,9 @@ Finally, let's append the following to <code>posts/posts.css</code> so that our
</div>
</div>
</div>
-
-<div id="outline-container-org85c3052" class="outline-2">
-<h2 id="org85c3052">Conclusion</h2>
-<div class="outline-text-2" id="text-org85c3052">
+<div id="outline-container-org32ee7b9" class="outline-2">
+<h2 id="org32ee7b9">Conclusion</h2>
+<div class="outline-text-2" id="text-org32ee7b9">
<p>
There are many more customizations that I plan to do on this system in the future, but I plan to leave this for now so that I can actually get to some blogging. I will proofread and fix my mistakes as time goes on, but this should be a good jumping off point for anyone interested in using org for their own blogging system.
</p>
diff --git a/posts/june_08_2025.html b/posts/june_08_2025.html
new file mode 100644
index 0000000..3683395
--- /dev/null
+++ b/posts/june_08_2025.html
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<title>Update June 08, 2025</title>
+<meta name="generator" content="Org Mode" />
+
+<link rel="stylesheet" href="/index.css" />
+<link rel="stylesheet" href="/posts/post.css" />
+<link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
+<script src='/posts/post.js'></script>
+</head>
+<body>
+<div id="org-div-home-and-up">
+ <a accesskey="h" href="/posts/sitemap.html"> UP </a>
+ <a accesskey="H" href="/"> HOME </a>
+</div><div id="preamble" class="status">
+
+ <div class="org-article-title">
+ <h1>Update June 08, 2025</h1>
+ <span>Last modified: 2025-06-08 Sun 15:30</span>
+ <span><a href="/posts/feed.xml">RSS Feed</a></span>
+ </div>
+</div>
+<div id="content" class="content">
+<div id="outline-container-orgd1fe380" class="outline-2">
+<h2 id="orgd1fe380">What have I been up to?</h2>
+<div class="outline-text-2" id="text-orgd1fe380">
+<p>
+Another month has gone by, so I guess it's time to see what I've been up to.
+</p>
+
+<p>
+Canonical hosted our company's sprint in Frankfurt, Germany during the month of May. It was a very productive time for the whole team. I always enjoy seeing everyone in person, talking through big issues face-to-face, and exploring a new city. I also got to spend some time in Zurich, Switzerland before the sprint began. Zurich is pretty awesome πŸ”οΈ!
+</p>
+
+<p>
+In miracle-wm, I have been going down quite the rabbit-holeπŸ‡! What began as a plan to fix the remaining warnings in the source code has snowballed into me implemnenting the rest of the IPC mechanism and testing the entire thing. This has been no small feat, as both sway and i3 implement a <span class="underline">lot</span> of different commands, and a failure to implement any one of them often leads to half-broken clients. I've had to make some "executive" decisions to ignore parts of the protocol that I deem irrelevant now (especially many of the X-specific bits), but it is a mostly compatible implementation. The good news is that I've nearly completed this journey and should be ready to release version <code>0.6.0</code> some time in the middle of June.
+</p>
+
+<p>
+Miracle is getting closer-and-closer to my vision of it every day. The only problem right now is finding the bandwidth to implement everything that I have in my head :)
+</p>
+
+<p>
+On the Mir side of things, I am still implementing the magnifier glass accessibility feature from before, but with a much-improved technical direction that we arrived at during our time in Frankfurt. Unfortunately, this required a quick detour to properly implement the <code>overlay_cursor</code> flag of <a href="https://wayland.app/protocols/wlr-screencopy-unstable-v1#zwlr_screencopy_manager_v1:request:capture_output:arg:overlay_cursor">zwlr<sub>screencopy</sub><sub>manager</sub><sub>v1</sub>::capture<sub>output</sub><sub>region</sub></a>, as both screencopy and magnification rely on this same code path. The good news is that I'm quite close on this and it should be landing in full any day now 🀞
+</p>
+
+<p>
+I also fixed <a href="https://github.com/canonical/mir/pull/3968">this very breaking bug</a> that was actively preventing miracle from rendering on my second monitor, so that's good.
+</p>
+
+<p>
+On addition to these two projects, I am also reinvolving myself in the Flutter multi-window work. For those who don't know, we're trying to make it so that the Flutter toolkit can render to multiple surfaces. This is no small feat, as Flutter was originally written with the assumption that only a single "view" would ever be drawn too. However we've managed to make some great progress on it thus far, and we're very excited to land the first pull request imminently with the help of the folks over a Google!
+</p>
+
+<p>
+I hope you're having a great and productive summer 😎
+</p>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/posts/may_06_2025.html b/posts/may_06_2025.html
new file mode 100644
index 0000000..52854f8
--- /dev/null
+++ b/posts/may_06_2025.html
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<title>Update May 06, 2025</title>
+<meta name="generator" content="Org Mode" />
+
+<link rel="stylesheet" href="/index.css" />
+<link rel="stylesheet" href="/posts/post.css" />
+<link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
+<script src='/posts/post.js'></script>
+</head>
+<body>
+<div id="org-div-home-and-up">
+ <a accesskey="h" href="/posts/sitemap.html"> UP </a>
+ <a accesskey="H" href="/"> HOME </a>
+</div><div id="preamble" class="status">
+
+ <div class="org-article-title">
+ <h1>Update May 06, 2025</h1>
+ <span>Last modified: 2025-05-06 Tue 17:00</span>
+ <span><a href="/posts/feed.xml">RSS Feed</a></span>
+ </div>
+</div>
+<div id="content" class="content">
+<div id="outline-container-org539b8c9" class="outline-2">
+<h2 id="org539b8c9">What have I been up to?</h2>
+<div class="outline-text-2" id="text-org539b8c9">
+<p>
+I've been meaning to do these little blog-post type updates for a while, and I figured now is as good a time as any. So let's start :)
+</p>
+
+<p>
+In the world of miracle-wm, I've been hard at work writing a new settings application for the compositor called <a href="https://github.com/miracle-wm-org/miracle-settings">miracle-settings</a>. While the application is written in Flutter, the logic behind the application is entirely implemented in <code>libmiracle-wm-config.so</code>, a new library that will ship with miracle as part of <code>v0.6.0</code>. If Flutter isn't your cup of tea, you should be able to implement your own settings app for miracle in the language/toolkit of your choice by simply binding to the C (or C++!) API.
+</p>
+
+<p>
+I also implemented <a href="https://wayland.app/protocols/wlr-output-management-unstable-v1">wlr-output-management</a> in miracle and changed how we do display configuration in a big way. The display configuration will now always be loaded from <code>$HOME/.config/miracle-wm/display.yaml</code>. Users should now be able to use apps like <a href="https://github.com/artizirk/wdisplays">wdisplays</a> to change the output configuration at runtime, which is pretty cool!
+</p>
+
+<p>
+On the Mir project, I've been working on accessibility features (e.g. magnification) in addition to exposing some facilities for compositor authors to write end-to-end tests for Mir-based compositors. These new testing facilities should help us write tests in miracle in a big way.
+</p>
+
+<p>
+Also - my cat who ate a sewing needle last year has turned two! 🐱
+</p>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/posts/sitemap.html b/posts/sitemap.html
index 31ec52d..f6e05fe 100644
--- a/posts/sitemap.html
+++ b/posts/sitemap.html
@@ -21,15 +21,34 @@
<div class="org-article-title">
<h1>Matthew's Blog Posts</h1>
- <span>Last modified: 2024-05-01 at 14:07</span>
+ <span>Last modified: 2025-06-08 at 15:35</span>
+ <span><a href="/posts/feed.xml">RSS Feed</a></span>
</div>
</div>
<div id="content" class="content">
<ul class="org-ul">
<li><p>
+<a href="june_08_2025.html">Update June 08, 2025</a> created on June 08, 2025
+</p>
+<div class="sitemap_tag" id="org0a77fe2">
+<p>
+update
+</p>
+
+</div></li>
+<li><p>
+<a href="may_06_2025.html">Update May 06, 2025</a> created on May 06, 2025
+</p>
+<div class="sitemap_tag" id="org32d887f">
+<p>
+update
+</p>
+
+</div></li>
+<li><p>
<a href="hello.html">Hello, Org</a> created on June 20, 2023
</p>
-<div class="sitemap_tag" id="orgb9e6a4a">
+<div class="sitemap_tag" id="org5c1e10a">
<p>
technology,home
</p>
diff --git a/publish.el b/publish.el
index 352c88f..9726cd1 100644
--- a/publish.el
+++ b/publish.el
@@ -44,10 +44,11 @@
<div class=\"org-article-title\">
<h1>%t</h1>
<span>Last modified: %d</span>
+ <span><a href=\"/posts/feed.xml\">RSS Feed</a></span>
</div>
"))
:auto-sitemap t
- :sitemap-sort-files "chronologically"
+ :sitemap-sort-files 'anti-chronologically
:sitemap-title "Matthew's Blog Posts"
:sitemap-format-entry (lambda (entry style project) (get-org-file-title entry style project))
:sitemap-function (lambda (title list) (my-sitemap-function title list))
diff --git a/resume.css b/resume.css
index 0bccb2b..36bb6bf 100755
--- a/resume.css
+++ b/resume.css
@@ -1,5 +1,5 @@
@font-face {
- font-family: Iosevka;
+ font-family: Ubuntu;
src: url(fonts/Ubuntu-M.ttf);
}
@@ -25,7 +25,7 @@ header {
text-align: left;
background-color: white;
color: black;
- font-family: 'Iosevka', Tahoma, Geneva, Verdana, sans-serif;
+ font-family: 'Ubuntu', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.325rem;
}
diff --git a/resume.html b/resume.html
index 0ee34d4..143a87d 100755
--- a/resume.html
+++ b/resume.html
@@ -8,12 +8,12 @@
<script src='/resume.js' defer></script>
<title>Matthew Kosarek - Resume</title>
+ <link href='https://fonts.googleapis.com/css?family=Noto Sans' rel='stylesheet'>
<link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon">
<meta name="description" content="The hosted resume of Matthew kosarek">
</head>
<body>
<header>
- <h1>Matthew Kosarek</h1>
<nav>
<ul>
<li><a href='/'>&#127969; Home</a></li>
diff --git a/resume.mobile.css b/resume.mobile.css
index 5790e0e..016095b 100644
--- a/resume.mobile.css
+++ b/resume.mobile.css
@@ -1,5 +1,5 @@
@media (max-width: 767.98px) {
- html {
+ #resume {
font-size: 12px;
}
diff --git a/themes/compile_commands.json b/themes/compile_commands.json
index bcf5405..020d53e 100644
--- a/themes/compile_commands.json
+++ b/themes/compile_commands.json
@@ -1,127 +1,127 @@
[
{
"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"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/spring/SpringTheme.cpp -o dist/./src/spring/SpringTheme.cpp.o",
- "file": "dist/./src/spring/SpringTheme.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/spring/GrassRenderer.cpp -o dist/./src/spring/GrassRenderer.cpp.o",
- "file": "dist/./src/spring/GrassRenderer.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/mathlib.cpp -o dist/./src/mathlib.cpp.o",
- "file": "dist/./src/mathlib.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/shaders/renderer3d_frag.cpp -o dist/./src/shaders/renderer3d_frag.cpp.o",
- "file": "dist/./src/shaders/renderer3d_frag.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/shaders/sun_frag.cpp -o dist/./src/shaders/sun_frag.cpp.o",
- "file": "dist/./src/shaders/sun_frag.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/shaders/renderer3d_vert.cpp -o dist/./src/shaders/renderer3d_vert.cpp.o",
- "file": "dist/./src/shaders/renderer3d_vert.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/shaders/renderer2d_frag.cpp -o dist/./src/shaders/renderer2d_frag.cpp.o",
- "file": "dist/./src/shaders/renderer2d_frag.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/shaders/sun_vert.cpp -o dist/./src/shaders/sun_vert.cpp.o",
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/shader_fetcher.cpp -o dist/./src/shader_fetcher.cpp.o",
- "file": "dist/./src/shader_fetcher.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/Logger.cpp -o dist/./src/Logger.cpp.o",
- "file": "dist/./src/Logger.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/Renderer3d.cpp -o dist/./src/Renderer3d.cpp.o",
- "file": "dist/./src/Renderer3d.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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.cpp -o dist/./src/Shader.cpp.o",
- "file": "dist/./src/Shader.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/summer/SummerTheme.cpp -o dist/./src/summer/SummerTheme.cpp.o",
- "file": "dist/./src/summer/SummerTheme.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/winter/Windfield.cpp -o dist/./src/winter/Windfield.cpp.o",
- "file": "dist/./src/winter/Windfield.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -MMD -MP -c src/WebglContext.cpp -o dist/./src/WebglContext.cpp.o",
+ "file": "dist/./src/WebglContext.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"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/winter/Snowflake.cpp -o dist/./src/winter/Snowflake.cpp.o",
- "file": "dist/./src/winter/Snowflake.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/autumn/AutumnTheme.cpp -o dist/./src/autumn/AutumnTheme.cpp.o",
- "file": "dist/./src/autumn/AutumnTheme.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/autumn/TreeShape.cpp -o dist/./src/autumn/TreeShape.cpp.o",
- "file": "dist/./src/autumn/TreeShape.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/autumn/LeafParticleRender.cpp -o dist/./src/autumn/LeafParticleRender.cpp.o",
- "file": "dist/./src/autumn/LeafParticleRender.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/shapes_2d.cpp -o dist/./src/shapes_2d.cpp.o",
- "file": "dist/./src/shapes_2d.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/Renderer2d.cpp -o dist/./src/Renderer2d.cpp.o",
- "file": "dist/./src/Renderer2d.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/main.cpp -o dist/./src/main.cpp.o",
- "file": "dist/./src/main.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -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/WebglContext.cpp -o dist/./src/WebglContext.cpp.o",
- "file": "dist/./src/WebglContext.cpp.o"
+ "command": "g++ -I./src -I./src/winter -I./src/autumn -I./src/shaders -I./src/tools -I./src/_shaders -I./src/summer -I./src/spring -MMD -MP -c src/MainLoop.cpp -o dist/./src/MainLoop.cpp.o",
+ "file": "dist/./src/MainLoop.cpp.o"
}
]
diff --git a/themes/dist/output.js b/themes/dist/output.js
index 13d1675..9ff02be 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,21 @@
// 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 WorkerGlobalScope != 'undefined';
+// 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) {
+
+}
+
// --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 +46,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 +56,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,45 +69,28 @@ 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) => {
- // 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);
- }
- assert(ret.buffer);
+ // We need to re-wrap `file://` strings to URLs.
+ filename = isFileURI(filename) ? new URL(filename) : filename;
+ var ret = fs.readFileSync(filename);
+ assert(Buffer.isBuffer(ret));
return ret;
};
-readAsync = (filename, onload, onerror, binary = true) => {
- // See the comment in the `read_` 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);
- });
+readAsync = async (filename, binary = true) => {
+ // See the comment in the `readBinary` function.
+ filename = isFileURI(filename) ? new URL(filename) : filename;
+ var ret = fs.readFileSync(filename, binary ? undefined : 'utf8');
+ assert(binary ? Buffer.isBuffer(ret) : typeof ret == 'string');
+ return ret;
};
// end include: node_shell_read.js
if (!Module['thisProgram'] && process.argv.length > 1) {
@@ -122,88 +103,15 @@ 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);
- }
+ if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof WorkerGlobalScope != 'undefined') 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?)');
} else
@@ -222,26 +130,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.slice(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?)');
+ if (!(typeof window == 'object' || typeof WorkerGlobalScope != 'undefined')) 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 +150,33 @@ 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 = async (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);
+ });
+ }
+ var response = await fetch(url, { credentials: 'same-origin' });
+ if (response.ok) {
+ return response.arrayBuffer();
+ }
+ throw new Error(response.status + ' : ' + response.url);
+ };
// end include: web_or_worker_shell_read.js
}
} else
@@ -279,7 +190,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 +203,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 +228,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 +243,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 +266,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) {
@@ -387,30 +297,24 @@ var HEAP,
HEAPU32,
/** @type {!Float32Array} */
HEAPF32,
+/* BigInt64Array type is not correctly defined in closure
+/** not-@type {!BigInt64Array} */
+ HEAP64,
+/* BigUint64Array type is not correctly defined in closure
+/** not-t@type {!BigUint64Array} */
+ HEAPU64,
/** @type {!Float64Array} */
HEAPF64;
-function updateMemoryViews() {
- var b = wasmMemory.buffer;
- Module['HEAP8'] = HEAP8 = new Int8Array(b);
- Module['HEAP16'] = HEAP16 = new Int16Array(b);
- Module['HEAPU8'] = HEAPU8 = new Uint8Array(b);
- Module['HEAPU16'] = HEAPU16 = new Uint16Array(b);
- Module['HEAP32'] = HEAP32 = new Int32Array(b);
- Module['HEAPU32'] = HEAPU32 = new Uint32Array(b);
- Module['HEAPF32'] = HEAPF32 = new Float32Array(b);
- Module['HEAPF64'] = HEAPF64 = new Float64Array(b);
-}
-
-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,
- 'JS engine does not provide full typed array support');
+var runtimeInitialized = false;
-// If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY
-assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
-assert(!Module['INITIAL_MEMORY'], 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
+/**
+ * Indicates whether filename is delivered via file protocol (as opposed to http/https)
+ * @noinline
+ */
+var isFileURI = (filename) => filename.startsWith('file://');
+// include: runtime_shared.js
// include: runtime_stack_check.js
// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
function writeStackCookie() {
@@ -449,30 +353,153 @@ function checkStackCookie() {
}
}
// end include: runtime_stack_check.js
-// include: runtime_assertions.js
+// include: runtime_exceptions.js
+// end include: runtime_exceptions.js
+// include: runtime_debug.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
-var __ATEXIT__ = []; // functions called during shutdown
-var __ATPOSTRUN__ = []; // functions called after the main() is called
+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)');
+}
-var runtimeInitialized = false;
+function legacyModuleProp(prop, newName, incoming=true) {
+ if (!Object.getOwnPropertyDescriptor(Module, prop)) {
+ Object.defineProperty(Module, prop, {
+ configurable: true,
+ get() {
+ 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);
+
+ }
+ });
+ }
+}
+
+function ignoredModuleProp(prop) {
+ if (Object.getOwnPropertyDescriptor(Module, prop)) {
+ abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`);
+ }
+}
+
+// forcing the filesystem exports a few things by default
+function isExportedByForceFilesystem(name) {
+ return name === 'FS_createPath' ||
+ name === 'FS_createDataFile' ||
+ name === 'FS_createPreloadedFile' ||
+ name === 'FS_unlink' ||
+ name === 'addRunDependency' ||
+ // The old FS has some functionality that WasmFS lacks.
+ name === 'FS_createLazyFile' ||
+ name === 'FS_createDevice' ||
+ name === 'removeRunDependency';
+}
-var runtimeKeepaliveCounter = 0;
+/**
+ * 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() {
+ func();
+ return undefined;
+ }
+ });
+ }
+}
-function keepRuntimeAlive() {
- return noExitRuntime || runtimeKeepaliveCounter > 0;
+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) {
+ 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);
+}
+
+function unexportedRuntimeSymbol(sym) {
+ if (!Object.getOwnPropertyDescriptor(Module, sym)) {
+ Object.defineProperty(Module, sym, {
+ configurable: true,
+ get() {
+ 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';
+ }
+ abort(msg);
+ }
+ });
+ }
+}
+
+// Used by XXXXX_DEBUG settings to output debug messages.
+function dbg(...args) {
+ // TODO(sbc): Make this configurable somehow. Its not always convenient for
+ // logging to show up as warnings.
+ console.warn(...args);
+}
+// end include: runtime_debug.js
+// include: memoryprofiler.js
+// end include: memoryprofiler.js
+
+
+function updateMemoryViews() {
+ var b = wasmMemory.buffer;
+ Module['HEAP8'] = HEAP8 = new Int8Array(b);
+ Module['HEAP16'] = HEAP16 = new Int16Array(b);
+ Module['HEAPU8'] = HEAPU8 = new Uint8Array(b);
+ Module['HEAPU16'] = HEAPU16 = new Uint16Array(b);
+ Module['HEAP32'] = HEAP32 = new Int32Array(b);
+ Module['HEAPU32'] = HEAPU32 = new Uint32Array(b);
+ Module['HEAPF32'] = HEAPF32 = new Float32Array(b);
+ Module['HEAPF64'] = HEAPF64 = new Float64Array(b);
+ Module['HEAP64'] = HEAP64 = new BigInt64Array(b);
+ Module['HEAPU64'] = HEAPU64 = new BigUint64Array(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,
+ 'JS engine does not provide full typed array support');
+
+// If memory is defined in wasm, the user can't provide it, or set INITIAL_MEMORY
+assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
+assert(!Module['INITIAL_MEMORY'], 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
+
function preRun() {
if (Module['preRun']) {
if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
@@ -480,7 +507,7 @@ function preRun() {
addOnPreRun(Module['preRun'].shift());
}
}
- callRuntimeCallbacks(__ATPRERUN__);
+ callRuntimeCallbacks(onPreRuns);
}
function initRuntime() {
@@ -490,13 +517,15 @@ function initRuntime() {
checkStackCookie();
- callRuntimeCallbacks(__ATINIT__);
+
+ wasmExports['__wasm_call_ctors']();
+
+
}
function preMain() {
checkStackCookie();
- callRuntimeCallbacks(__ATMAIN__);
}
function postRun() {
@@ -509,42 +538,9 @@ function postRun() {
}
}
- callRuntimeCallbacks(__ATPOSTRUN__);
-}
-
-function addOnPreRun(cb) {
- __ATPRERUN__.unshift(cb);
+ callRuntimeCallbacks(onPostRuns);
}
-function addOnInit(cb) {
- __ATINIT__.unshift(cb);
-}
-
-function addOnPreMain(cb) {
- __ATMAIN__.unshift(cb);
-}
-
-function addOnExit(cb) {
-}
-
-function addOnPostRun(cb) {
- __ATPOSTRUN__.unshift(cb);
-}
-
-// include: runtime_math.js
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
-
-assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
-assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
-assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
-assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
-// end include: runtime_math.js
// A counter of dependencies for calling run(). If we need to
// do asynchronous work before running, increment this and
// decrement it. Incrementing must happen in a place like
@@ -553,9 +549,9 @@ assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGAC
// it happens right before run - run will be postponed until
// the dependencies are met.
var runDependencies = 0;
-var runDependencyWatcher = null;
var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
var runDependencyTracking = {};
+var runDependencyWatcher = null;
function getUniqueRunDependency(id) {
var orig = id;
@@ -568,9 +564,7 @@ function getUniqueRunDependency(id) {
function addRunDependency(id) {
runDependencies++;
- if (Module['monitorRunDependencies']) {
- Module['monitorRunDependencies'](runDependencies);
- }
+ Module['monitorRunDependencies']?.(runDependencies);
if (id) {
assert(!runDependencyTracking[id]);
@@ -604,9 +598,7 @@ function addRunDependency(id) {
function removeRunDependency(id) {
runDependencies--;
- if (Module['monitorRunDependencies']) {
- Module['monitorRunDependencies'](runDependencies);
- }
+ Module['monitorRunDependencies']?.(runDependencies);
if (id) {
assert(runDependencyTracking[id]);
@@ -629,9 +621,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 +629,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 +640,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} */
@@ -663,8 +652,6 @@ function abort(what) {
throw e;
}
-// include: memoryprofiler.js
-// end include: memoryprofiler.js
// show errors on likely calls to FS when it was not included
var FS = {
error() {
@@ -684,37 +671,21 @@ var FS = {
Module['FS_createDataFile'] = FS.createDataFile;
Module['FS_createPreloadedFile'] = FS.createPreloadedFile;
-// include: URIUtils.js
-// 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://');
-}
-// 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
var wasmBinaryFile;
- wasmBinaryFile = 'output.wasm';
- if (!isDataURI(wasmBinaryFile)) {
- wasmBinaryFile = locateFile(wasmBinaryFile);
- }
+function findWasmBinary() {
+ return locateFile('output.wasm');
+}
function getBinarySync(file) {
if (file == wasmBinaryFile && wasmBinary) {
@@ -723,45 +694,31 @@ 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 (!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)
- });
+async function getWasmBinary(binaryFile) {
+ // If we don't have the binary yet, load it asynchronously using readAsync.
+ if (!wasmBinary) {
+ // Fetch the binary using readAsync
+ try {
+ var response = await readAsync(binaryFile);
+ return new Uint8Array(response);
+ } catch {
+ // Fall back to getBinarySync below;
}
}
// Otherwise, getBinarySync should be able to get it synchronously
- return Promise.resolve().then(() => getBinarySync(binaryFile));
+ return getBinarySync(binaryFile);
}
-function instantiateArrayBuffer(binaryFile, imports, receiver) {
- return getBinaryPromise(binaryFile).then((binary) => {
- return WebAssembly.instantiate(binary, imports);
- }).then((instance) => {
+async function instantiateArrayBuffer(binaryFile, imports) {
+ try {
+ var binary = await getWasmBinary(binaryFile);
+ var instance = await WebAssembly.instantiate(binary, imports);
return instance;
- }).then(receiver, (reason) => {
+ } catch (reason) {
err(`failed to asynchronously prepare wasm: ${reason}`);
// Warn on some common problems.
@@ -769,53 +726,47 @@ function instantiateArrayBuffer(binaryFile, imports, receiver) {
err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`);
}
abort(reason);
- });
+ }
}
-function instantiateAsync(binary, binaryFile, imports, callback) {
- if (!binary &&
- typeof WebAssembly.instantiateStreaming == 'function' &&
- !isDataURI(binaryFile) &&
+async function instantiateAsync(binary, binaryFile, imports) {
+ if (!binary && typeof WebAssembly.instantiateStreaming == 'function'
// Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
- !isFileURI(binaryFile) &&
+ && !isFileURI(binaryFile)
// Avoid instantiateStreaming() on Node.js environment for now, as while
// Node.js v18.1.0 implements it, it does not have a full fetch()
// implementation yet.
//
// Reference:
// https://github.com/emscripten-core/emscripten/pull/16917
- !ENVIRONMENT_IS_NODE &&
- typeof fetch == 'function') {
- return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => {
- // Suppress closure warning here since the upstream definition for
- // instantiateStreaming only allows Promise<Repsponse> rather than
- // an actual Response.
- // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed.
- /** @suppress {checkTypes} */
- var result = WebAssembly.instantiateStreaming(response, imports);
-
- return result.then(
- callback,
- function(reason) {
- // We expect the most common failure cause to be a bad MIME type for the binary,
- // in which case falling back to ArrayBuffer instantiation should work.
- err(`wasm streaming compile failed: ${reason}`);
- err('falling back to ArrayBuffer instantiation');
- return instantiateArrayBuffer(binaryFile, imports, callback);
- });
- });
- }
- return instantiateArrayBuffer(binaryFile, imports, callback);
+ && !ENVIRONMENT_IS_NODE
+ ) {
+ try {
+ var response = fetch(binaryFile, { credentials: 'same-origin' });
+ var instantiationResult = await WebAssembly.instantiateStreaming(response, imports);
+ return instantiationResult;
+ } catch (reason) {
+ // We expect the most common failure cause to be a bad MIME type for the binary,
+ // in which case falling back to ArrayBuffer instantiation should work.
+ err(`wasm streaming compile failed: ${reason}`);
+ err('falling back to ArrayBuffer instantiation');
+ // fall back of instantiateArrayBuffer below
+ };
+ }
+ return instantiateArrayBuffer(binaryFile, imports);
}
-// 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.
+async function createWasm() {
// 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,18 +778,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");
-
- addOnInit(wasmExports['__wasm_call_ctors']);
+ assert(wasmTable, 'table not found in wasm exports');
removeRunDependency('wasm-instantiate');
return wasmExports;
@@ -858,9 +803,11 @@ function createWasm() {
trueModule = null;
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
// When the regression is fixed, can restore the above PTHREADS-enabled path.
- receiveInstance(result['instance']);
+ return receiveInstance(result['instance']);
}
+ var info = getWasmImports();
+
// User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
// to manually instantiate the Wasm module themselves. This allows pages to
// run the instantiation parallel to any other async startup actions they are
@@ -868,131 +815,36 @@ 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) {
- err(`Module.instantiateWasm callback failed with error: ${e}`);
- return false;
- }
- }
-
- instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult);
- return {}; // no exports yet; we'll fill them in later
-}
-
-// Globals used by JS i64 conversions (see makeSetValue)
-var tempDouble;
-var tempI64;
-
-// include: runtime_debug.js
-function legacyModuleProp(prop, newName, incomming=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)' : '';
- abort(`\`Module.${prop}\` has been replaced by \`${newName}\`` + extra);
-
- }
- });
- }
-}
-
-function ignoredModuleProp(prop) {
- if (Object.getOwnPropertyDescriptor(Module, prop)) {
- abort(`\`Module.${prop}\` was supplied but \`${prop}\` not included in INCOMING_MODULE_JS_API`);
- }
-}
-
-// forcing the filesystem exports a few things by default
-function isExportedByForceFilesystem(name) {
- return name === 'FS_createPath' ||
- name === 'FS_createDataFile' ||
- name === 'FS_createPreloadedFile' ||
- name === 'FS_unlink' ||
- name === 'addRunDependency' ||
- // The old FS has some functionality that WasmFS lacks.
- name === 'FS_createLazyFile' ||
- name === 'FS_createDevice' ||
- name === 'removeRunDependency';
-}
-
-function missingGlobal(sym, msg) {
- if (typeof globalThis !== 'undefined') {
- Object.defineProperty(globalThis, sym, {
- configurable: true,
- get() {
- warnOnce('`' + sym + '` is not longer defined by emscripten. ' + msg);
- return undefined;
+ return new Promise((resolve, reject) => {
+ try {
+ Module['instantiateWasm'](info, (mod, inst) => {
+ receiveInstance(mod, inst);
+ resolve(mod.exports);
+ });
+ } catch(e) {
+ err(`Module.instantiateWasm callback failed with error: ${e}`);
+ reject(e);
}
});
}
-}
-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)
- // not exported on the Module object.
- unexportedRuntimeSymbol(sym);
-}
+ wasmBinaryFile ??= findWasmBinary();
-function unexportedRuntimeSymbol(sym) {
- if (!Object.getOwnPropertyDescriptor(Module, sym)) {
- Object.defineProperty(Module, sym, {
- configurable: true,
- get() {
- 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';
- }
- abort(msg);
- }
- });
- }
+ var result = await instantiateAsync(wasmBinary, wasmBinaryFile, info);
+ var exports = receiveInstantiationResult(result);
+ return exports;
}
-// Used by XXXXX_DEBUG settings to output debug messages.
-function dbg(text) {
- // TODO(sbc): Make this configurable somehow. Its not always convenient for
- // logging to show up as warnings.
- console.warn.apply(console, arguments);
-}
-// end include: runtime_debug.js
// === Body ===
-
// end include: preamble.js
- /** @constructor */
- function ExitStatus(status) {
- this.name = 'ExitStatus';
- this.message = `Program terminated with exit(${status})`;
- this.status = status;
+
+ class ExitStatus {
+ name = 'ExitStatus';
+ constructor(status) {
+ this.message = `Program terminated with exit(${status})`;
+ this.status = status;
+ }
}
var callRuntimeCallbacks = (callbacks) => {
@@ -1001,6 +853,12 @@ function dbg(text) {
callbacks.shift()(Module);
}
};
+ var onPostRuns = [];
+ var addOnPostRun = (cb) => onPostRuns.unshift(cb);
+
+ var onPreRuns = [];
+ var addOnPreRun = (cb) => onPreRuns.unshift(cb);
+
/**
@@ -1010,11 +868,11 @@ 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');
+ case 'i64': return HEAP64[((ptr)>>3)];
case 'float': return HEAPF32[((ptr)>>2)];
case 'double': return HEAPF64[((ptr)>>3)];
case '*': return HEAPU32[((ptr)>>2)];
@@ -1022,6 +880,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,11 +898,11 @@ 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');
+ case 'i64': HEAP64[((ptr)>>3)] = BigInt(value); break;
case 'float': HEAPF32[((ptr)>>2)] = value; break;
case 'double': HEAPF64[((ptr)>>3)] = value; break;
case '*': HEAPU32[((ptr)>>2)] = value; break;
@@ -1050,8 +910,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,20 +923,10 @@ function dbg(text) {
}
};
- function __emscripten_fetch_free(id) {
- if (Fetch.xhrs.has(id)) {
- var xhr = Fetch.xhrs.get(id);
- Fetch.xhrs.free(id);
- // check if fetch is still in progress and should be aborted
- if (xhr.readyState > 0 && xhr.readyState < 4) {
- xhr.abort();
- }
- }
- }
+ var __abort_js = () =>
+ abort('native code called abort()');
- var isLeapYear = (year) => {
- return year%4 === 0 && (year%100 !== 0 || year%400 === 0);
- };
+ 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];
@@ -1085,13 +939,12 @@ function dbg(text) {
return yday;
};
- var convertI32PairToI53Checked = (lo, hi) => {
- assert(lo == (lo >>> 0) || lo == (lo|0)); // lo should either be a i32 or a u32
- assert(hi === (hi|0)); // hi should be a i32
- 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 INT53_MAX = 9007199254740992;
+
+ var INT53_MIN = -9007199254740992;
+ var bigintToI53Checked = (num) => (num < INT53_MIN || num > INT53_MAX) ? NaN : Number(num);
+ function __localtime_js(time, tmPtr) {
+ time = bigintToI53Checked(time);
var date = new Date(time*1000);
@@ -1116,29 +969,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 +1021,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 +1049,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 +1066,60 @@ 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;
- };
+ function _emscripten_fetch_free(id) {
+ if (Fetch.xhrs.has(id)) {
+ var xhr = Fetch.xhrs.get(id);
+ Fetch.xhrs.free(id);
+ // check if fetch is still in progress and should be aborted
+ if (xhr.readyState > 0 && xhr.readyState < 4) {
+ xhr.abort();
+ }
+ }
+ }
+
+ var onExits = [];
+ var addOnExit = (cb) => onExits.unshift(cb);
var JSEvents = {
- inEventHandler:0,
+ memcpy(target, src, size) {
+ HEAP8.set(HEAP8.subarray(src, src + size), target);
+ },
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 +1131,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 +1145,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 +1163,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 +1189,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 +1222,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,25 +1233,25 @@ function dbg(text) {
},
};
- var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined;
+ 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=} idx
* @param {number=} maxBytesToRead
* @return {string}
*/
- var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => {
+ 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 means Infinity)
+ // so that undefined/NaN means Infinity)
while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
@@ -1452,7 +1303,7 @@ function dbg(text) {
* @return {string}
*/
var UTF8ToString = (ptr, maxBytesToRead) => {
- assert(typeof ptr == 'number');
+ assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`);
return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
};
var maybeCStringToJsString = (cString) => {
@@ -1463,10 +1314,11 @@ 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);
- var domElement = specialHTMLTargets[target] || (typeof document != 'undefined' ? document.querySelector(target) : undefined);
+ var domElement = specialHTMLTargets[target] || (typeof document != 'undefined' ? document.querySelector(target) : null);
return domElement;
};
@@ -1485,18 +1337,19 @@ 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];
if (!func) {
if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;
+ /** @suppress {checkTypes} */
wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
}
- assert(wasmTable.get(funcPtr) == func, "JavaScript-side Wasm function table mirror is out of date!");
+ /** @suppress {checkTypes} */
+ 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 +1368,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 +1420,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 +1428,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 +1441,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 +1456,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 +1511,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 +1529,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 +1555,36 @@ 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 {
+ allocated = [undefined];
+ 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 +1594,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 +1621,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 +1641,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 +1677,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 +1686,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 +1696,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 +1708,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 +1719,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 +1741,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 +1761,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 +1793,18 @@ 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 +1822,7 @@ function dbg(text) {
};
var _exit = exitJS;
+
var maybeExit = () => {
if (!keepRuntimeAlive()) {
try {
@@ -2025,9 +1868,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 +1878,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 +1887,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 +1903,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 +1920,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 +1953,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 +1965,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 +1993,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 +2013,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 +2028,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 +2048,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 +2086,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,9 +2132,77 @@ function dbg(text) {
return !!(ctx.mdibvbi = ctx.getExtension('WEBGL_multi_draw_instanced_base_vertex_base_instance'));
};
- var webgl_enable_WEBGL_multi_draw = (ctx) => {
+ var webgl_enable_EXT_polygon_offset_clamp = (ctx) =>
+ !!(ctx.extPolygonOffsetClamp = ctx.getExtension('EXT_polygon_offset_clamp'));
+
+ var webgl_enable_EXT_clip_control = (ctx) =>
+ !!(ctx.extClipControl = ctx.getExtension('EXT_clip_control'));
+
+ var webgl_enable_WEBGL_polygon_mode = (ctx) =>
+ !!(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'));
+ !!(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);
};
@@ -2312,7 +2231,8 @@ function dbg(text) {
stringiCache:{
},
unpackAlignment:4,
- recordError:function recordError(errorCode) {
+ unpackRowLength:0,
+ recordError:(errorCode) => {
if (!GL.lastError) {
GL.lastError = errorCode;
}
@@ -2322,13 +2242,30 @@ function dbg(text) {
for (var i = table.length; i < ret; i++) {
table[i] = null;
}
+ // Skip over any non-null elements that might have been created by
+ // glBindBuffer.
+ while (table[ret]) {
+ ret = GL.counter++;
+ }
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 +2316,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 +2332,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 +2345,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 +2363,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 +2376,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 +2396,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 +2448,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 +2459,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 +2477,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]?.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 +2544,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,33 +2556,38 @@ 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]
};
+ // TODO: Make these into hard errors at some point in the future
+ if (contextAttributes.majorVersion !== 1 && contextAttributes.majorVersion !== 2) {
+ err(`Invalid WebGL version requested: ${contextAttributes.majorVersion}`);
+ }
+
var canvas = findCanvasEventTarget(target);
if (!canvas) {
@@ -2629,34 +2603,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);;
+ function _fd_seek(fd, offset, whence, newOffset) {
+ offset = bigintToI53Checked(offset);
return 70;
@@ -2669,7 +2633,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);
@@ -2705,6 +2669,14 @@ function dbg(text) {
};
var _glBindBuffer = (target, buffer) => {
+ // Calling glBindBuffer with an unknown buffer will implicitly create a
+ // new one. Here we bypass `GL.counter` and directly using the ID passed
+ // in.
+ if (buffer && !GL.buffers[buffer]) {
+ var b = GLctx.createBuffer();
+ b.name = buffer;
+ GL.buffers[buffer] = b;
+ }
if (target == 0x8892 /*GL_ARRAY_BUFFER*/) {
GLctx.currentArrayBufferBinding = buffer;
} else if (target == 0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/) {
@@ -2712,9 +2684,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 +2707,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 +2753,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 +2791,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 +2805,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 +2823,7 @@ function dbg(text) {
}
};
- function _glDepthFunc(x0) { GLctx.depthFunc(x0) }
+ var _glDepthFunc = (x0) => GLctx.depthFunc(x0);
var _glDepthMask = (flag) => {
GLctx.depthMask(!!flag);
@@ -2858,19 +2840,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 +2886,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,36 +2894,19 @@ 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) => {
- return GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name));
- };
+ var _glGetAttribLocation = (program, name) =>
+ GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name));
var _glGetProgramInfoLog = (program, maxLength, length, infoLog) => {
var log = GLctx.getProgramInfoLog(GL.programs[program]);
@@ -2929,8 +2917,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 +2937,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 +2974,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 +3004,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 +3019,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 +3059,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 +3076,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 +3090,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 +3118,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;
@@ -3138,18 +3136,19 @@ function dbg(text) {
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 +3169,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 +3206,35 @@ 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 */
- _emscripten_fetch_free: __emscripten_fetch_free,
+ _abort_js: __abort_js,
/** @export */
_localtime_js: __localtime_js,
/** @export */
_tzset_js: __tzset_js,
/** @export */
- abort: _abort,
- /** @export */
emscripten_date_now: _emscripten_date_now,
/** @export */
+ emscripten_fetch_free: _emscripten_fetch_free,
+ /** @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 +3249,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,
@@ -3331,23 +3329,21 @@ var wasmImports = {
/** @export */
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 wasmExports;
+createWasm();
+var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors', 0);
+var _free = createExportWrapper('free', 1);
+var _malloc = createExportWrapper('malloc', 1);
+var _main = Module['_main'] = createExportWrapper('main', 2);
+var _fflush = createExportWrapper('fflush', 1);
+var _strerror = createExportWrapper('strerror', 1);
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');
// include: postamble.js
@@ -3359,39 +3355,35 @@ var missingLibrarySymbols = [
'writeI53ToU64Clamped',
'writeI53ToU64Signaling',
'convertI32PairToI53',
+ 'convertI32PairToI53Checked',
'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',
- 'dynCallLegacy',
'getDynCaller',
'dynCall',
'runtimeKeepalivePush',
'runtimeKeepalivePop',
- 'safeSetTimeout',
'asmjsMangle',
'asyncLoad',
- 'alignMemory',
'mmapAlloc',
'getNativeTypeSize',
+ 'addOnInit',
+ 'addOnPostCtor',
+ 'addOnPreMain',
'STACK_SIZE',
'STACK_ALIGN',
'POINTER_SIZE',
@@ -3423,6 +3415,7 @@ var missingLibrarySymbols = [
'UTF32ToString',
'stringToUTF32',
'lengthBytesUTF32',
+ 'stringToNewUTF8',
'stringToUTF8OnStack',
'writeArrayToMemory',
'registerKeyEventCallback',
@@ -3460,37 +3453,41 @@ var missingLibrarySymbols = [
'registerBatteryEventCallback',
'setCanvasElementSize',
'getCanvasElementSize',
- 'demangle',
- 'demangleAll',
'jsStackTrace',
- 'stackTrace',
+ 'getCallstack',
+ 'convertPCtoSourceLocation',
'getEnvStrings',
'checkWasiClock',
'wasiRightsToMuslOFlags',
'wasiOFlagsToMuslOFlags',
- 'createDyncallWrapper',
+ 'initRandomFill',
+ 'randomFill',
+ 'safeSetTimeout',
'setImmediateWrapped',
+ 'safeRequestAnimationFrame',
'clearImmediateWrapped',
- 'polyfillSetImmediate',
+ 'registerPostMainLoop',
'getPromise',
'makePromise',
'idsToPromises',
'makePromiseCallback',
'ExceptionInfo',
'findMatchingCatch',
- 'setMainLoop',
+ 'Browser_asyncPrepareDataCounter',
+ '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,78 +3500,63 @@ 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)
var unexportedSymbols = [
'run',
- 'addOnPreRun',
- 'addOnInit',
- 'addOnPreMain',
- 'addOnExit',
- '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',
+ 'INT53_MAX',
+ 'INT53_MIN',
+ 'bigintToI53Checked',
+ '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',
+ 'addOnPreRun',
+ 'addOnExit',
+ 'addOnPostRun',
'freeTableIndexes',
'functionsInTableMap',
'setValue',
@@ -3588,7 +3570,6 @@ var unexportedSymbols = [
'stringToUTF8',
'lengthBytesUTF8',
'UTF16Decoder',
- 'stringToNewUTF8',
'JSEvents',
'specialHTMLTargets',
'maybeCStringToJsString',
@@ -3600,18 +3581,34 @@ var unexportedSymbols = [
'registerUiEventCallback',
'currentFullscreenStrategy',
'restoreOldWindowedStyle',
+ 'UNWIND_CACHE',
'ExitStatus',
'flush_NO_FILESYSTEM',
+ 'emSetImmediate',
+ 'emClearImmediate_deps',
+ 'emClearImmediate',
+ '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 +3620,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 +3638,8 @@ var unexportedSymbols = [
'webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance',
'allocateUTF8',
'allocateUTF8OnStack',
+ 'print',
+ 'printErr',
'Fetch',
'fetchDeleteCachedData',
'fetchLoadCachedData',
@@ -3652,15 +3652,9 @@ unexportedSymbols.forEach(unexportedRuntimeSymbol);
var calledRun;
-dependenciesFulfilled = function runCaller() {
- // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
- if (!calledRun) run();
- if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled
-};
-
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(typeof onPreRuns === 'undefined' || onPreRuns.length == 0, 'cannot call main when preRun functions remain to be called');
var entryFunction = _main;
@@ -3674,8 +3668,7 @@ function callMain() {
// if we're not running an evented main loop, it's time to exit
exitJS(ret, /* implicit = */ true);
return ret;
- }
- catch (e) {
+ } catch (e) {
return handleException(e);
}
}
@@ -3692,22 +3685,24 @@ function stackCheckInit() {
function run() {
if (runDependencies > 0) {
+ dependenciesFulfilled = run;
return;
}
- stackCheckInit();
+ stackCheckInit();
preRun();
// a preRun added a dependency, run will be called later
if (runDependencies > 0) {
+ dependenciesFulfilled = run;
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;
+ assert(!calledRun);
calledRun = true;
Module['calledRun'] = true;
@@ -3717,19 +3712,18 @@ function run() {
preMain();
- if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
+ Module['onRuntimeInitialized']?.();
- if (shouldRunNow) callMain();
+ var noInitialRun = Module['noInitialRun'];legacyModuleProp('noInitialRun', 'noInitialRun');
+ if (!noInitialRun) callMain();
postRun();
}
if (Module['setStatus']) {
Module['setStatus']('Running...');
- setTimeout(function() {
- setTimeout(function() {
- Module['setStatus']('');
- }, 1);
+ setTimeout(() => {
+ setTimeout(() => Module['setStatus'](''), 1);
doRun();
}, 1);
} else
@@ -3775,12 +3769,7 @@ if (Module['preInit']) {
}
}
-// shouldRunNow refers to calling main(), not run().
-var shouldRunNow = true;
-
-if (Module['noInitialRun']) shouldRunNow = false;
-
run();
-
// end include: postamble.js
+
diff --git a/themes/dist/output.wasm b/themes/dist/output.wasm
index 925d783..9754410 100755
--- a/themes/dist/output.wasm
+++ b/themes/dist/output.wasm
Binary files differ
diff --git a/themes/src/MainLoop.h b/themes/src/MainLoop.h
index 2573bb8..07520a2 100644
--- a/themes/src/MainLoop.h
+++ b/themes/src/MainLoop.h
@@ -26,4 +26,4 @@ struct MainLoop {
void stop() {
isRunning = false;
}
-}; \ No newline at end of file
+};
diff --git a/themes/src/main.cpp b/themes/src/main.cpp
index 14227c9..d9cfc01 100644
--- a/themes/src/main.cpp
+++ b/themes/src/main.cpp
@@ -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) {