caspervonb / amokify

Other
25 stars 2 forks source link

Adding new require calls won't work #1

Closed caspervonb closed 9 years ago

caspervonb commented 9 years ago

Details to come.

caspervonb commented 9 years ago

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

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 commented 9 years ago

Fixed in 209c550c72b2c02c7d38bb8dca22ee97b814461c

caspervonb commented 9 years ago

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

caspervonb commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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');