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

Adding new require calls won't work #1

Closed
caspervonb opened this issue Aug 26, 2015 · 6 comments
Closed

Adding new require calls won't work #1

caspervonb opened this issue Aug 26, 2015 · 6 comments

Comments

@caspervonb
Copy link
Owner

Details to come.

@caspervonb
Copy link
Owner Author

This is all about the prelude, it was never built for this kind of hackery.

  • Module ids are integers, which is fine except that they are integers that change meaning between builds. Your entry point module might start out as module 1, and end up being module 9.
    We can fix this by using --full-paths, which gives us a stable identifier.
  • Module definitions need to appear in the body of a function, this is currently done by hacking the prelude, turning the modules parameter into a function, but we're better off just moving it into
  • Module 'name' require map needs to be kept live.
  • The order which modules appear is not optimal, setScriptSource can get confused if the entire script is drastically changed. To eliminate the risk of this happening, cache the order, and sort depending on that.

So, accounting for all that, we'll end up with a prelude template that looks something like the following

(function(cache, entries) {
  function require(name) {
    if (cache[name]) {
      return cache[name].exports;
    }

    var modules = <%= modules %>

    if(!modules[name]) {
      var error = new Error('Cannot find module \'' + name + '\'');
      throw error;
    }

    function resolve(name) {
      return <%= resolves %>[name];
    }

    var module = {
      locals: {},
      exports: {},
      identities: {},
      exec: function(id, fn) {
        if (!module.identities[id]) {
          module.identities[id] = fn;
          fn();
        }
      },
    };

    cache[name] = module;

    var fn = modules[name].bind(module.exports, function(key) {
      var identifiers = resolve(name);
      if (identifiers && identifiers[key]) {
        return require(identifiers[key]);
      }

      return require(key);
    }, module, module.exports);

    fn();

    var source = modules[name].toString();
    addEventListener('patch', function() {
      if (source !== modules[name].toString()) {
        fn();
      }

      source = modules[name].toString();
    });
  }

  entries.forEach(require);
  return require;
}(%= arguments %));

@caspervonb
Copy link
Owner Author

Fixed in 209c550

@caspervonb
Copy link
Owner Author

Reopening this, while new requires do work with the previously mentioned commit, they can break on huge modules.

@caspervonb caspervonb reopened this Aug 27, 2015
@caspervonb
Copy link
Owner Author

Minimal reproducible example, with the transform and eval functionality disabled.

setInterval(function() {
  // var lib = require('util');
  console.log(typeof lib);
});

Uncommenting that require will cause a detached state. However if the module is a small module without many dependencies being pulled in, it is fine.

@caspervonb
Copy link
Owner Author

So it seems this is not a problem inherent to the prelude. Also callbacks are the only things that are breaking, so its not straight out failing its just failing to keep the binding. In #2 the cause appeared to be that the closure was changing I can't see that being the case here.

Now, adding a big chunk of things in another scope, does not appear to break anything, same goes for removing.

@caspervonb
Copy link
Owner Author

Breakthrough, the following form seems to to work, in the case case i was adding 30k lines of extra modules.

var modules = {};

function require(id) {
  apply(modules);
  return modules[id]();
}

function apply(modules) {
  if (!modules['a']) {
    (function() {
      modules['a'] = function() {
        setInterval(function() {
          document.body.innerHTML = 'Are we live?';
        }, 500);
      };
    }());
  }
}

require('a');

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

1 participant