NuclearDispersionSystem/ant-design-vue-jeecg/node_modules/single-spa/lib/system/single-spa.dev.js

1775 lines
67 KiB
JavaScript
Raw Normal View History

2023-09-14 14:47:11 +08:00
/* single-spa@5.9.4 - SystemJS - dev */
System.register([], function (exports) {
'use strict';
return {
execute: function () {
exports({
addErrorHandler: addErrorHandler,
checkActivityFunctions: checkActivityFunctions,
ensureJQuerySupport: ensureJQuerySupport,
getAppNames: getAppNames,
getAppStatus: getAppStatus,
getMountedApps: getMountedApps,
mountRootParcel: mountRootParcel,
navigateToUrl: navigateToUrl,
pathToActiveWhen: pathToActiveWhen,
registerApplication: registerApplication,
removeErrorHandler: removeErrorHandler,
setBootstrapMaxTime: setBootstrapMaxTime,
setMountMaxTime: setMountMaxTime,
setUnloadMaxTime: setUnloadMaxTime,
setUnmountMaxTime: setUnmountMaxTime,
start: start,
triggerAppChange: triggerAppChange,
unloadApplication: unloadApplication,
unregisterApplication: unregisterApplication
});
var singleSpa = /*#__PURE__*/Object.freeze({
__proto__: null,
get start () { return start; },
get ensureJQuerySupport () { return ensureJQuerySupport; },
get setBootstrapMaxTime () { return setBootstrapMaxTime; },
get setMountMaxTime () { return setMountMaxTime; },
get setUnmountMaxTime () { return setUnmountMaxTime; },
get setUnloadMaxTime () { return setUnloadMaxTime; },
get registerApplication () { return registerApplication; },
get unregisterApplication () { return unregisterApplication; },
get getMountedApps () { return getMountedApps; },
get getAppStatus () { return getAppStatus; },
get unloadApplication () { return unloadApplication; },
get checkActivityFunctions () { return checkActivityFunctions; },
get getAppNames () { return getAppNames; },
get pathToActiveWhen () { return pathToActiveWhen; },
get navigateToUrl () { return navigateToUrl; },
get triggerAppChange () { return triggerAppChange; },
get addErrorHandler () { return addErrorHandler; },
get removeErrorHandler () { return removeErrorHandler; },
get mountRootParcel () { return mountRootParcel; },
get NOT_LOADED () { return NOT_LOADED; },
get LOADING_SOURCE_CODE () { return LOADING_SOURCE_CODE; },
get NOT_BOOTSTRAPPED () { return NOT_BOOTSTRAPPED; },
get BOOTSTRAPPING () { return BOOTSTRAPPING; },
get NOT_MOUNTED () { return NOT_MOUNTED; },
get MOUNTING () { return MOUNTING; },
get UPDATING () { return UPDATING; },
get LOAD_ERROR () { return LOAD_ERROR; },
get MOUNTED () { return MOUNTED; },
get UNMOUNTING () { return UNMOUNTING; },
get SKIP_BECAUSE_BROKEN () { return SKIP_BECAUSE_BROKEN; }
});
function _typeof(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof(obj);
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
var NativeCustomEvent = commonjsGlobal.CustomEvent;
function useNative () {
try {
var p = new NativeCustomEvent('cat', { detail: { foo: 'bar' } });
return 'cat' === p.type && 'bar' === p.detail.foo;
} catch (e) {
}
return false;
}
/**
* Cross-browser `CustomEvent` constructor.
*
* https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent.CustomEvent
*
* @public
*/
var customEvent = useNative() ? NativeCustomEvent :
// IE >= 9
'undefined' !== typeof document && 'function' === typeof document.createEvent ? function CustomEvent (type, params) {
var e = document.createEvent('CustomEvent');
if (params) {
e.initCustomEvent(type, params.bubbles, params.cancelable, params.detail);
} else {
e.initCustomEvent(type, false, false, void 0);
}
return e;
} :
// IE <= 8
function CustomEvent (type, params) {
var e = document.createEventObject();
e.type = type;
if (params) {
e.bubbles = Boolean(params.bubbles);
e.cancelable = Boolean(params.cancelable);
e.detail = params.detail;
} else {
e.bubbles = false;
e.cancelable = false;
e.detail = void 0;
}
return e;
};
var errorHandlers = [];
function handleAppError(err, app, newStatus) {
var transformedErr = transformErr(err, app, newStatus);
if (errorHandlers.length) {
errorHandlers.forEach(function (handler) {
return handler(transformedErr);
});
} else {
setTimeout(function () {
throw transformedErr;
});
}
}
function addErrorHandler(handler) {
if (typeof handler !== "function") {
throw Error(formatErrorMessage(28, "a single-spa error handler must be a function"));
}
errorHandlers.push(handler);
}
function removeErrorHandler(handler) {
if (typeof handler !== "function") {
throw Error(formatErrorMessage(29, "a single-spa error handler must be a function"));
}
var removedSomething = false;
errorHandlers = errorHandlers.filter(function (h) {
var isHandler = h === handler;
removedSomething = removedSomething || isHandler;
return !isHandler;
});
return removedSomething;
}
function formatErrorMessage(code, msg) {
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
args[_key - 2] = arguments[_key];
}
return "single-spa minified message #".concat(code, ": ").concat(msg ? msg + " " : "", "See https://single-spa.js.org/error/?code=").concat(code).concat(args.length ? "&arg=".concat(args.join("&arg=")) : "");
}
function transformErr(ogErr, appOrParcel, newStatus) {
var errPrefix = "".concat(objectType(appOrParcel), " '").concat(toName(appOrParcel), "' died in status ").concat(appOrParcel.status, ": ");
var result;
if (ogErr instanceof Error) {
try {
ogErr.message = errPrefix + ogErr.message;
} catch (err) {
/* Some errors have read-only message properties, in which case there is nothing
* that we can do.
*/
}
result = ogErr;
} else {
console.warn(formatErrorMessage(30, "While ".concat(appOrParcel.status, ", '").concat(toName(appOrParcel), "' rejected its lifecycle function promise with a non-Error. This will cause stack traces to not be accurate."), appOrParcel.status, toName(appOrParcel)));
try {
result = Error(errPrefix + JSON.stringify(ogErr));
} catch (err) {
// If it's not an Error and you can't stringify it, then what else can you even do to it?
result = ogErr;
}
}
result.appOrParcelName = toName(appOrParcel); // We set the status after transforming the error so that the error message
// references the state the application was in before the status change.
appOrParcel.status = newStatus;
return result;
}
var NOT_LOADED = exports('NOT_LOADED', "NOT_LOADED");
var LOADING_SOURCE_CODE = exports('LOADING_SOURCE_CODE', "LOADING_SOURCE_CODE");
var NOT_BOOTSTRAPPED = exports('NOT_BOOTSTRAPPED', "NOT_BOOTSTRAPPED");
var BOOTSTRAPPING = exports('BOOTSTRAPPING', "BOOTSTRAPPING");
var NOT_MOUNTED = exports('NOT_MOUNTED', "NOT_MOUNTED");
var MOUNTING = exports('MOUNTING', "MOUNTING");
var MOUNTED = exports('MOUNTED', "MOUNTED");
var UPDATING = exports('UPDATING', "UPDATING");
var UNMOUNTING = exports('UNMOUNTING', "UNMOUNTING");
var UNLOADING = "UNLOADING";
var LOAD_ERROR = exports('LOAD_ERROR', "LOAD_ERROR");
var SKIP_BECAUSE_BROKEN = exports('SKIP_BECAUSE_BROKEN', "SKIP_BECAUSE_BROKEN");
function isActive(app) {
return app.status === MOUNTED;
}
function shouldBeActive(app) {
try {
return app.activeWhen(window.location);
} catch (err) {
handleAppError(err, app, SKIP_BECAUSE_BROKEN);
return false;
}
}
function toName(app) {
return app.name;
}
function isParcel(appOrParcel) {
return Boolean(appOrParcel.unmountThisParcel);
}
function objectType(appOrParcel) {
return isParcel(appOrParcel) ? "parcel" : "application";
}
// Object.assign() is not available in IE11. And the babel compiled output for object spread
// syntax checks a bunch of Symbol stuff and is almost a kb. So this function is the smaller replacement.
function assign() {
for (var i = arguments.length - 1; i > 0; i--) {
for (var key in arguments[i]) {
if (key === "__proto__") {
continue;
}
arguments[i - 1][key] = arguments[i][key];
}
}
return arguments[0];
}
/* the array.prototype.find polyfill on npmjs.com is ~20kb (not worth it)
* and lodash is ~200kb (not worth it)
*/
function find(arr, func) {
for (var i = 0; i < arr.length; i++) {
if (func(arr[i])) {
return arr[i];
}
}
return null;
}
function validLifecycleFn(fn) {
return fn && (typeof fn === "function" || isArrayOfFns(fn));
function isArrayOfFns(arr) {
return Array.isArray(arr) && !find(arr, function (item) {
return typeof item !== "function";
});
}
}
function flattenFnArray(appOrParcel, lifecycle) {
var fns = appOrParcel[lifecycle] || [];
fns = Array.isArray(fns) ? fns : [fns];
if (fns.length === 0) {
fns = [function () {
return Promise.resolve();
}];
}
var type = objectType(appOrParcel);
var name = toName(appOrParcel);
return function (props) {
return fns.reduce(function (resultPromise, fn, index) {
return resultPromise.then(function () {
var thisPromise = fn(props);
return smellsLikeAPromise(thisPromise) ? thisPromise : Promise.reject(formatErrorMessage(15, "Within ".concat(type, " ").concat(name, ", the lifecycle function ").concat(lifecycle, " at array index ").concat(index, " did not return a promise"), type, name, lifecycle, index));
});
}, Promise.resolve());
};
}
function smellsLikeAPromise(promise) {
return promise && typeof promise.then === "function" && typeof promise.catch === "function";
}
function toBootstrapPromise(appOrParcel, hardFail) {
return Promise.resolve().then(function () {
if (appOrParcel.status !== NOT_BOOTSTRAPPED) {
return appOrParcel;
}
appOrParcel.status = BOOTSTRAPPING;
if (!appOrParcel.bootstrap) {
// Default implementation of bootstrap
return Promise.resolve().then(successfulBootstrap);
}
return reasonableTime(appOrParcel, "bootstrap").then(successfulBootstrap).catch(function (err) {
if (hardFail) {
throw transformErr(err, appOrParcel, SKIP_BECAUSE_BROKEN);
} else {
handleAppError(err, appOrParcel, SKIP_BECAUSE_BROKEN);
return appOrParcel;
}
});
});
function successfulBootstrap() {
appOrParcel.status = NOT_MOUNTED;
return appOrParcel;
}
}
function toUnmountPromise(appOrParcel, hardFail) {
return Promise.resolve().then(function () {
if (appOrParcel.status !== MOUNTED) {
return appOrParcel;
}
appOrParcel.status = UNMOUNTING;
var unmountChildrenParcels = Object.keys(appOrParcel.parcels).map(function (parcelId) {
return appOrParcel.parcels[parcelId].unmountThisParcel();
});
return Promise.all(unmountChildrenParcels).then(unmountAppOrParcel, function (parcelError) {
// There is a parcel unmount error
return unmountAppOrParcel().then(function () {
// Unmounting the app/parcel succeeded, but unmounting its children parcels did not
var parentError = Error(parcelError.message);
if (hardFail) {
throw transformErr(parentError, appOrParcel, SKIP_BECAUSE_BROKEN);
} else {
handleAppError(parentError, appOrParcel, SKIP_BECAUSE_BROKEN);
}
});
}).then(function () {
return appOrParcel;
});
function unmountAppOrParcel() {
// We always try to unmount the appOrParcel, even if the children parcels failed to unmount.
return reasonableTime(appOrParcel, "unmount").then(function () {
// The appOrParcel needs to stay in a broken status if its children parcels fail to unmount
{
appOrParcel.status = NOT_MOUNTED;
}
}).catch(function (err) {
if (hardFail) {
throw transformErr(err, appOrParcel, SKIP_BECAUSE_BROKEN);
} else {
handleAppError(err, appOrParcel, SKIP_BECAUSE_BROKEN);
}
});
}
});
}
var beforeFirstMountFired = false;
var firstMountFired = false;
function toMountPromise(appOrParcel, hardFail) {
return Promise.resolve().then(function () {
if (appOrParcel.status !== NOT_MOUNTED) {
return appOrParcel;
}
if (!beforeFirstMountFired) {
window.dispatchEvent(new customEvent("single-spa:before-first-mount"));
beforeFirstMountFired = true;
}
return reasonableTime(appOrParcel, "mount").then(function () {
appOrParcel.status = MOUNTED;
if (!firstMountFired) {
window.dispatchEvent(new customEvent("single-spa:first-mount"));
firstMountFired = true;
}
return appOrParcel;
}).catch(function (err) {
// If we fail to mount the appOrParcel, we should attempt to unmount it before putting in SKIP_BECAUSE_BROKEN
// We temporarily put the appOrParcel into MOUNTED status so that toUnmountPromise actually attempts to unmount it
// instead of just doing a no-op.
appOrParcel.status = MOUNTED;
return toUnmountPromise(appOrParcel, true).then(setSkipBecauseBroken, setSkipBecauseBroken);
function setSkipBecauseBroken() {
if (!hardFail) {
handleAppError(err, appOrParcel, SKIP_BECAUSE_BROKEN);
return appOrParcel;
} else {
throw transformErr(err, appOrParcel, SKIP_BECAUSE_BROKEN);
}
}
});
});
}
function toUpdatePromise(parcel) {
return Promise.resolve().then(function () {
if (parcel.status !== MOUNTED) {
throw Error(formatErrorMessage(32, "Cannot update parcel '".concat(toName(parcel), "' because it is not mounted"), toName(parcel)));
}
parcel.status = UPDATING;
return reasonableTime(parcel, "update").then(function () {
parcel.status = MOUNTED;
return parcel;
}).catch(function (err) {
throw transformErr(err, parcel, SKIP_BECAUSE_BROKEN);
});
});
}
var parcelCount = 0;
var rootParcels = {
parcels: {}
}; // This is a public api, exported to users of single-spa
function mountRootParcel() {
return mountParcel.apply(rootParcels, arguments);
}
function mountParcel(config, customProps) {
var owningAppOrParcel = this; // Validate inputs
if (!config || _typeof(config) !== "object" && typeof config !== "function") {
throw Error(formatErrorMessage(2, "Cannot mount parcel without a config object or config loading function"));
}
if (config.name && typeof config.name !== "string") {
throw Error(formatErrorMessage(3, "Parcel name must be a string, if provided. Was given ".concat(_typeof(config.name)), _typeof(config.name)));
}
if (_typeof(customProps) !== "object") {
throw Error(formatErrorMessage(4, "Parcel ".concat(name, " has invalid customProps -- must be an object but was given ").concat(_typeof(customProps)), name, _typeof(customProps)));
}
if (!customProps.domElement) {
throw Error(formatErrorMessage(5, "Parcel ".concat(name, " cannot be mounted without a domElement provided as a prop"), name));
}
var id = parcelCount++;
var passedConfigLoadingFunction = typeof config === "function";
var configLoadingFunction = passedConfigLoadingFunction ? config : function () {
return Promise.resolve(config);
}; // Internal representation
var parcel = {
id: id,
parcels: {},
status: passedConfigLoadingFunction ? LOADING_SOURCE_CODE : NOT_BOOTSTRAPPED,
customProps: customProps,
parentName: toName(owningAppOrParcel),
unmountThisParcel: function unmountThisParcel() {
return mountPromise.then(function () {
if (parcel.status !== MOUNTED) {
throw Error(formatErrorMessage(6, "Cannot unmount parcel '".concat(name, "' -- it is in a ").concat(parcel.status, " status"), name, parcel.status));
}
return toUnmountPromise(parcel, true);
}).then(function (value) {
if (parcel.parentName) {
delete owningAppOrParcel.parcels[parcel.id];
}
return value;
}).then(function (value) {
resolveUnmount(value);
return value;
}).catch(function (err) {
parcel.status = SKIP_BECAUSE_BROKEN;
rejectUnmount(err);
throw err;
});
}
}; // We return an external representation
var externalRepresentation; // Add to owning app or parcel
owningAppOrParcel.parcels[id] = parcel;
var loadPromise = configLoadingFunction();
if (!loadPromise || typeof loadPromise.then !== "function") {
throw Error(formatErrorMessage(7, "When mounting a parcel, the config loading function must return a promise that resolves with the parcel config"));
}
loadPromise = loadPromise.then(function (config) {
if (!config) {
throw Error(formatErrorMessage(8, "When mounting a parcel, the config loading function returned a promise that did not resolve with a parcel config"));
}
var name = config.name || "parcel-".concat(id);
if ( // ES Module objects don't have the object prototype
Object.prototype.hasOwnProperty.call(config, "bootstrap") && !validLifecycleFn(config.bootstrap)) {
throw Error(formatErrorMessage(9, "Parcel ".concat(name, " provided an invalid bootstrap function"), name));
}
if (!validLifecycleFn(config.mount)) {
throw Error(formatErrorMessage(10, "Parcel ".concat(name, " must have a valid mount function"), name));
}
if (!validLifecycleFn(config.unmount)) {
throw Error(formatErrorMessage(11, "Parcel ".concat(name, " must have a valid unmount function"), name));
}
if (config.update && !validLifecycleFn(config.update)) {
throw Error(formatErrorMessage(12, "Parcel ".concat(name, " provided an invalid update function"), name));
}
var bootstrap = flattenFnArray(config, "bootstrap");
var mount = flattenFnArray(config, "mount");
var unmount = flattenFnArray(config, "unmount");
parcel.status = NOT_BOOTSTRAPPED;
parcel.name = name;
parcel.bootstrap = bootstrap;
parcel.mount = mount;
parcel.unmount = unmount;
parcel.timeouts = ensureValidAppTimeouts(config.timeouts);
if (config.update) {
parcel.update = flattenFnArray(config, "update");
externalRepresentation.update = function (customProps) {
parcel.customProps = customProps;
return promiseWithoutReturnValue(toUpdatePromise(parcel));
};
}
}); // Start bootstrapping and mounting
// The .then() causes the work to be put on the event loop instead of happening immediately
var bootstrapPromise = loadPromise.then(function () {
return toBootstrapPromise(parcel, true);
});
var mountPromise = bootstrapPromise.then(function () {
return toMountPromise(parcel, true);
});
var resolveUnmount, rejectUnmount;
var unmountPromise = new Promise(function (resolve, reject) {
resolveUnmount = resolve;
rejectUnmount = reject;
});
externalRepresentation = {
mount: function mount() {
return promiseWithoutReturnValue(Promise.resolve().then(function () {
if (parcel.status !== NOT_MOUNTED) {
throw Error(formatErrorMessage(13, "Cannot mount parcel '".concat(name, "' -- it is in a ").concat(parcel.status, " status"), name, parcel.status));
} // Add to owning app or parcel
owningAppOrParcel.parcels[id] = parcel;
return toMountPromise(parcel);
}));
},
unmount: function unmount() {
return promiseWithoutReturnValue(parcel.unmountThisParcel());
},
getStatus: function getStatus() {
return parcel.status;
},
loadPromise: promiseWithoutReturnValue(loadPromise),
bootstrapPromise: promiseWithoutReturnValue(bootstrapPromise),
mountPromise: promiseWithoutReturnValue(mountPromise),
unmountPromise: promiseWithoutReturnValue(unmountPromise)
};
return externalRepresentation;
}
function promiseWithoutReturnValue(promise) {
return promise.then(function () {
return null;
});
}
function getProps(appOrParcel) {
var name = toName(appOrParcel);
var customProps = typeof appOrParcel.customProps === "function" ? appOrParcel.customProps(name, window.location) : appOrParcel.customProps;
if (_typeof(customProps) !== "object" || customProps === null || Array.isArray(customProps)) {
customProps = {};
console.warn(formatErrorMessage(40, "single-spa: ".concat(name, "'s customProps function must return an object. Received ").concat(customProps)), name, customProps);
}
var result = assign({}, customProps, {
name: name,
mountParcel: mountParcel.bind(appOrParcel),
singleSpa: singleSpa
});
if (isParcel(appOrParcel)) {
result.unmountSelf = appOrParcel.unmountThisParcel;
}
return result;
}
var defaultWarningMillis = 1000;
var globalTimeoutConfig = {
bootstrap: {
millis: 4000,
dieOnTimeout: false,
warningMillis: defaultWarningMillis
},
mount: {
millis: 3000,
dieOnTimeout: false,
warningMillis: defaultWarningMillis
},
unmount: {
millis: 3000,
dieOnTimeout: false,
warningMillis: defaultWarningMillis
},
unload: {
millis: 3000,
dieOnTimeout: false,
warningMillis: defaultWarningMillis
},
update: {
millis: 3000,
dieOnTimeout: false,
warningMillis: defaultWarningMillis
}
};
function setBootstrapMaxTime(time, dieOnTimeout, warningMillis) {
if (typeof time !== "number" || time <= 0) {
throw Error(formatErrorMessage(16, "bootstrap max time must be a positive integer number of milliseconds"));
}
globalTimeoutConfig.bootstrap = {
millis: time,
dieOnTimeout: dieOnTimeout,
warningMillis: warningMillis || defaultWarningMillis
};
}
function setMountMaxTime(time, dieOnTimeout, warningMillis) {
if (typeof time !== "number" || time <= 0) {
throw Error(formatErrorMessage(17, "mount max time must be a positive integer number of milliseconds"));
}
globalTimeoutConfig.mount = {
millis: time,
dieOnTimeout: dieOnTimeout,
warningMillis: warningMillis || defaultWarningMillis
};
}
function setUnmountMaxTime(time, dieOnTimeout, warningMillis) {
if (typeof time !== "number" || time <= 0) {
throw Error(formatErrorMessage(18, "unmount max time must be a positive integer number of milliseconds"));
}
globalTimeoutConfig.unmount = {
millis: time,
dieOnTimeout: dieOnTimeout,
warningMillis: warningMillis || defaultWarningMillis
};
}
function setUnloadMaxTime(time, dieOnTimeout, warningMillis) {
if (typeof time !== "number" || time <= 0) {
throw Error(formatErrorMessage(19, "unload max time must be a positive integer number of milliseconds"));
}
globalTimeoutConfig.unload = {
millis: time,
dieOnTimeout: dieOnTimeout,
warningMillis: warningMillis || defaultWarningMillis
};
}
function reasonableTime(appOrParcel, lifecycle) {
var timeoutConfig = appOrParcel.timeouts[lifecycle];
var warningPeriod = timeoutConfig.warningMillis;
var type = objectType(appOrParcel);
return new Promise(function (resolve, reject) {
var finished = false;
var errored = false;
appOrParcel[lifecycle](getProps(appOrParcel)).then(function (val) {
finished = true;
resolve(val);
}).catch(function (val) {
finished = true;
reject(val);
});
setTimeout(function () {
return maybeTimingOut(1);
}, warningPeriod);
setTimeout(function () {
return maybeTimingOut(true);
}, timeoutConfig.millis);
var errMsg = formatErrorMessage(31, "Lifecycle function ".concat(lifecycle, " for ").concat(type, " ").concat(toName(appOrParcel), " lifecycle did not resolve or reject for ").concat(timeoutConfig.millis, " ms."), lifecycle, type, toName(appOrParcel), timeoutConfig.millis);
function maybeTimingOut(shouldError) {
if (!finished) {
if (shouldError === true) {
errored = true;
if (timeoutConfig.dieOnTimeout) {
reject(Error(errMsg));
} else {
console.error(errMsg); //don't resolve or reject, we're waiting this one out
}
} else if (!errored) {
var numWarnings = shouldError;
var numMillis = numWarnings * warningPeriod;
console.warn(errMsg);
if (numMillis + warningPeriod < timeoutConfig.millis) {
setTimeout(function () {
return maybeTimingOut(numWarnings + 1);
}, warningPeriod);
}
}
}
}
});
}
function ensureValidAppTimeouts(timeouts) {
var result = {};
for (var key in globalTimeoutConfig) {
result[key] = assign({}, globalTimeoutConfig[key], timeouts && timeouts[key] || {});
}
return result;
}
function toLoadPromise(app) {
return Promise.resolve().then(function () {
if (app.loadPromise) {
return app.loadPromise;
}
if (app.status !== NOT_LOADED && app.status !== LOAD_ERROR) {
return app;
}
app.status = LOADING_SOURCE_CODE;
var appOpts, isUserErr;
return app.loadPromise = Promise.resolve().then(function () {
var loadPromise = app.loadApp(getProps(app));
if (!smellsLikeAPromise(loadPromise)) {
// The name of the app will be prepended to this error message inside of the handleAppError function
isUserErr = true;
throw Error(formatErrorMessage(33, "single-spa loading function did not return a promise. Check the second argument to registerApplication('".concat(toName(app), "', loadingFunction, activityFunction)"), toName(app)));
}
return loadPromise.then(function (val) {
app.loadErrorTime = null;
appOpts = val;
var validationErrMessage, validationErrCode;
if (_typeof(appOpts) !== "object") {
validationErrCode = 34;
{
validationErrMessage = "does not export anything";
}
}
if ( // ES Modules don't have the Object prototype
Object.prototype.hasOwnProperty.call(appOpts, "bootstrap") && !validLifecycleFn(appOpts.bootstrap)) {
validationErrCode = 35;
{
validationErrMessage = "does not export a valid bootstrap function or array of functions";
}
}
if (!validLifecycleFn(appOpts.mount)) {
validationErrCode = 36;
{
validationErrMessage = "does not export a mount function or array of functions";
}
}
if (!validLifecycleFn(appOpts.unmount)) {
validationErrCode = 37;
{
validationErrMessage = "does not export a unmount function or array of functions";
}
}
var type = objectType(appOpts);
if (validationErrCode) {
var appOptsStr;
try {
appOptsStr = JSON.stringify(appOpts);
} catch (_unused) {}
console.error(formatErrorMessage(validationErrCode, "The loading function for single-spa ".concat(type, " '").concat(toName(app), "' resolved with the following, which does not have bootstrap, mount, and unmount functions"), type, toName(app), appOptsStr), appOpts);
handleAppError(validationErrMessage, app, SKIP_BECAUSE_BROKEN);
return app;
}
if (appOpts.devtools && appOpts.devtools.overlays) {
app.devtools.overlays = assign({}, app.devtools.overlays, appOpts.devtools.overlays);
}
app.status = NOT_BOOTSTRAPPED;
app.bootstrap = flattenFnArray(appOpts, "bootstrap");
app.mount = flattenFnArray(appOpts, "mount");
app.unmount = flattenFnArray(appOpts, "unmount");
app.unload = flattenFnArray(appOpts, "unload");
app.timeouts = ensureValidAppTimeouts(appOpts.timeouts);
delete app.loadPromise;
return app;
});
}).catch(function (err) {
delete app.loadPromise;
var newStatus;
if (isUserErr) {
newStatus = SKIP_BECAUSE_BROKEN;
} else {
newStatus = LOAD_ERROR;
app.loadErrorTime = new Date().getTime();
}
handleAppError(err, app, newStatus);
return app;
});
});
}
var isInBrowser = typeof window !== "undefined";
/* We capture navigation event listeners so that we can make sure
* that application navigation listeners are not called until
* single-spa has ensured that the correct applications are
* unmounted and mounted.
*/
var capturedEventListeners = {
hashchange: [],
popstate: []
};
var routingEventsListeningTo = ["hashchange", "popstate"];
function navigateToUrl(obj) {
var url;
if (typeof obj === "string") {
url = obj;
} else if (this && this.href) {
url = this.href;
} else if (obj && obj.currentTarget && obj.currentTarget.href && obj.preventDefault) {
url = obj.currentTarget.href;
obj.preventDefault();
} else {
throw Error(formatErrorMessage(14, "singleSpaNavigate/navigateToUrl must be either called with a string url, with an <a> tag as its context, or with an event whose currentTarget is an <a> tag"));
}
var current = parseUri(window.location.href);
var destination = parseUri(url);
if (url.indexOf("#") === 0) {
window.location.hash = destination.hash;
} else if (current.host !== destination.host && destination.host) {
{
window.location.href = url;
}
} else if (destination.pathname === current.pathname && destination.search === current.search) {
window.location.hash = destination.hash;
} else {
// different path, host, or query params
window.history.pushState(null, null, url);
}
}
function callCapturedEventListeners(eventArguments) {
var _this = this;
if (eventArguments) {
var eventType = eventArguments[0].type;
if (routingEventsListeningTo.indexOf(eventType) >= 0) {
capturedEventListeners[eventType].forEach(function (listener) {
try {
// The error thrown by application event listener should not break single-spa down.
// Just like https://github.com/single-spa/single-spa/blob/85f5042dff960e40936f3a5069d56fc9477fac04/src/navigation/reroute.js#L140-L146 did
listener.apply(_this, eventArguments);
} catch (e) {
setTimeout(function () {
throw e;
});
}
});
}
}
}
var urlRerouteOnly;
function setUrlRerouteOnly(val) {
urlRerouteOnly = val;
}
function urlReroute() {
reroute([], arguments);
}
function patchedUpdateState(updateState, methodName) {
return function () {
var urlBefore = window.location.href;
var result = updateState.apply(this, arguments);
var urlAfter = window.location.href;
if (!urlRerouteOnly || urlBefore !== urlAfter) {
if (isStarted()) {
// fire an artificial popstate event once single-spa is started,
// so that single-spa applications know about routing that
// occurs in a different application
window.dispatchEvent(createPopStateEvent(window.history.state, methodName));
} else {
// do not fire an artificial popstate event before single-spa is started,
// since no single-spa applications need to know about routing events
// outside of their own router.
reroute([]);
}
}
return result;
};
}
function createPopStateEvent(state, originalMethodName) {
// https://github.com/single-spa/single-spa/issues/224 and https://github.com/single-spa/single-spa-angular/issues/49
// We need a popstate event even though the browser doesn't do one by default when you call replaceState, so that
// all the applications can reroute. We explicitly identify this extraneous event by setting singleSpa=true and
// singleSpaTrigger=<pushState|replaceState> on the event instance.
var evt;
try {
evt = new PopStateEvent("popstate", {
state: state
});
} catch (err) {
// IE 11 compatibility https://github.com/single-spa/single-spa/issues/299
// https://docs.microsoft.com/en-us/openspecs/ie_standards/ms-html5e/bd560f47-b349-4d2c-baa8-f1560fb489dd
evt = document.createEvent("PopStateEvent");
evt.initPopStateEvent("popstate", false, false, state);
}
evt.singleSpa = true;
evt.singleSpaTrigger = originalMethodName;
return evt;
}
if (isInBrowser) {
// We will trigger an app change for any routing events.
window.addEventListener("hashchange", urlReroute);
window.addEventListener("popstate", urlReroute); // Monkeypatch addEventListener so that we can ensure correct timing
var originalAddEventListener = window.addEventListener;
var originalRemoveEventListener = window.removeEventListener;
window.addEventListener = function (eventName, fn) {
if (typeof fn === "function") {
if (routingEventsListeningTo.indexOf(eventName) >= 0 && !find(capturedEventListeners[eventName], function (listener) {
return listener === fn;
})) {
capturedEventListeners[eventName].push(fn);
return;
}
}
return originalAddEventListener.apply(this, arguments);
};
window.removeEventListener = function (eventName, listenerFn) {
if (typeof listenerFn === "function") {
if (routingEventsListeningTo.indexOf(eventName) >= 0) {
capturedEventListeners[eventName] = capturedEventListeners[eventName].filter(function (fn) {
return fn !== listenerFn;
});
return;
}
}
return originalRemoveEventListener.apply(this, arguments);
};
window.history.pushState = patchedUpdateState(window.history.pushState, "pushState");
window.history.replaceState = patchedUpdateState(window.history.replaceState, "replaceState");
if (window.singleSpaNavigate) {
console.warn(formatErrorMessage(41, "single-spa has been loaded twice on the page. This can result in unexpected behavior."));
} else {
/* For convenience in `onclick` attributes, we expose a global function for navigating to
* whatever an <a> tag's href is.
*/
window.singleSpaNavigate = navigateToUrl;
}
}
function parseUri(str) {
var anchor = document.createElement("a");
anchor.href = str;
return anchor;
}
var hasInitialized = false;
function ensureJQuerySupport() {
var jQuery = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.jQuery;
if (!jQuery) {
if (window.$ && window.$.fn && window.$.fn.jquery) {
jQuery = window.$;
}
}
if (jQuery && !hasInitialized) {
var originalJQueryOn = jQuery.fn.on;
var originalJQueryOff = jQuery.fn.off;
jQuery.fn.on = function (eventString, fn) {
return captureRoutingEvents.call(this, originalJQueryOn, window.addEventListener, eventString, fn, arguments);
};
jQuery.fn.off = function (eventString, fn) {
return captureRoutingEvents.call(this, originalJQueryOff, window.removeEventListener, eventString, fn, arguments);
};
hasInitialized = true;
}
}
function captureRoutingEvents(originalJQueryFunction, nativeFunctionToCall, eventString, fn, originalArgs) {
if (typeof eventString !== "string") {
return originalJQueryFunction.apply(this, originalArgs);
}
var eventNames = eventString.split(/\s+/);
eventNames.forEach(function (eventName) {
if (routingEventsListeningTo.indexOf(eventName) >= 0) {
nativeFunctionToCall(eventName, fn);
eventString = eventString.replace(eventName, "");
}
});
if (eventString.trim() === "") {
return this;
} else {
return originalJQueryFunction.apply(this, originalArgs);
}
}
var appsToUnload = {};
function toUnloadPromise(app) {
return Promise.resolve().then(function () {
var unloadInfo = appsToUnload[toName(app)];
if (!unloadInfo) {
/* No one has called unloadApplication for this app,
*/
return app;
}
if (app.status === NOT_LOADED) {
/* This app is already unloaded. We just need to clean up
* anything that still thinks we need to unload the app.
*/
finishUnloadingApp(app, unloadInfo);
return app;
}
if (app.status === UNLOADING) {
/* Both unloadApplication and reroute want to unload this app.
* It only needs to be done once, though.
*/
return unloadInfo.promise.then(function () {
return app;
});
}
if (app.status !== NOT_MOUNTED && app.status !== LOAD_ERROR) {
/* The app cannot be unloaded until it is unmounted.
*/
return app;
}
var unloadPromise = app.status === LOAD_ERROR ? Promise.resolve() : reasonableTime(app, "unload");
app.status = UNLOADING;
return unloadPromise.then(function () {
finishUnloadingApp(app, unloadInfo);
return app;
}).catch(function (err) {
errorUnloadingApp(app, unloadInfo, err);
return app;
});
});
}
function finishUnloadingApp(app, unloadInfo) {
delete appsToUnload[toName(app)]; // Unloaded apps don't have lifecycles
delete app.bootstrap;
delete app.mount;
delete app.unmount;
delete app.unload;
app.status = NOT_LOADED;
/* resolve the promise of whoever called unloadApplication.
* This should be done after all other cleanup/bookkeeping
*/
unloadInfo.resolve();
}
function errorUnloadingApp(app, unloadInfo, err) {
delete appsToUnload[toName(app)]; // Unloaded apps don't have lifecycles
delete app.bootstrap;
delete app.mount;
delete app.unmount;
delete app.unload;
handleAppError(err, app, SKIP_BECAUSE_BROKEN);
unloadInfo.reject(err);
}
function addAppToUnload(app, promiseGetter, resolve, reject) {
appsToUnload[toName(app)] = {
app: app,
resolve: resolve,
reject: reject
};
Object.defineProperty(appsToUnload[toName(app)], "promise", {
get: promiseGetter
});
}
function getAppUnloadInfo(appName) {
return appsToUnload[appName];
}
var apps = [];
function getAppChanges() {
var appsToUnload = [],
appsToUnmount = [],
appsToLoad = [],
appsToMount = []; // We re-attempt to download applications in LOAD_ERROR after a timeout of 200 milliseconds
var currentTime = new Date().getTime();
apps.forEach(function (app) {
var appShouldBeActive = app.status !== SKIP_BECAUSE_BROKEN && shouldBeActive(app);
switch (app.status) {
case LOAD_ERROR:
if (appShouldBeActive && currentTime - app.loadErrorTime >= 200) {
appsToLoad.push(app);
}
break;
case NOT_LOADED:
case LOADING_SOURCE_CODE:
if (appShouldBeActive) {
appsToLoad.push(app);
}
break;
case NOT_BOOTSTRAPPED:
case NOT_MOUNTED:
if (!appShouldBeActive && getAppUnloadInfo(toName(app))) {
appsToUnload.push(app);
} else if (appShouldBeActive) {
appsToMount.push(app);
}
break;
case MOUNTED:
if (!appShouldBeActive) {
appsToUnmount.push(app);
}
break;
// all other statuses are ignored
}
});
return {
appsToUnload: appsToUnload,
appsToUnmount: appsToUnmount,
appsToLoad: appsToLoad,
appsToMount: appsToMount
};
}
function getMountedApps() {
return apps.filter(isActive).map(toName);
}
function getAppNames() {
return apps.map(toName);
} // used in devtools, not (currently) exposed as a single-spa API
function getRawAppData() {
return [].concat(apps);
}
function getAppStatus(appName) {
var app = find(apps, function (app) {
return toName(app) === appName;
});
return app ? app.status : null;
}
function registerApplication(appNameOrConfig, appOrLoadApp, activeWhen, customProps) {
var registration = sanitizeArguments(appNameOrConfig, appOrLoadApp, activeWhen, customProps);
if (getAppNames().indexOf(registration.name) !== -1) throw Error(formatErrorMessage(21, "There is already an app registered with name ".concat(registration.name), registration.name));
apps.push(assign({
loadErrorTime: null,
status: NOT_LOADED,
parcels: {},
devtools: {
overlays: {
options: {},
selectors: []
}
}
}, registration));
if (isInBrowser) {
ensureJQuerySupport();
reroute();
}
}
function checkActivityFunctions() {
var location = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.location;
return apps.filter(function (app) {
return app.activeWhen(location);
}).map(toName);
}
function unregisterApplication(appName) {
if (apps.filter(function (app) {
return toName(app) === appName;
}).length === 0) {
throw Error(formatErrorMessage(25, "Cannot unregister application '".concat(appName, "' because no such application has been registered"), appName));
}
return unloadApplication(appName).then(function () {
var appIndex = apps.map(toName).indexOf(appName);
apps.splice(appIndex, 1);
});
}
function unloadApplication(appName) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
waitForUnmount: false
};
if (typeof appName !== "string") {
throw Error(formatErrorMessage(26, "unloadApplication requires a string 'appName'"));
}
var app = find(apps, function (App) {
return toName(App) === appName;
});
if (!app) {
throw Error(formatErrorMessage(27, "Could not unload application '".concat(appName, "' because no such application has been registered"), appName));
}
var appUnloadInfo = getAppUnloadInfo(toName(app));
if (opts && opts.waitForUnmount) {
// We need to wait for unmount before unloading the app
if (appUnloadInfo) {
// Someone else is already waiting for this, too
return appUnloadInfo.promise;
} else {
// We're the first ones wanting the app to be resolved.
var promise = new Promise(function (resolve, reject) {
addAppToUnload(app, function () {
return promise;
}, resolve, reject);
});
return promise;
}
} else {
/* We should unmount the app, unload it, and remount it immediately.
*/
var resultPromise;
if (appUnloadInfo) {
// Someone else is already waiting for this app to unload
resultPromise = appUnloadInfo.promise;
immediatelyUnloadApp(app, appUnloadInfo.resolve, appUnloadInfo.reject);
} else {
// We're the first ones wanting the app to be resolved.
resultPromise = new Promise(function (resolve, reject) {
addAppToUnload(app, function () {
return resultPromise;
}, resolve, reject);
immediatelyUnloadApp(app, resolve, reject);
});
}
return resultPromise;
}
}
function immediatelyUnloadApp(app, resolve, reject) {
toUnmountPromise(app).then(toUnloadPromise).then(function () {
resolve();
setTimeout(function () {
// reroute, but the unload promise is done
reroute();
});
}).catch(reject);
}
function validateRegisterWithArguments(name, appOrLoadApp, activeWhen, customProps) {
if (typeof name !== "string" || name.length === 0) throw Error(formatErrorMessage(20, "The 1st argument to registerApplication must be a non-empty string 'appName'"));
if (!appOrLoadApp) throw Error(formatErrorMessage(23, "The 2nd argument to registerApplication must be an application or loading application function"));
if (typeof activeWhen !== "function") throw Error(formatErrorMessage(24, "The 3rd argument to registerApplication must be an activeWhen function"));
if (!validCustomProps(customProps)) throw Error(formatErrorMessage(22, "The optional 4th argument is a customProps and must be an object"));
}
function validateRegisterWithConfig(config) {
if (Array.isArray(config) || config === null) throw Error(formatErrorMessage(39, "Configuration object can't be an Array or null!"));
var validKeys = ["name", "app", "activeWhen", "customProps"];
var invalidKeys = Object.keys(config).reduce(function (invalidKeys, prop) {
return validKeys.indexOf(prop) >= 0 ? invalidKeys : invalidKeys.concat(prop);
}, []);
if (invalidKeys.length !== 0) throw Error(formatErrorMessage(38, "The configuration object accepts only: ".concat(validKeys.join(", "), ". Invalid keys: ").concat(invalidKeys.join(", "), "."), validKeys.join(", "), invalidKeys.join(", ")));
if (typeof config.name !== "string" || config.name.length === 0) throw Error(formatErrorMessage(20, "The config.name on registerApplication must be a non-empty string"));
if (_typeof(config.app) !== "object" && typeof config.app !== "function") throw Error(formatErrorMessage(20, "The config.app on registerApplication must be an application or a loading function"));
var allowsStringAndFunction = function allowsStringAndFunction(activeWhen) {
return typeof activeWhen === "string" || typeof activeWhen === "function";
};
if (!allowsStringAndFunction(config.activeWhen) && !(Array.isArray(config.activeWhen) && config.activeWhen.every(allowsStringAndFunction))) throw Error(formatErrorMessage(24, "The config.activeWhen on registerApplication must be a string, function or an array with both"));
if (!validCustomProps(config.customProps)) throw Error(formatErrorMessage(22, "The optional config.customProps must be an object"));
}
function validCustomProps(customProps) {
return !customProps || typeof customProps === "function" || _typeof(customProps) === "object" && customProps !== null && !Array.isArray(customProps);
}
function sanitizeArguments(appNameOrConfig, appOrLoadApp, activeWhen, customProps) {
var usingObjectAPI = _typeof(appNameOrConfig) === "object";
var registration = {
name: null,
loadApp: null,
activeWhen: null,
customProps: null
};
if (usingObjectAPI) {
validateRegisterWithConfig(appNameOrConfig);
registration.name = appNameOrConfig.name;
registration.loadApp = appNameOrConfig.app;
registration.activeWhen = appNameOrConfig.activeWhen;
registration.customProps = appNameOrConfig.customProps;
} else {
validateRegisterWithArguments(appNameOrConfig, appOrLoadApp, activeWhen, customProps);
registration.name = appNameOrConfig;
registration.loadApp = appOrLoadApp;
registration.activeWhen = activeWhen;
registration.customProps = customProps;
}
registration.loadApp = sanitizeLoadApp(registration.loadApp);
registration.customProps = sanitizeCustomProps(registration.customProps);
registration.activeWhen = sanitizeActiveWhen(registration.activeWhen);
return registration;
}
function sanitizeLoadApp(loadApp) {
if (typeof loadApp !== "function") {
return function () {
return Promise.resolve(loadApp);
};
}
return loadApp;
}
function sanitizeCustomProps(customProps) {
return customProps ? customProps : {};
}
function sanitizeActiveWhen(activeWhen) {
var activeWhenArray = Array.isArray(activeWhen) ? activeWhen : [activeWhen];
activeWhenArray = activeWhenArray.map(function (activeWhenOrPath) {
return typeof activeWhenOrPath === "function" ? activeWhenOrPath : pathToActiveWhen(activeWhenOrPath);
});
return function (location) {
return activeWhenArray.some(function (activeWhen) {
return activeWhen(location);
});
};
}
function pathToActiveWhen(path, exactMatch) {
var regex = toDynamicPathValidatorRegex(path, exactMatch);
return function (location) {
// compatible with IE10
var origin = location.origin;
if (!origin) {
origin = "".concat(location.protocol, "//").concat(location.host);
}
var route = location.href.replace(origin, "").replace(location.search, "").split("?")[0];
return regex.test(route);
};
}
function toDynamicPathValidatorRegex(path, exactMatch) {
var lastIndex = 0,
inDynamic = false,
regexStr = "^";
if (path[0] !== "/") {
path = "/" + path;
}
for (var charIndex = 0; charIndex < path.length; charIndex++) {
var char = path[charIndex];
var startOfDynamic = !inDynamic && char === ":";
var endOfDynamic = inDynamic && char === "/";
if (startOfDynamic || endOfDynamic) {
appendToRegex(charIndex);
}
}
appendToRegex(path.length);
return new RegExp(regexStr, "i");
function appendToRegex(index) {
var anyCharMaybeTrailingSlashRegex = "[^/]+/?";
var commonStringSubPath = escapeStrRegex(path.slice(lastIndex, index));
regexStr += inDynamic ? anyCharMaybeTrailingSlashRegex : commonStringSubPath;
if (index === path.length) {
if (inDynamic) {
if (exactMatch) {
// Ensure exact match paths that end in a dynamic portion don't match
// urls with characters after a slash after the dynamic portion.
regexStr += "$";
}
} else {
// For exact matches, expect no more characters. Otherwise, allow
// any characters.
var suffix = exactMatch ? "" : ".*";
regexStr = // use charAt instead as we could not use es6 method endsWith
regexStr.charAt(regexStr.length - 1) === "/" ? "".concat(regexStr).concat(suffix, "$") : "".concat(regexStr, "(/").concat(suffix, ")?(#.*)?$");
}
}
inDynamic = !inDynamic;
lastIndex = index;
}
function escapeStrRegex(str) {
// borrowed from https://github.com/sindresorhus/escape-string-regexp/blob/master/index.js
return str.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
}
}
var appChangeUnderway = false,
peopleWaitingOnAppChange = [],
currentUrl = isInBrowser && window.location.href;
function triggerAppChange() {
// Call reroute with no arguments, intentionally
return reroute();
}
function reroute() {
var pendingPromises = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var eventArguments = arguments.length > 1 ? arguments[1] : undefined;
if (appChangeUnderway) {
return new Promise(function (resolve, reject) {
peopleWaitingOnAppChange.push({
resolve: resolve,
reject: reject,
eventArguments: eventArguments
});
});
}
var _getAppChanges = getAppChanges(),
appsToUnload = _getAppChanges.appsToUnload,
appsToUnmount = _getAppChanges.appsToUnmount,
appsToLoad = _getAppChanges.appsToLoad,
appsToMount = _getAppChanges.appsToMount;
var appsThatChanged,
navigationIsCanceled = false,
oldUrl = currentUrl,
newUrl = currentUrl = window.location.href;
if (isStarted()) {
appChangeUnderway = true;
appsThatChanged = appsToUnload.concat(appsToLoad, appsToUnmount, appsToMount);
return performAppChanges();
} else {
appsThatChanged = appsToLoad;
return loadApps();
}
function cancelNavigation() {
navigationIsCanceled = true;
}
function loadApps() {
return Promise.resolve().then(function () {
var loadPromises = appsToLoad.map(toLoadPromise);
return Promise.all(loadPromises).then(callAllEventListeners) // there are no mounted apps, before start() is called, so we always return []
.then(function () {
return [];
}).catch(function (err) {
callAllEventListeners();
throw err;
});
});
}
function performAppChanges() {
return Promise.resolve().then(function () {
// https://github.com/single-spa/single-spa/issues/545
window.dispatchEvent(new customEvent(appsThatChanged.length === 0 ? "single-spa:before-no-app-change" : "single-spa:before-app-change", getCustomEventDetail(true)));
window.dispatchEvent(new customEvent("single-spa:before-routing-event", getCustomEventDetail(true, {
cancelNavigation: cancelNavigation
})));
if (navigationIsCanceled) {
window.dispatchEvent(new customEvent("single-spa:before-mount-routing-event", getCustomEventDetail(true)));
finishUpAndReturn();
navigateToUrl(oldUrl);
return;
}
var unloadPromises = appsToUnload.map(toUnloadPromise);
var unmountUnloadPromises = appsToUnmount.map(toUnmountPromise).map(function (unmountPromise) {
return unmountPromise.then(toUnloadPromise);
});
var allUnmountPromises = unmountUnloadPromises.concat(unloadPromises);
var unmountAllPromise = Promise.all(allUnmountPromises);
unmountAllPromise.then(function () {
window.dispatchEvent(new customEvent("single-spa:before-mount-routing-event", getCustomEventDetail(true)));
});
/* We load and bootstrap apps while other apps are unmounting, but we
* wait to mount the app until all apps are finishing unmounting
*/
var loadThenMountPromises = appsToLoad.map(function (app) {
return toLoadPromise(app).then(function (app) {
return tryToBootstrapAndMount(app, unmountAllPromise);
});
});
/* These are the apps that are already bootstrapped and just need
* to be mounted. They each wait for all unmounting apps to finish up
* before they mount.
*/
var mountPromises = appsToMount.filter(function (appToMount) {
return appsToLoad.indexOf(appToMount) < 0;
}).map(function (appToMount) {
return tryToBootstrapAndMount(appToMount, unmountAllPromise);
});
return unmountAllPromise.catch(function (err) {
callAllEventListeners();
throw err;
}).then(function () {
/* Now that the apps that needed to be unmounted are unmounted, their DOM navigation
* events (like hashchange or popstate) should have been cleaned up. So it's safe
* to let the remaining captured event listeners to handle about the DOM event.
*/
callAllEventListeners();
return Promise.all(loadThenMountPromises.concat(mountPromises)).catch(function (err) {
pendingPromises.forEach(function (promise) {
return promise.reject(err);
});
throw err;
}).then(finishUpAndReturn);
});
});
}
function finishUpAndReturn() {
var returnValue = getMountedApps();
pendingPromises.forEach(function (promise) {
return promise.resolve(returnValue);
});
try {
var appChangeEventName = appsThatChanged.length === 0 ? "single-spa:no-app-change" : "single-spa:app-change";
window.dispatchEvent(new customEvent(appChangeEventName, getCustomEventDetail()));
window.dispatchEvent(new customEvent("single-spa:routing-event", getCustomEventDetail()));
} catch (err) {
/* We use a setTimeout because if someone else's event handler throws an error, single-spa
* needs to carry on. If a listener to the event throws an error, it's their own fault, not
* single-spa's.
*/
setTimeout(function () {
throw err;
});
}
/* Setting this allows for subsequent calls to reroute() to actually perform
* a reroute instead of just getting queued behind the current reroute call.
* We want to do this after the mounting/unmounting is done but before we
* resolve the promise for the `reroute` function.
*/
appChangeUnderway = false;
if (peopleWaitingOnAppChange.length > 0) {
/* While we were rerouting, someone else triggered another reroute that got queued.
* So we need reroute again.
*/
var nextPendingPromises = peopleWaitingOnAppChange;
peopleWaitingOnAppChange = [];
reroute(nextPendingPromises);
}
return returnValue;
}
/* We need to call all event listeners that have been delayed because they were
* waiting on single-spa. This includes haschange and popstate events for both
* the current run of performAppChanges(), but also all of the queued event listeners.
* We want to call the listeners in the same order as if they had not been delayed by
* single-spa, which means queued ones first and then the most recent one.
*/
function callAllEventListeners() {
pendingPromises.forEach(function (pendingPromise) {
callCapturedEventListeners(pendingPromise.eventArguments);
});
callCapturedEventListeners(eventArguments);
}
function getCustomEventDetail() {
var _appsByNewStatus;
var isBeforeChanges = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var extraProperties = arguments.length > 1 ? arguments[1] : undefined;
var newAppStatuses = {};
var appsByNewStatus = (_appsByNewStatus = {}, _defineProperty(_appsByNewStatus, MOUNTED, []), _defineProperty(_appsByNewStatus, NOT_MOUNTED, []), _defineProperty(_appsByNewStatus, NOT_LOADED, []), _defineProperty(_appsByNewStatus, SKIP_BECAUSE_BROKEN, []), _appsByNewStatus);
if (isBeforeChanges) {
appsToLoad.concat(appsToMount).forEach(function (app, index) {
addApp(app, MOUNTED);
});
appsToUnload.forEach(function (app) {
addApp(app, NOT_LOADED);
});
appsToUnmount.forEach(function (app) {
addApp(app, NOT_MOUNTED);
});
} else {
appsThatChanged.forEach(function (app) {
addApp(app);
});
}
var result = {
detail: {
newAppStatuses: newAppStatuses,
appsByNewStatus: appsByNewStatus,
totalAppChanges: appsThatChanged.length,
originalEvent: eventArguments === null || eventArguments === void 0 ? void 0 : eventArguments[0],
oldUrl: oldUrl,
newUrl: newUrl,
navigationIsCanceled: navigationIsCanceled
}
};
if (extraProperties) {
assign(result.detail, extraProperties);
}
return result;
function addApp(app, status) {
var appName = toName(app);
status = status || getAppStatus(appName);
newAppStatuses[appName] = status;
var statusArr = appsByNewStatus[status] = appsByNewStatus[status] || [];
statusArr.push(appName);
}
}
}
/**
* Let's imagine that some kind of delay occurred during application loading.
* The user without waiting for the application to load switched to another route,
* this means that we shouldn't bootstrap and mount that application, thus we check
* twice if that application should be active before bootstrapping and mounting.
* https://github.com/single-spa/single-spa/issues/524
*/
function tryToBootstrapAndMount(app, unmountAllPromise) {
if (shouldBeActive(app)) {
return toBootstrapPromise(app).then(function (app) {
return unmountAllPromise.then(function () {
return shouldBeActive(app) ? toMountPromise(app) : app;
});
});
} else {
return unmountAllPromise.then(function () {
return app;
});
}
}
var started = false;
function start(opts) {
started = true;
if (opts && opts.urlRerouteOnly) {
setUrlRerouteOnly(opts.urlRerouteOnly);
}
if (isInBrowser) {
reroute();
}
}
function isStarted() {
return started;
}
if (isInBrowser) {
setTimeout(function () {
if (!started) {
console.warn(formatErrorMessage(1, "singleSpa.start() has not been called, 5000ms after single-spa was loaded. Before start() is called, apps can be declared and loaded, but not bootstrapped or mounted."));
}
}, 5000);
}
var devtools = {
getRawAppData: getRawAppData,
reroute: reroute,
NOT_LOADED: NOT_LOADED,
toLoadPromise: toLoadPromise,
toBootstrapPromise: toBootstrapPromise,
unregisterApplication: unregisterApplication
};
if (isInBrowser && window.__SINGLE_SPA_DEVTOOLS__) {
window.__SINGLE_SPA_DEVTOOLS__.exposedMethods = devtools;
}
}
};
});
//# sourceMappingURL=single-spa.dev.js.map