Source: worker.js

"use strict";

/** @file Parallel JavaScript execution to control infinite loops, patterned after the
    <a href='https://github.com/mdn/simple-web-worker'>basic dedicated worker example</a>.
    @author Axel T. Schreiner <ats@cs.rit.edu>
    @version 2.1
*/

/** Contains (and tries to protect) global functions which the message handler uses.
    Note that <code>self</code> is the global scope of the <code>DedicatedWorker</code>
    — and, unfortunately, of all boxes.
    @type {Object}
    @property {function(string)} eval - evaluates a code string in the global scope.
    @property {function(object, ...string)} load - needs to be curried.
    @property {function(...string)} log - writes a message to the JavaScript console.
    @property {function(function)} map - applies a function to an array.
    @property {function(string[])} postMessage - sends a (reply) message.
    @property {function(function, null)} reduce - applies a function to an array and returns the last result.
    @property {function(object)} String - converts to a string.
*/
const NB = {
  eval: self.eval.bind(self),
  load: (files, ...ids) => {
      if (files && ids.length)
        return NB.reduce.call(ids, (_, id) => {
          if (id in files)
            try {
              NB.log('load: ' + files[id]);
              return NB.eval(files[id]);
            } catch (e) {
              throw id + ': ' + NB.String(e);
            }
          else
            throw id + ': not found';
        }, null);
    },
  log: self.console.log.bind(self.console),
  map: self.Array.prototype.map,
  postMessage: self.postMessage.bind(self),
  reduce: self.Array.prototype.reduce,
  String: self.String
};

/** Function to print one line.
    @param {string} [vals] - string(s) to be printed joined by single blanks.
*/
function print (...vals) { NB.postMessage(['print', NB.map.call(vals, val => NB.String(val))]); }

/** Function to evaluate source code in file boxes.
    @param {string} [ids] - name(s) of file boxes to load.
    @returns result of last evaluation if any, else <code>undefined</code>.
    @throws {string} error if any, terminates execution.
*/
function load (...ids) {}

/** Evaluates a code cell.
    @param {Event} _event contains an array with a code string and an optional hash of keys to
      code strings which can be loaded.
*/
onmessage = function (_event) {
  // add file information to load function
  self.load = NB.load.bind(null, _event.data.length > 1 && _event.data[1] ?  _event.data[1] : null);
    
  // evaluate
  try {
    let result;
    try {
      NB.log('eval: ' + _event.data[0]);
      result = NB.eval(_event.data[0]);
    } catch (e) {
      throw typeof e == 'string' ? e : 'run: ' + NB.String(e);
    }
    if (typeof result == 'undefined')
      NB.postMessage(['exit']);
    else
      NB.postMessage(['exit', NB.String(result)]);
  } catch (e) {
    NB.postMessage(['error', e]);
  }
};