fvtt-lib-wrapper icon indicating copy to clipboard operation
fvtt-lib-wrapper copied to clipboard

Add support for wrapping generators

Open ruipin opened this issue 3 years ago • 0 comments

Because generator functions are synctactic sugar around a Generator factory, trying to wrap a generator the naive way will trigger a libWrapper exception:

game.generatorFn = function*(...args) {
  yield args[0];
  yield args[1];
  yield args[2];
};

libWrapper.register('package_id', 'game.generatorFn',  function*(wrapped, ...args) {
  const gen = wrapped(...args);
  yield gen.next().value+1;
  yield gen.next().value+1;
  yield gen.next().value+1;
}, "WRAPPER");

console.log(game.generatorFn(1).next());
// <- The wrapper for 'game.generatorFn' registered by module 'package_id' with type WRAPPER did not chain the call to the next wrapper, which breaks a libWrapper API requirement. This wrapper will be unregistered.

A workaround is to divide the wrapper into two parts, a factory, and a generator:

game.generatorFn = function*(...args) {
  yield args[0];
  yield args[1];
  yield args[2];
};

function* generatorFn_wrapped(wrapped, ...args) {
  yield wrapped.next().value+1;
  yield wrapped.next().value+1;
  yield wrapped.next().value+1;
}

libWrapper.register('package_id', 'game.generatorFn',  function(wrapped, ...args) {
  return generatorFn_wrapped(wrapped(...args), ...args);
}, "WRAPPER");

console.log(game.generatorFn(1,2,3).next().value);
// <- 2

It might be a good idea to have libWrapper do this automatically when it detects the wrapper function is a generator. When libWrapper.register detects that the wrapper function is a generator, it should automatically create a corresponding factory, and register that instead, similar to above.

To detect whether a function is a generator, the following StackOverflow thread is useful: https://stackoverflow.com/questions/21559365/how-to-identify-an-es6-generator

ruipin avatar Jul 23 '21 20:07 ruipin