next
Version:
The React Framework
311 lines (309 loc) • 12.8 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
createMutableActionQueue: null,
dispatchNavigateAction: null,
dispatchTraverseAction: null,
getCurrentAppRouterState: null,
publicAppRouterInstance: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
createMutableActionQueue: function() {
return createMutableActionQueue;
},
dispatchNavigateAction: function() {
return dispatchNavigateAction;
},
dispatchTraverseAction: function() {
return dispatchTraverseAction;
},
getCurrentAppRouterState: function() {
return getCurrentAppRouterState;
},
publicAppRouterInstance: function() {
return publicAppRouterInstance;
}
});
const _routerreducertypes = require("./router-reducer/router-reducer-types");
const _routerreducer = require("./router-reducer/router-reducer");
const _react = require("react");
const _isthenable = require("../../shared/lib/is-thenable");
const _segmentcache = require("./segment-cache");
const _useactionqueue = require("./use-action-queue");
const _addbasepath = require("../add-base-path");
const _approuter = require("./app-router");
const _prefetchreducer = require("./router-reducer/reducers/prefetch-reducer");
const _links = require("./links");
function runRemainingActions(actionQueue, setState) {
if (actionQueue.pending !== null) {
actionQueue.pending = actionQueue.pending.next;
if (actionQueue.pending !== null) {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
runAction({
actionQueue,
action: actionQueue.pending,
setState
});
} else {
// No more actions are pending, check if a refresh is needed
if (actionQueue.needsRefresh) {
actionQueue.needsRefresh = false;
actionQueue.dispatch({
type: _routerreducertypes.ACTION_REFRESH,
origin: window.location.origin
}, setState);
}
}
}
}
async function runAction(param) {
let { actionQueue, action, setState } = param;
const prevState = actionQueue.state;
actionQueue.pending = action;
const payload = action.payload;
const actionResult = actionQueue.action(prevState, payload);
function handleResult(nextState) {
// if we discarded this action, the state should also be discarded
if (action.discarded) {
return;
}
actionQueue.state = nextState;
runRemainingActions(actionQueue, setState);
action.resolve(nextState);
}
// if the action is a promise, set up a callback to resolve it
if ((0, _isthenable.isThenable)(actionResult)) {
actionResult.then(handleResult, (err)=>{
runRemainingActions(actionQueue, setState);
action.reject(err);
});
} else {
handleResult(actionResult);
}
}
function dispatchAction(actionQueue, payload, setState) {
let resolvers = {
resolve: setState,
reject: ()=>{}
};
// most of the action types are async with the exception of restore
// it's important that restore is handled quickly since it's fired on the popstate event
// and we don't want to add any delay on a back/forward nav
// this only creates a promise for the async actions
if (payload.type !== _routerreducertypes.ACTION_RESTORE) {
// Create the promise and assign the resolvers to the object.
const deferredPromise = new Promise((resolve, reject)=>{
resolvers = {
resolve,
reject
};
});
(0, _react.startTransition)(()=>{
// we immediately notify React of the pending promise -- the resolver is attached to the action node
// and will be called when the associated action promise resolves
setState(deferredPromise);
});
}
const newAction = {
payload,
next: null,
resolve: resolvers.resolve,
reject: resolvers.reject
};
// Check if the queue is empty
if (actionQueue.pending === null) {
// The queue is empty, so add the action and start it immediately
// Mark this action as the last in the queue
actionQueue.last = newAction;
runAction({
actionQueue,
action: newAction,
setState
});
} else if (payload.type === _routerreducertypes.ACTION_NAVIGATE || payload.type === _routerreducertypes.ACTION_RESTORE) {
// Navigations (including back/forward) take priority over any pending actions.
// Mark the pending action as discarded (so the state is never applied) and start the navigation action immediately.
actionQueue.pending.discarded = true;
// The rest of the current queue should still execute after this navigation.
// (Note that it can't contain any earlier navigations, because we always put those into `actionQueue.pending` by calling `runAction`)
newAction.next = actionQueue.pending.next;
// if the pending action was a server action, mark the queue as needing a refresh once events are processed
if (actionQueue.pending.payload.type === _routerreducertypes.ACTION_SERVER_ACTION) {
actionQueue.needsRefresh = true;
}
runAction({
actionQueue,
action: newAction,
setState
});
} else {
// The queue is not empty, so add the action to the end of the queue
// It will be started by runRemainingActions after the previous action finishes
if (actionQueue.last !== null) {
actionQueue.last.next = newAction;
}
actionQueue.last = newAction;
}
}
let globalActionQueue = null;
function createMutableActionQueue(initialState, instrumentationHooks) {
const actionQueue = {
state: initialState,
dispatch: (payload, setState)=>dispatchAction(actionQueue, payload, setState),
action: async (state, action)=>{
const result = (0, _routerreducer.reducer)(state, action);
return result;
},
pending: null,
last: null,
onRouterTransitionStart: instrumentationHooks !== null && typeof instrumentationHooks.onRouterTransitionStart === 'function' ? instrumentationHooks.onRouterTransitionStart : null
};
if (typeof window !== 'undefined') {
// The action queue is lazily created on hydration, but after that point
// it doesn't change. So we can store it in a global rather than pass
// it around everywhere via props/context.
if (globalActionQueue !== null) {
throw Object.defineProperty(new Error('Internal Next.js Error: createMutableActionQueue was called more ' + 'than once'), "__NEXT_ERROR_CODE", {
value: "E624",
enumerable: false,
configurable: true
});
}
globalActionQueue = actionQueue;
}
return actionQueue;
}
function getCurrentAppRouterState() {
return globalActionQueue !== null ? globalActionQueue.state : null;
}
function getAppRouterActionQueue() {
if (globalActionQueue === null) {
throw Object.defineProperty(new Error('Internal Next.js error: Router action dispatched before initialization.'), "__NEXT_ERROR_CODE", {
value: "E668",
enumerable: false,
configurable: true
});
}
return globalActionQueue;
}
function getProfilingHookForOnNavigationStart() {
if (globalActionQueue !== null) {
return globalActionQueue.onRouterTransitionStart;
}
return null;
}
function dispatchNavigateAction(href, navigateType, shouldScroll, linkInstanceRef) {
// TODO: This stuff could just go into the reducer. Leaving as-is for now
// since we're about to rewrite all the router reducer stuff anyway.
const url = new URL((0, _addbasepath.addBasePath)(href), location.href);
if (process.env.__NEXT_APP_NAV_FAIL_HANDLING) {
window.next.__pendingUrl = url;
}
(0, _links.setLinkForCurrentNavigation)(linkInstanceRef);
const onRouterTransitionStart = getProfilingHookForOnNavigationStart();
if (onRouterTransitionStart !== null) {
onRouterTransitionStart(href, navigateType);
}
(0, _useactionqueue.dispatchAppRouterAction)({
type: _routerreducertypes.ACTION_NAVIGATE,
url,
isExternalUrl: (0, _approuter.isExternalURL)(url),
locationSearch: location.search,
shouldScroll,
navigateType,
allowAliasing: true
});
}
function dispatchTraverseAction(href, tree) {
const onRouterTransitionStart = getProfilingHookForOnNavigationStart();
if (onRouterTransitionStart !== null) {
onRouterTransitionStart(href, 'traverse');
}
(0, _useactionqueue.dispatchAppRouterAction)({
type: _routerreducertypes.ACTION_RESTORE,
url: new URL(href),
tree
});
}
const publicAppRouterInstance = {
back: ()=>window.history.back(),
forward: ()=>window.history.forward(),
prefetch: process.env.__NEXT_CLIENT_SEGMENT_CACHE ? // data in the router reducer state; it writes into a global mutable
// cache. So we don't need to dispatch an action.
(href, options)=>{
const actionQueue = getAppRouterActionQueue();
(0, _segmentcache.prefetch)(href, actionQueue.state.nextUrl, actionQueue.state.tree, (options == null ? void 0 : options.kind) === _routerreducertypes.PrefetchKind.FULL);
} : (href, options)=>{
// Use the old prefetch implementation.
const actionQueue = getAppRouterActionQueue();
const url = (0, _approuter.createPrefetchURL)(href);
if (url !== null) {
var _options_kind;
// The prefetch reducer doesn't actually update any state or
// trigger a rerender. It just writes to a mutable cache. So we
// shouldn't bother calling setState/dispatch; we can just re-run
// the reducer directly using the current state.
// TODO: Refactor this away from a "reducer" so it's
// less confusing.
(0, _prefetchreducer.prefetchReducer)(actionQueue.state, {
type: _routerreducertypes.ACTION_PREFETCH,
url,
kind: (_options_kind = options == null ? void 0 : options.kind) != null ? _options_kind : _routerreducertypes.PrefetchKind.FULL
});
}
},
replace: (href, options)=>{
(0, _react.startTransition)(()=>{
var _options_scroll;
dispatchNavigateAction(href, 'replace', (_options_scroll = options == null ? void 0 : options.scroll) != null ? _options_scroll : true, null);
});
},
push: (href, options)=>{
(0, _react.startTransition)(()=>{
var _options_scroll;
dispatchNavigateAction(href, 'push', (_options_scroll = options == null ? void 0 : options.scroll) != null ? _options_scroll : true, null);
});
},
refresh: ()=>{
(0, _react.startTransition)(()=>{
(0, _useactionqueue.dispatchAppRouterAction)({
type: _routerreducertypes.ACTION_REFRESH,
origin: window.location.origin
});
});
},
hmrRefresh: ()=>{
if (process.env.NODE_ENV !== 'development') {
throw Object.defineProperty(new Error('hmrRefresh can only be used in development mode. Please use refresh instead.'), "__NEXT_ERROR_CODE", {
value: "E485",
enumerable: false,
configurable: true
});
} else {
(0, _react.startTransition)(()=>{
(0, _useactionqueue.dispatchAppRouterAction)({
type: _routerreducertypes.ACTION_HMR_REFRESH,
origin: window.location.origin
});
});
}
}
};
// Exists for debugging purposes. Don't use in application code.
if (typeof window !== 'undefined' && window.next) {
window.next.router = publicAppRouterInstance;
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=app-router-instance.js.map
;