Skip to content

Fix #472: Emscripten Frontend#662

Merged
lefticus merged 2 commits intoChaiScript:developfrom
leftibot:fix/issue-472-emscripten-frontend
Apr 11, 2026
Merged

Fix #472: Emscripten Frontend#662
lefticus merged 2 commits intoChaiScript:developfrom
leftibot:fix/issue-472-emscripten-frontend

Conversation

@leftibot
Copy link
Copy Markdown
Contributor

Automated fix by @leftibot.

What changed

Fix #472: Add Emscripten/WebAssembly build for browser-based ChaiScript
Port Rob Loach's ChaiScript.js work (https://github.com/RobLoach/ChaiScript.js)
into the main repository as an Emscripten build target. Adds a GitHub Actions
workflow that builds ChaiScript to WebAssembly and publishes artifacts (JS, WASM,
HTML) for embedding in the official ChaiScript.com website. Includes an HTML
interactive playground frontend and a native test validating the eval API surface.
Co-Authored-By: Rob Loach [email protected]
Co-Authored-By: Claude Opus 4.6 (1M context) [email protected]

Files

 .github/workflows/emscripten.yml   |  42 +++++++
 CMakeLists.txt                     |   4 +
 emscripten/CMakeLists.txt          |  35 ++++++
 emscripten/chaiscript.html         | 237 +++++++++++++++++++++++++++++++++++++
 emscripten/chaiscript_em.cpp       |  23 ++++
 emscripten/chaiscript_eval.hpp     |  48 ++++++++
 unittests/emscripten_eval_test.cpp |  51 ++++++++
 7 files changed, 440 insertions(+)

Closes #472

Triggered by @lefticus.

…d ChaiScript

Port Rob Loach's ChaiScript.js work (https://github.com/RobLoach/ChaiScript.js)
into the main repository as an Emscripten build target. Adds a GitHub Actions
workflow that builds ChaiScript to WebAssembly and publishes artifacts (JS, WASM,
HTML) for embedding in the official ChaiScript.com website. Includes an HTML
interactive playground frontend and a native test validating the eval API surface.

Co-Authored-By: Rob Loach <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@lefticus
Copy link
Copy Markdown
Member

@leftibot what is the next steps for actually utilizing this on the website?

@leftibot
Copy link
Copy Markdown
Contributor Author

Good question. Right now the workflow builds the artifacts and uploads them via actions/upload-artifact, but there's no deployment step — the WASM build just sits as a downloadable zip on the Actions run. Here's what I'd suggest as next steps:

1. Decide on hosting strategy

A few options depending on where chaiscript.com is hosted:

  • GitHub Pages (simplest): Add a deployment step to the workflow that publishes chaiscript.js, chaiscript.wasm, and chaiscript.html to a gh-pages branch or uses the actions/deploy-pages action. Could live at something like chaiscript.com/playground.
  • Embed in existing site: If chaiscript.com is built separately (e.g., Jekyll, Hugo, or a custom site), the workflow could push the built artifacts to that site's repo or an S3 bucket / CDN as part of a release.
  • Subdomain: Host at try.chaiscript.com or playground.chaiscript.com pointing to GitHub Pages on this repo.

2. Integrate with the site design

The current chaiscript.html is a standalone page. To integrate with the existing site you'd want to either:

  • Embed it in the site's existing layout/navigation (header, footer, links)
  • Or keep it standalone but link to it from the main site

3. Serve .wasm with correct MIME type

Whatever hosting you use needs to serve .wasm files with Content-Type: application/wasm. GitHub Pages does this correctly out of the box. If using another host, this may need configuration.

4. Trigger deployment on release (not every push)

The current workflow runs on every push/PR to develop/main. For the actual website deployment, you'd probably want to either:

  • Deploy only from develop/main pushes (not PRs)
  • Or tie deployment to tagged releases

5. Concrete next step

The smallest useful change would be adding a GitHub Pages deploy job to emscripten.yml. Something like:

  deploy:
    needs: emscripten
    if: github.ref == 'refs/heads/develop' && github.event_name == 'push'
    runs-on: ubuntu-latest
    permissions:
      pages: write
      id-token: write
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: chaiscript-web
          path: site
      - uses: actions/configure-pages@v4
      - uses: actions/upload-pages-artifact@v4
        with:
          path: site
      - id: deployment
        uses: actions/deploy-pages@v4

That would get the playground live immediately. Want me to add a deployment job to the workflow?

@lefticus
Copy link
Copy Markdown
Member

@leftibot can it be deployed to https://github.com/ChaiScript/chaiscript.github.io directly with an action? The site is currently in a separate repo, not in the gh-pages branch

@leftibot
Copy link
Copy Markdown
Contributor Author

Yes, absolutely. You can push to ChaiScript/chaiscript.github.io from this repo's workflow using a deploy key or a PAT. Here's the approach:

Using a deploy key (recommended)

  1. Generate an SSH keypair (ssh-keygen -t ed25519 -f deploy_key -N "")
  2. Add the public key as a deploy key on ChaiScript/chaiscript.github.io with write access
  3. Add the private key as a secret (e.g., DEPLOY_KEY) on ChaiScript/ChaiScript

