Skip to content
This repository has been archived by the owner on May 12, 2020. It is now read-only.

[idea] how to require files from within scripts #50

Open
eridal opened this issue Nov 27, 2016 · 1 comment
Open

[idea] how to require files from within scripts #50

eridal opened this issue Nov 27, 2016 · 1 comment

Comments

@eridal
Copy link
Contributor

eridal commented Nov 27, 2016

Allow to require files

This is an idea to allow requirejs' style to include files from the scripts. Currently we only have the default.js and it's getting cluttered for me, so thought about how to make this feature possible.

Interaction

The basic idea is that main.js will inject bridge.js, which will expose the require function to the browser in order to communicate with the nodejs environment.

The main.js will match the files and include them. When these call require, the bridge will emit an event, main.js will require the files and emit the results back to the bridge, which will notify the scripts.

  ┌────────┐      ┌─────────┐                 ┌───────────┐                  ┌────────────────┐
  │ nodejs │      │ main.js │                 │ bridge.js │                  │ example.com.js │
  └────────┘      └─────────┘                 └───────────┘                  └────────────────┘
      │                 │                             │                                │
      │                 ╞════ injects ═══════════════>╞═══╗ declares require shim      │
      │                 │                             │<══╝                            │
      │                 │                             │                                │
      │                 ╞═════ matchFile ═════════════════════════════════════════════>│
      │                 │                             │                                │
      │                 │                             │       require(files, fn)       │
      │                 │               emit(req) ╔═══╡<═══════════════════════════════╡
      │                 │                         ╚══>│                                │
      │                 │                             │                                │
      │                 │<-- on('req') ---------------│                                │
      │ require(files)  │                             │                                │
    ╔═╡<════════════════╡                             │                                │
    ╚═╪════════════════>│ emit(res)                   │                                │
      │                 │                             │                                │
      │                 │--------------- on('res') -->│                                │
      │                 │                             │                                │
      │                 │                             ╞═════════════ fn(err, result) ═>│

      legend:
        --> sync
        ══> async 

Implementation

Please note that this is more like a draft of the idea, than an actual implementation. I have not run the code and it may contain subtle bugs :)

1. main.js

Here we are at nodejs.

We need to add the listener for the bridge, in which we will require the files and send the back. Other than that, the file wont need any other modification.

worker.port.on('.js:require-req', function (req) {
  try {
    worker.port.emit('.js:require-ret', {
      id: req.id,
      result: deps.map(function (dep) {
        return require(dep)
      }),
    })
  } catch (err) {
    worker.port.emit('.js:require-err', {
      id: req.id,
      error : err,
    })
  }
});

worker.port.on('init', function (domain) {
  // 1. inject the 
  worker.port.emit('load-scripts', 'bridge.js');
  // 2. match + emit load-scripts as usual
  // ...
})

2. bridge.js

We are at browser-side, so we declare the window.require shim and declare the hooks required for IPC

var queue = []
var next = 0

window.require = function (deps, done) {

  if (++next === Number.MAX_SAFE_INTEGER) {
    next = 0
  }

  queue[next] = done

  self.port.emit('.js:require-req', { 
    id: next, 
    deps: deps 
  });
}

self.port.on('.js:require-err', function (res) {
  queue[res.id](res.error)
})

self.port.on('.js:require-res', function (res) {
  queue[res.id].call(null, [null].concat(res.result))
})

3. script

This could be an example of a script, that make usage of the require shim.

require([
  'foo',
  'bar/baz',
], function (err, foo, baz) {

  if (err) {
    console.log('boo', err.message)
  }

  console.log('foo', foo)
  console.log('baz', baz)
})
@rlr
Copy link
Owner

rlr commented Dec 16, 2016

that's super cool! I'm game for that...

However, I'm pretty sure this whole addon needs to be reimplemented somehow using WebExtensions since the addon sdk and this style of addons will stop working soonish (I think it's Firefox 57?). So, I'll need to look into that and see if it's even possible.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants