golike-defer
Version:
go's defer statement in JavaScript
184 lines (147 loc) • 4.07 kB
JavaScript
exports.__esModule = true;
exports.default = exports.defer = void 0;
var push = Array.prototype.push;
var toDecorator = function toDecorator(wrap) {
return function (target, key, descriptor) {
if (key === undefined) {
return wrap(target);
}
descriptor.value = wrap(descriptor.value);
return descriptor;
};
};
var setFnNameAndLength = function () {
var _defineProperties = Object.defineProperties;
try {
var f = _defineProperties(function () {}, {
length: {
value: 2
},
name: {
value: "foo"
}
});
if (f.length === 2 && f.name === "foo") {
return function (fn, name, length) {
return _defineProperties(fn, {
length: {
configurable: true,
value: length > 0 ? length : 0
},
name: {
configurable: true,
value: name
}
});
};
}
} catch (_) {}
return function (f) {
return f;
};
}();
var defaultOnError = function defaultOnError(error) {
console.error(error);
};
var SUCCESS = 1 << 0;
var FAILURE = 1 << 1;
function Deferred(fn, thisArg, args, when) {
this.args = args;
this.fn = fn;
this.thisArg = thisArg;
this.when = when;
}
Deferred.prototype.run = function (when) {
if ((when & this.when) !== 0) {
return this.fn.apply(this.thisArg, this.args);
}
};
function defer(fn, onError) {
if (onError === void 0) {
onError = defaultOnError;
}
var wrapper = function wrapper() {
var deferreds = [];
var makeAddDeferred = function makeAddDeferred(when) {
return function $defer(deferred) {
var args;
if (typeof deferred !== "function") {
deferred = this[deferred];
}
var nArgs = arguments.length - 1;
if (nArgs !== 0) {
args = new Array(nArgs);
for (var _i = 0; _i < nArgs; ++_i) {
args[_i] = arguments[_i + 1];
}
}
deferreds.push(new Deferred(deferred, this, args, when));
};
};
var $defer = makeAddDeferred(FAILURE | SUCCESS);
$defer.onFailure = makeAddDeferred(FAILURE);
$defer.onSuccess = makeAddDeferred(SUCCESS);
var args = [$defer];
push.apply(args, arguments);
var hasThrown, result;
try {
result = fn.apply(this, args);
var then;
if (result != null && typeof (then = result.then) === "function") {
var executeAndForward = function executeAndForward(when) {
var i = deferreds.length;
var loop = function loop() {
if (i === 0) {
return result;
}
try {
var _result = deferreds[--i].run(when);
var _then;
return _result != null && typeof (_then = _result.then) === "function" ? _then.call(_result, loop, reportAndLoop) : loop();
} catch (error) {
return reportAndLoop(error);
}
};
var reportAndLoop = function reportAndLoop(error) {
onError(error);
return loop();
};
return loop();
};
return then.call(result, function () {
return executeAndForward(SUCCESS);
}, function () {
return executeAndForward(FAILURE);
});
}
hasThrown = false;
} catch (error) {
result = error;
hasThrown = true;
}
var when = hasThrown ? FAILURE : SUCCESS;
var i = deferreds.length;
while (i > 0) {
try {
deferreds[--i].run(when);
} catch (error) {
onError(error);
}
}
if (hasThrown) {
throw result;
}
return result;
};
var length = fn.length;
return setFnNameAndLength(wrapper, `defer(${fn.name})`, length > 0 ? length - 1 : length);
}
var decorator = toDecorator(defer);
exports.default = exports.defer = decorator;
decorator.onError = function (cb) {
return toDecorator(function (fn) {
return defer(fn, cb);
});
};
//# sourceMappingURL=index.js.map
;