Then add a deploy job to the workflow:

  deploy:
    needs: emscripten
    if: github.ref == 'refs/heads/develop' && github.event_name == 'push'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: chaiscript-web
          path: artifacts

      - name: Clone target repo
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}
        run: |
          mkdir -p ~/.ssh
          echo "$SSH_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          export GIT_SSH_COMMAND="ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no"
          git clone [email protected]:ChaiScript/chaiscript.github.io.git target

      - name: Copy artifacts and push
        run: |
          export GIT_SSH_COMMAND="ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no"
          # Copy into a subdirectory so it doesn't clobber the existing site
          mkdir -p target/playground
          cp artifacts/build-em/chaiscript.js target/playground/
          cp artifacts/build-em/chaiscript.wasm target/playground/
          cp artifacts/build-em/chaiscript.html target/playground/index.html
          cd target
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add playground/
          git diff --cached --quiet || git commit -m "Update ChaiScript playground from ChaiScript/ChaiScript@${GITHUB_SHA::8}"
          git push

This would make the playground available at chaiscript.com/playground (or whatever path the site uses) without interfering with the rest of the site content.

Alternative: PAT

A GitHub PAT with repo scope stored as a secret also works (git clone https://x-access-token:${{ secrets.PAT }}@github.com/ChaiScript/chaiscript.github.io.git), but a deploy key is scoped to just that one repo, which is cleaner from a security perspective.

Want me to update the workflow in this PR to include the deploy job? You'd just need to set up the deploy key / secret on both repos.

@lefticus
Copy link
Copy Markdown
Member

@leftibot can it possibly go the other way there the website is triggered to rebuild whenever there's a new artifact on "main" or "develop" here so that we don't need to do the keys and permissions thing?

@leftibot
Copy link
Copy Markdown
Contributor Author

Unfortunately, there's no fully "zero-auth" way to trigger a cross-repo workflow in GitHub Actions. The workflow_run trigger only works within the same repository, and repository_dispatch (the standard way to trigger repo B from repo A) still requires a token with write access to the target repo.

That said, there's a lightweight approach that avoids deploy keys entirely:

Publish as a GitHub Release asset (no cross-repo auth needed)

  1. This repo's workflow attaches the built .js, .wasm, and .html files as assets on a GitHub Release (or even a "rolling" pre-release tag like latest-wasm). Release assets on public repos are downloadable without authentication.

  2. The website repo has a simple scheduled workflow (e.g., every 15 minutes or hourly) that:

    • Fetches the latest release from ChaiScript/ChaiScript via the public API
    • Downloads the assets
    • Checks if they differ from what's already committed
    • If changed, commits and pushes → triggers a site rebuild
# In chaiscript.github.io
on:
  schedule:
    - cron: '*/15 * * * *'  # every 15 min

jobs:
  update-playground:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Fetch latest WASM build
        run: |
          mkdir -p playground
          # Public API, no token needed for public repos
          RELEASE=$(curl -s https://api.github.com/repos/ChaiScript/ChaiScript/releases/tags/wasm-latest)
          for file in chaiscript.js chaiscript.wasm chaiscript.html; do
            URL=$(echo "$RELEASE" | jq -r ".assets[] | select(.name==\"$file\") | .browser_download_url")
            curl -sL "$URL" -o "playground/$file"
          done

      - name: Commit if changed
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add playground/
          git diff --cached --quiet || git commit -m "Update ChaiScript playground"
          git push

The tradeoff is up to 15 minutes of latency (or whatever cron interval you pick), but it requires zero secrets, zero keys, zero cross-repo permissions. The website repo just pulls from a public URL.

If you want instant triggering

You'd need at minimum a fine-grained PAT stored as a secret in this repo, scoped to just ChaiScript/chaiscript.github.io with actions:write permission — then this repo sends a repository_dispatch event. It's the lightest auth option for real-time triggering, but it does still require one secret.

The cron-based approach is probably the better fit here given that playground updates aren't time-critical.

@lefticus
Copy link
Copy Markdown
Member

@leftibot update this emscripten thing to publish assets under some tag, but only from develop branch, that is then fetchable by the website cron (daily is fine, really) then I'm going to tell you to update the website too.

Add a publish job to the emscripten workflow that creates a prerelease
tagged wasm-latest with chaiscript.js, chaiscript.wasm, and
chaiscript.html as downloadable assets. Runs only on pushes to the
develop branch. The website repo can fetch these via the public
GitHub Releases API on a daily cron without any cross-repo auth.

Requested by @lefticus in PR ChaiScript#662 review.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@leftibot
Copy link
Copy Markdown
Contributor Author

Addressed review feedback from @lefticus. New commits:

316d605f Address review: publish WASM assets as release under wasm-latest tag

@lefticus lefticus merged commit 340e7d4 into ChaiScript:develop Apr 11, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Emscripten Frontend

2 participants