npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

gxjs-loader

v0.0.4

Published

(G)erbil E(x)tended (J)avaScript (S)cheme Loader

Downloads

1

Readme

GxJS Loader: Load Scheme files into JavaScript

GxJS Loader is used to take either source code written in Gerbil Gambit or Gambit Scheme scheme and transpile them to JavaScript.

Installation

Easy! I choose yarn, but npm also works.

yarn add gxjs-loader --dev

Usage

Gerbil

To start with here’s a Gerbil file (.ss) that mixes JavaScript code with Gerbil code.

(import :js)

(js#declaration "console.log('started GxJS loader!')")

(def property-name "This is valid")

(def GxJS-jso
  {
    thisIsTheAnswer: 42
    'this "is how we make the moonshine"
    property-name 'symbols-have-no-js-value!
  })


(def (this-is-gxjs! (val 42))
  (js#statement "console.log('This is GxJS!', (@1@), (@2@), (@3@))"
                val
                (js#foreign->js GxJS-jso)
                (js#scm->js (string-append "string " "append"))))

(js#statement "console.log('finished GxJS loader');
 module.exports = RTS.scm2host(@1@);" this-is-gxjs!)

Now a JavaScript file that requires what we export, calls what we export, and exports what we export.

const GxJS = require('gxjs-loader!./gxjs-loader-usage.ss')

GxJS('yay!');

module.exports = GxJS;

When run at the shell after compilation with node -e that outputs:

started GxJS loader!
finished GxJS loader
This is GxJS! { codes: [ 121, 97, 121, 33 ] } {
  thisIsTheAnswer: 42,
  this: 'is how we hake the moonshine',
  'This is valid': {
    name: 'symbols-have-no-js-value!',
    hash: 386716666,
    interned: true
  }
} string append

Note that the RTS took our 'yay!' JavaScript string and turned it into a scheme string when calling the function.

Gambit

Gerbil itself transpiles its Meta-Scheme dialect to Gambit scheme. If we want to compile a Gambit scheme file without calling gxc, the gerbil compiler, we can do so.

(declare (extended-bindings))

(##inline-host-declaration "console.log('Started Gambit-only GxJS loader!')")

(define property-name "This is valid")

(define GxJS-vector
  (##vector
   property-name 42
   'this "is how we hake the moonshine"))


(define (this-is-gambit-gxjs! #!optional (val 42))
  (##inline-host-statement "console.log('This is GxJS!', (@1@), (@2@))"
               val GxJS-vector))

(##inline-host-statement "console.log('finished Gambit-only GxJS loader');
 module.exports = RTS.scm2host(@1@);" this-is-gambit-gxjs!)

Now a JavaScript file that requires what we export, calls what we export, and exports what we export.

const gambitGxJS = require('gxjs-loader!./gxjs-loader-usage.scm')

gambitGxJS('gambitYay!');

module.exports = gambitGxJS;

cd ../gxjs-loader/ && yarn run webpack && du -h dist/* && cd - ; echo "TESTING"; echo; cd ../gxjs-tests/; yarn run webpack ; node -e "require ('./dist/main.js')"

Options: Make the JS code differ

By default the loader just loads the scheme file, using Gerbil then Gambit to compile it first, into the gxjs runtime system.

It does so by adding const RTS = require('gxjs') to the top, then wrapping the output from the compiler in an ArrowFunctionExpression that it calls.

If the extenstion is .scm we do not call Gerbil at all, by default.

But that can be changed. Mostly for developing the runtimes things need changing around. Here are the options.

  • -link: If this is passed and not false make a link file that has the RTS definition and do not require any RTS’s.

  • return: When this is passed a symbol name then the very end of the code has a return statement for that symbol. i.e. gxjs-loader?-linkreturn=RTS adds that.

  • call: All the generated code is wrapped in an ArrowFunctionExpression, mostly to isolate it and deal with scope. If we want to call that function, which be default we do, call contains the arguments we wish to call it with. Default: [].

    If false we do not call the generated function.

  • exports: Do we want to place a module.exports = before the function or function call expression? If this is passed and not false, yes, yes we do. i.e. 'gxjs-loader?-link&return=RTS&exports!./gxjs-link-loader-runtime.ss'

  • args: This is an array of parameters to declare the ArrowFunction with. By default [] of course.

  • RTS: If is is a string that becomes the argument that we require for const RTS to become the runtime system. If it’s false there is no RTS required.

    i.e. 'gxjs-loader?args=["RTS"]&RTS=false&call=false&exports!./gxjs-link-loader-runtime.ss' or 'gxjs-loader?RTS=./gxjs-link-loader.js!./gxjs-link-use-runtime.ss'

-link to create and embed a runtime system.

Most of the time there is a const RTS = require('gxjs') inserted in the file.

But sometimes, like, so far, the one time I needed to create the runtime contained in 'gxjs', we actually want the compiler to create one for us.

Let’s create the runtime we want, which is the smallest. Essentially all it does is change the upstream (Gambit v4.9.3) module initialization to one that always runs.

(import :js)

(js#statement #<<EOF
RTS.module_register = function(module_descr) {
  const r = this;
  r.sp = -1;
  r.stack[++this.sp] = void 0;
  r.r0 = this.underflow;
  r.nargs = 0;
  r.trampoline(module_descr[4]);
};

EOF
)

And now the js to use it.

const RTS = require('gxjs-loader?-link&return=RTS&exports!./gxjs-link-loader-runtime.ss');
const extraRunTime = require('gxjs-loader?args=["RTS"]&RTS=false&call=false&exports!./gxjs-link-loader-runtime.ss');

extraRunTime(RTS);
console.log('New RTS:', RTS.glo, extraRunTime)

module.exports = RTS;

Now we can use that RTS elsewhere

(import :js)
(js#declaration "console.log('Using another RTS,', RTS.glo)")
(js#statement "module.exports = 42")

const answer = require('gxjs-loader?RTS=./gxjs-link-loader.js!./gxjs-link-use-runtime.ss')

module.exports = answer;

Support

Go to https://github.com/drewc/gxjs/issues or contact the author.