mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-23 18:13:54 +03:00
108 lines
3.4 KiB
JavaScript
108 lines
3.4 KiB
JavaScript
//
|
|
// FunctionPromise: possibly-asynchronous function constructor.
|
|
//
|
|
// This is a prototype polyfill for a FunctionPromise object as described in:
|
|
//
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=854627
|
|
//
|
|
// Where possible it will arrange for the function body to be parsed/compiled
|
|
// off of the main thread, with the function object returned asynchronously
|
|
// via a promise. The fallback implementation processes just falls back to
|
|
// the standard synchronous Function() constructor.
|
|
//
|
|
// It doesn't (yet) have the following features from the linked proposal:
|
|
//
|
|
// * ability to copy to different workers
|
|
// * ability to store in IndexedDB
|
|
//
|
|
function FunctionPromise(/* [args1[, args2[, ...argN]],], functionBody) */) {
|
|
|
|
var useFallback =
|
|
typeof window === "undefined" ||
|
|
window.FunctionPromise !== FunctionPromise ||
|
|
typeof document === "undefined" ||
|
|
typeof document.createElement === "undefined" ||
|
|
typeof document.head === "undefined" ||
|
|
typeof document.head.appendChild === "undefined" ||
|
|
typeof Blob === "undefined" ||
|
|
typeof URL === "undefined" ||
|
|
typeof URL.createObjectURL === "undefined";
|
|
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
|
// For the fallback case, we just use the normal Function constructor.
|
|
|
|
if (useFallback) {
|
|
try {
|
|
var fn = Function.apply(null, args);
|
|
return Promise.resolve(fn);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
}
|
|
|
|
// If we have all the necessary pieces, we can do this asynchronously
|
|
// by writing a <script> tag into the DOM.
|
|
|
|
var funcid = FunctionPromise._nextid++;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
try {
|
|
var funcSrc = [];
|
|
funcSrc.push("window.FunctionPromise._results[" + funcid + "]=");
|
|
funcSrc.push("function(");
|
|
if (args.length > 1) {
|
|
funcSrc.push(args[0]);
|
|
for (var i = 1; i < args.length - 1; i++) {
|
|
funcSrc.push(",");
|
|
funcSrc.push(args[i]);
|
|
}
|
|
}
|
|
funcSrc.push("){");
|
|
funcSrc.push(args[args.length - 1]);
|
|
funcSrc.push("}");
|
|
var dataUrl = URL.createObjectURL(new Blob(funcSrc));
|
|
var scriptTag = document.createElement("script");
|
|
var cleanup = function() {
|
|
URL.revokeObjectURL(dataUrl);
|
|
scriptTag.remove();
|
|
delete window.FunctionPromise._results[funcid];
|
|
}
|
|
scriptTag.onerror = function() {
|
|
reject(new Error("unknown error loading FunctionPromise"))
|
|
cleanup();
|
|
}
|
|
scriptTag.onload = function() {
|
|
if (window.FunctionPromise._results[funcid]) {
|
|
resolve(window.FunctionPromise._results[funcid]);
|
|
} else {
|
|
// No function, something must have gone wrong.
|
|
// Likely a syntax error in the function body string.
|
|
// Fall back to Function() constructor to surface it.
|
|
try {
|
|
Function.apply(null, args);
|
|
reject(new Error("unknown error fulfilling FunctionPromise"));
|
|
} catch (err) {
|
|
reject(err);
|
|
}
|
|
}
|
|
cleanup();
|
|
}
|
|
scriptTag.src = dataUrl;
|
|
document.head.appendChild(scriptTag);
|
|
} catch (err) {
|
|
reject(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
FunctionPromise._nextid = 0;
|
|
FunctionPromise._results = {};
|
|
|
|
if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
|
|
if (typeof Promise === "undefined") {
|
|
Promise = require('es6-promise').Promise;
|
|
}
|
|
module.exports = FunctionPromise;
|
|
}
|