Skip to content

Comments

Support string requires of globalThis js deps #95#129

Merged
borkdude merged 2 commits intobabashka:mainfrom
chr15m:globalthis-require
Aug 21, 2025
Merged

Support string requires of globalThis js deps #95#129
borkdude merged 2 commits intobabashka:mainfrom
chr15m:globalthis-require

Conversation

@chr15m
Copy link
Contributor

@chr15m chr15m commented Aug 21, 2025

Fixes #95. This patch updates Scittle to support requiring already-loaded script tag JS deps off globalThis. Workflow:

<script src="https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js"></script>
(ns main
  (:require
    ["JSConfetti" :as c]))

(.addConfetti (c.))

You can also use esm imports in your index.html if you monkey-patch them onto globalThis/window before Scittle runs.

I'm not sure my naïve implementation is future proof so don't hesitate to reject or ask for changes. On #95 we spoked about David's plan to give globalThis requires a special syntax, and this patch should be forwards compatible with any future syntax I think.

In future it could also be adapted to load es modules using maybe sci.async. So it would try two loaders for a string require: 1. from globalThis 2. looking up the import map and doing an async esm import from the url specified. That's outside the scope of this PR though.


Please answer the following questions and leave the below in as part of your PR.

@borkdude
Copy link
Collaborator

borkdude commented Aug 21, 2025

You can also use esm imports in your index.html if you monkey-patch them onto globalThis/window before Scittle runs.

Nice!

I guess it's guaranteed that the type=module script tag always runs first?

<html>
  <head>
    <script type="module">
      import confetti from "https://esm.sh/[email protected]"
      globalThis.x = await(Promise.resolve(1));
      globalThis.JSConfetti = confetti;
    </script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/scittle.js" type="application/javascript"></script>
    <script type="application/x-scittle">
      (js/console.log js/x)
      (js/JSConfetti)
    </script>
  </head>
  <body>
  </body>
</html>

@borkdude
Copy link
Collaborator

Hmm, according to some sources (ChatGPT...) the type=module isn't guaranteed to finish before the "sync" script tag since it's always defer-ed by default

@borkdude
Copy link
Collaborator

borkdude commented Aug 21, 2025

Yeah here's a counter-example:

<html>
  <head>
    <script type="module">
      import confetti from "https://esm.sh/[email protected]"
      globalThis.x = await(new Promise((resolve) => setTimeout(resolve, 500)));
      console.log('hello')
      globalThis.JSConfetti = confetti;
    </script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/scittle.js" type="application/javascript"></script>
    <script type="application/x-scittle">
      (js/console.log js/x)
      (js/JSConfetti)
    </script>
  </head>
  <body>
  </body>
</html>

@chr15m
Copy link
Contributor Author

chr15m commented Aug 21, 2025

Ah ok so it would only work for non-modules scripts.

Maybe we could add something like scittle.js?wait-for-modules which would await for all module script tags on the page before running the Scittle boot up?

@chr15m
Copy link
Contributor Author

chr15m commented Aug 21, 2025

Although I don't think onload would wait for the setTimeout await. 🤔

@borkdude
Copy link
Collaborator

I think this should be the solution with async modules:

<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/scittle.js" type="application/javascript"></script>
    <script>scittle.core.disable_auto_eval()</script>
    <script type="module">
      import confetti from "https://esm.sh/[email protected]"
      globalThis.x = await(new Promise((resolve) => setTimeout(resolve, 500)));
      console.log('hello')
      globalThis.JSConfetti = confetti;
      scittle.core.eval_script_tags();
    </script>
    <script type="application/x-scittle">
      (js/console.log js/x)
      (js/JSConfetti)
    </script>
  </head>
  <body>
  </body>
</html>

@borkdude
Copy link
Collaborator

and this would work perfectly with your solution as well

@borkdude borkdude merged commit 7aebb5b into babashka:main Aug 21, 2025
@borkdude
Copy link
Collaborator

Exciting!

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.

Ability to map require's to loaded JS deps

2 participants