chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
diff --git a/dist/assemble-release-plan.cjs.dev.js b/dist/assemble-release-plan.cjs.dev.js
|
||||
index e1376ca756d69816f8c79637ee7b45161f092167..8cb0a24dced96f422afffe4ec21cf3628b4951dd 100644
|
||||
--- a/dist/assemble-release-plan.cjs.dev.js
|
||||
+++ b/dist/assemble-release-plan.cjs.dev.js
|
||||
@@ -257,7 +257,7 @@ function shouldBumpMajor({
|
||||
// we check if it is a peerDependency because if it is, our dependent bump type might need to be major.
|
||||
return depType === "peerDependencies" && nextRelease.type !== "none" && nextRelease.type !== "patch" && ( // 1. If onlyUpdatePeerDependentsWhenOutOfRange set to true, bump major if the version is leaving the range.
|
||||
// 2. If onlyUpdatePeerDependentsWhenOutOfRange set to false, bump major regardless whether or not the version is leaving the range.
|
||||
- !onlyUpdatePeerDependentsWhenOutOfRange || !semverSatisfies__default['default'](incrementVersion(nextRelease, preInfo), versionRange)) && ( // bump major only if the dependent doesn't already has a major release.
|
||||
+ !onlyUpdatePeerDependentsWhenOutOfRange) && ( // bump major only if the dependent doesn't already has a major release.
|
||||
!releases.has(dependent) || releases.has(dependent) && releases.get(dependent).type !== "major");
|
||||
}
|
||||
|
||||
diff --git a/dist/assemble-release-plan.cjs.prod.js b/dist/assemble-release-plan.cjs.prod.js
|
||||
index 3a83720644a94cdf6e62fa188a72c51c0384d00e..411ef794988c7f770545bca6a7a38f9419806cd6 100644
|
||||
--- a/dist/assemble-release-plan.cjs.prod.js
|
||||
+++ b/dist/assemble-release-plan.cjs.prod.js
|
||||
@@ -130,7 +130,7 @@ function getDependencyVersionRanges(dependentPkgJSON, dependencyRelease) {
|
||||
}
|
||||
|
||||
function shouldBumpMajor({dependent: dependent, depType: depType, versionRange: versionRange, releases: releases, nextRelease: nextRelease, preInfo: preInfo, onlyUpdatePeerDependentsWhenOutOfRange: onlyUpdatePeerDependentsWhenOutOfRange}) {
|
||||
- return "peerDependencies" === depType && "none" !== nextRelease.type && "patch" !== nextRelease.type && (!onlyUpdatePeerDependentsWhenOutOfRange || !semverSatisfies__default.default(incrementVersion(nextRelease, preInfo), versionRange)) && (!releases.has(dependent) || releases.has(dependent) && "major" !== releases.get(dependent).type);
|
||||
+ return "peerDependencies" === depType && "none" !== nextRelease.type && "patch" !== nextRelease.type && !onlyUpdatePeerDependentsWhenOutOfRange && (!releases.has(dependent) || releases.has(dependent) && "major" !== releases.get(dependent).type);
|
||||
}
|
||||
|
||||
function flattenReleases(changesets, packagesByName, ignoredPackages) {
|
||||
@@ -0,0 +1,53 @@
|
||||
diff --git a/dist/cache.js b/dist/cache.js
|
||||
index d58eea314385e5b5dea1f5d9104ba9446deb6364..3554cef6ba6cd1c8186bf0fa880eab2c5a4f3289 100644
|
||||
--- a/dist/cache.js
|
||||
+++ b/dist/cache.js
|
||||
@@ -1,11 +1,12 @@
|
||||
import { ADD, CHANGE, CONNECT, DELETE, ERROR, UPDATE, } from './informer.js';
|
||||
import { ObjectSerializer } from './serializer.js';
|
||||
export class ListWatch {
|
||||
- constructor(path, watch, listFn, autoStart = true, labelSelector) {
|
||||
+ constructor(path, watch, listFn, autoStart = true, labelSelector, fieldSelector) {
|
||||
this.path = path;
|
||||
this.watch = watch;
|
||||
this.listFn = listFn;
|
||||
this.labelSelector = labelSelector;
|
||||
+ this.fieldSelector = fieldSelector;
|
||||
this.objects = new Map();
|
||||
this.indexCache = {};
|
||||
this.callbackCache = {};
|
||||
@@ -113,6 +114,9 @@ export class ListWatch {
|
||||
if (this.labelSelector !== undefined) {
|
||||
queryParams.labelSelector = ObjectSerializer.serialize(this.labelSelector, 'string');
|
||||
}
|
||||
+ if (this.fieldSelector !== undefined) {
|
||||
+ queryParams.fieldSelector = ObjectSerializer.serialize(this.fieldSelector, 'string');
|
||||
+ }
|
||||
this.request = await this.watch.watch(this.path, queryParams, this.watchHandler.bind(this), this.doneHandler.bind(this));
|
||||
}
|
||||
addOrUpdateItems(items) {
|
||||
diff --git a/dist/informer.d.ts b/dist/informer.d.ts
|
||||
index 903de9078b4b11a5fd933802be042e1a4f966079..4177cf12b5705a373def8f22d235416cd82114c6 100644
|
||||
--- a/dist/informer.d.ts
|
||||
+++ b/dist/informer.d.ts
|
||||
@@ -16,4 +16,4 @@ export interface Informer<T extends KubernetesObject> {
|
||||
start(): Promise<void>;
|
||||
stop(): Promise<void>;
|
||||
}
|
||||
-export declare function makeInformer<T extends KubernetesObject>(kubeconfig: KubeConfig, path: string, listPromiseFn: ListPromise<T>, labelSelector?: string): Informer<T>;
|
||||
+export declare function makeInformer<T extends KubernetesObject>(kubeconfig: KubeConfig, path: string, listPromiseFn: ListPromise<T>, labelSelector?: string, fieldSelector?: string): Informer<T>;
|
||||
diff --git a/dist/informer.js b/dist/informer.js
|
||||
index 0dc471fc3e2d8e653a4c4795211b4774563d2d14..ae33a4357308b77bfb4e7588807e9ac0d7643ba3 100644
|
||||
--- a/dist/informer.js
|
||||
+++ b/dist/informer.js
|
||||
@@ -9,8 +9,8 @@ export const DELETE = 'delete';
|
||||
export const CONNECT = 'connect';
|
||||
// This is issued when there is an error
|
||||
export const ERROR = 'error';
|
||||
-export function makeInformer(kubeconfig, path, listPromiseFn, labelSelector) {
|
||||
+export function makeInformer(kubeconfig, path, listPromiseFn, labelSelector, fieldSelector) {
|
||||
const watch = new Watch(kubeconfig);
|
||||
- return new ListWatch(path, watch, listPromiseFn, false, labelSelector);
|
||||
+ return new ListWatch(path, watch, listPromiseFn, false, labelSelector, fieldSelector);
|
||||
}
|
||||
//# sourceMappingURL=informer.js.map
|
||||
@@ -0,0 +1,58 @@
|
||||
diff --git a/dist/router.cjs.js b/dist/router.cjs.js
|
||||
index 6aa7db6fb5a7182afcdf17b16a3356abfa1e7945..95edbde228beff8dbd13fb2800302e31a932ef25 100644
|
||||
--- a/dist/router.cjs.js
|
||||
+++ b/dist/router.cjs.js
|
||||
@@ -783,6 +783,11 @@ function convertRoutesToDataRoutes(routes, mapRouteProperties, parentPath, manif
|
||||
*
|
||||
* @see https://reactrouter.com/v6/utils/match-routes
|
||||
*/
|
||||
+// trigger.dev perf patch — memoize per-request route matching. See patches/README.md
|
||||
+// (backports the idea in react-router PR #14866, which was closed in favor of the partial
|
||||
+// fix #14967; maintainer suggested patch-package until the Remix 3 route-pattern rewrite).
|
||||
+let __branchCache = new WeakMap();
|
||||
+let __compileCache = new Map();
|
||||
function matchRoutes(routes, locationArg, basename) {
|
||||
if (basename === void 0) {
|
||||
basename = "/";
|
||||
@@ -795,8 +800,13 @@ function matchRoutesImpl(routes, locationArg, basename, allowPartial) {
|
||||
if (pathname == null) {
|
||||
return null;
|
||||
}
|
||||
- let branches = flattenRoutes(routes);
|
||||
- rankRouteBranches(branches);
|
||||
+ // flatten+rank depend only on `routes` (static) — cache per route-tree ref.
|
||||
+ let branches = __branchCache.get(routes);
|
||||
+ if (!branches) {
|
||||
+ branches = flattenRoutes(routes);
|
||||
+ rankRouteBranches(branches);
|
||||
+ __branchCache.set(routes, branches);
|
||||
+ }
|
||||
let matches = null;
|
||||
let decoded = decodePath(pathname);
|
||||
for (let i = 0; matches == null && i < branches.length; ++i) {
|
||||
@@ -1115,6 +1125,12 @@ function compilePath(path, caseSensitive, end) {
|
||||
if (end === void 0) {
|
||||
end = true;
|
||||
}
|
||||
+ // perf patch: cache the compiled [regexp, params] by pattern (see patches/README.md).
|
||||
+ let __ck = path + "\0" + caseSensitive + "\0" + end;
|
||||
+ let __cc = __compileCache.get(__ck);
|
||||
+ if (__cc !== void 0) {
|
||||
+ return __cc;
|
||||
+ }
|
||||
warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\"."));
|
||||
let params = [];
|
||||
let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
|
||||
@@ -1147,7 +1163,11 @@ function compilePath(path, caseSensitive, end) {
|
||||
regexpSource += "(?:(?=\\/|$))";
|
||||
} else ;
|
||||
let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
|
||||
- return [matcher, params];
|
||||
+ let __res = [matcher, params];
|
||||
+ // Bounded: route patterns are a static set; the cap guards any dynamic matchPath() use.
|
||||
+ if (__compileCache.size >= 2000) __compileCache.clear();
|
||||
+ __compileCache.set(__ck, __res);
|
||||
+ return __res;
|
||||
}
|
||||
function decodePath(value) {
|
||||
try {
|
||||
@@ -0,0 +1,39 @@
|
||||
diff --git a/build/cjs/vendor/instrumentation.js b/build/cjs/vendor/instrumentation.js
|
||||
index 84e18d1051f57d5807e65c8b8ce858ceee7d4557..640a5253d565650338fe33e0ea52c8dffc63e4e7 100644
|
||||
--- a/build/cjs/vendor/instrumentation.js
|
||||
+++ b/build/cjs/vendor/instrumentation.js
|
||||
@@ -238,7 +238,7 @@ class RemixInstrumentation extends instrumentation.InstrumentationBase {
|
||||
return function callRouteAction(original) {
|
||||
return async function patchCallRouteAction( ...args) {
|
||||
const [params] = args;
|
||||
- const clonedRequest = params.request.clone();
|
||||
+ const clonedRequest = params.request;
|
||||
const span = plugin.tracer.startSpan(
|
||||
`ACTION ${params.routeId}`,
|
||||
{ attributes: { [semanticConventions.SemanticAttributes.CODE_FUNCTION]: 'action' } },
|
||||
@@ -257,25 +257,6 @@ class RemixInstrumentation extends instrumentation.InstrumentationBase {
|
||||
.then(async response => {
|
||||
addResponseAttributesToSpan(span, response);
|
||||
|
||||
- try {
|
||||
- const formData = await clonedRequest.formData();
|
||||
- const { actionFormDataAttributes: actionFormAttributes } = plugin.getConfig();
|
||||
-
|
||||
- formData.forEach((value, key) => {
|
||||
- if (
|
||||
- actionFormAttributes?.[key] &&
|
||||
- actionFormAttributes[key] !== false &&
|
||||
- typeof value === 'string'
|
||||
- ) {
|
||||
- const keyName = actionFormAttributes[key] === true ? key : actionFormAttributes[key];
|
||||
- span.setAttribute(`formData.${keyName}`, value.toString());
|
||||
- }
|
||||
- });
|
||||
- } catch {
|
||||
- // Silently continue on any error. Typically happens because the action body cannot be processed
|
||||
- // into FormData, in which case we should just continue.
|
||||
- }
|
||||
-
|
||||
return response;
|
||||
})
|
||||
.catch(async error => {
|
||||
@@ -0,0 +1,26 @@
|
||||
diff --git a/dist/index.js b/dist/index.js
|
||||
index 7d1502426320957017988aed0c29974acd70e8da..062769cda055302d737503e5d1ba5e62609c934f 100644
|
||||
--- a/dist/index.js
|
||||
+++ b/dist/index.js
|
||||
@@ -841,7 +841,7 @@ var tokenBucketLimitScript = `
|
||||
refilledAt = refilledAt + numRefills * interval
|
||||
end
|
||||
|
||||
- if tokens == 0 then
|
||||
+ if tokens < incrementBy then
|
||||
return {-1, refilledAt + interval}
|
||||
end
|
||||
|
||||
diff --git a/dist/index.mjs b/dist/index.mjs
|
||||
index 25a2c888be27b7c5aff41de63d5df189e0031145..53b4a4b2d2ef55f709f7404cc6a66058b7f3191a 100644
|
||||
--- a/dist/index.mjs
|
||||
+++ b/dist/index.mjs
|
||||
@@ -813,7 +813,7 @@ var tokenBucketLimitScript = `
|
||||
refilledAt = refilledAt + numRefills * interval
|
||||
end
|
||||
|
||||
- if tokens == 0 then
|
||||
+ if tokens < incrementBy then
|
||||
return {-1, refilledAt + interval}
|
||||
end
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
diff --git a/dist/commonjs/index.js b/dist/commonjs/index.js
|
||||
index e3bdcf702702392e9a06c981545f659ee7c5970e..d88ae6b2dc5b4cf1970cb693f58a926bd12a8f45 100644
|
||||
--- a/dist/commonjs/index.js
|
||||
+++ b/dist/commonjs/index.js
|
||||
@@ -757,30 +757,14 @@ function updateLayout(context, dragEvent) {
|
||||
panelAfter.onCollapseChange.current(false);
|
||||
}
|
||||
}
|
||||
- const panelBeforeIsAboutToCollapse = panelBefore.currentValue.value.eq(getUnitPixelValue(context, panelBefore.min));
|
||||
- // If the panel was expanded and now is at it's min size, collapse it
|
||||
- if (!dragEvent.disregardCollapseBuffer &&
|
||||
- panelBefore.collapsible &&
|
||||
- panelBeforeIsAboutToCollapse) {
|
||||
- if (panelBefore.onCollapseChange?.current &&
|
||||
- panelBefore.collapseIsControlled &&
|
||||
- !dragEvent.controlled &&
|
||||
- !dragEvent.isVirtual) {
|
||||
- panelBefore.onCollapseChange.current(true);
|
||||
- return { dragOvershoot: newDragOvershoot };
|
||||
- }
|
||||
- // Make it collapsed
|
||||
- panelBefore.collapsed = true;
|
||||
- panelBeforeNewValue = getUnitPixelValue(context, panelBefore.collapsedSize);
|
||||
- // Add the extra space created to the before panel
|
||||
- panelAfterNewValue = panelAfter.currentValue.value.add(panelBeforePreviousValue.minus(panelBeforeNewValue));
|
||||
- if (panelBefore.onCollapseChange?.current &&
|
||||
- !panelBefore.collapseIsControlled &&
|
||||
- !dragEvent.controlled &&
|
||||
- !dragEvent.isVirtual) {
|
||||
- panelBefore.onCollapseChange.current(true);
|
||||
- }
|
||||
- }
|
||||
+ // Drag-to-collapse is disabled in this fork: every consumer of the
|
||||
+ // library uses controlled `collapsed` props and triggers collapse
|
||||
+ // explicitly (close button, ESC, URL change, etc.). The original auto-
|
||||
+ // collapse-on-drag logic that lived here would notify the parent when a
|
||||
+ // collapsible panel reached its min during a drag — keeping it for our
|
||||
+ // (controlled-only) case caused state-machine deadlocks when handlers
|
||||
+ // were no-ops, so the block is removed entirely. Panels just clamp at
|
||||
+ // `min` during drag now.
|
||||
panelBefore.currentValue = { type: "pixel", value: panelBeforeNewValue };
|
||||
panelAfter.currentValue = { type: "pixel", value: panelAfterNewValue };
|
||||
const leftoverSpace = new big_js_1.default(getGroupSize(context)).minus(newItems.reduce((acc, b) => acc.add(isPanelData(b) ? b.currentValue.value : b.size.value), new big_js_1.default(0)));
|
||||
@@ -940,7 +924,12 @@ function setCookie(name, jsonData) {
|
||||
function getDeltaForEvent(context, event) {
|
||||
const panel = getPanelWithId(context, event.panelId);
|
||||
if (event.type === "expandPanel") {
|
||||
- return new big_js_1.default(panel.sizeBeforeCollapse ?? getUnitPixelValue(context, panel.min)).minus(panel.currentValue.value);
|
||||
+ // Fall back to `default` before `min` so the first-ever expand of a
|
||||
+ // panel that started life collapsed lands at its configured default
|
||||
+ // size rather than getting stuck at `min`.
|
||||
+ const defaultPx = panel.default ? getUnitPixelValue(context, panel.default) : undefined;
|
||||
+ const target = panel.sizeBeforeCollapse ?? defaultPx ?? getUnitPixelValue(context, panel.min);
|
||||
+ return new big_js_1.default(target).minus(panel.currentValue.value);
|
||||
}
|
||||
const collapsedSize = getUnitPixelValue(context, panel.collapsedSize);
|
||||
return panel.currentValue.value.minus(collapsedSize);
|
||||
diff --git a/dist/esm/index.js b/dist/esm/index.js
|
||||
index f8fddd70c0f1aaed29f2fb0ca0d8093d8ce66335..d1dae8beb1447afca47b91e796b8279135f50c36 100644
|
||||
--- a/dist/esm/index.js
|
||||
+++ b/dist/esm/index.js
|
||||
@@ -728,30 +728,14 @@ function updateLayout(context, dragEvent) {
|
||||
panelAfter.onCollapseChange.current(false);
|
||||
}
|
||||
}
|
||||
- const panelBeforeIsAboutToCollapse = panelBefore.currentValue.value.eq(getUnitPixelValue(context, panelBefore.min));
|
||||
- // If the panel was expanded and now is at it's min size, collapse it
|
||||
- if (!dragEvent.disregardCollapseBuffer &&
|
||||
- panelBefore.collapsible &&
|
||||
- panelBeforeIsAboutToCollapse) {
|
||||
- if (panelBefore.onCollapseChange?.current &&
|
||||
- panelBefore.collapseIsControlled &&
|
||||
- !dragEvent.controlled &&
|
||||
- !dragEvent.isVirtual) {
|
||||
- panelBefore.onCollapseChange.current(true);
|
||||
- return { dragOvershoot: newDragOvershoot };
|
||||
- }
|
||||
- // Make it collapsed
|
||||
- panelBefore.collapsed = true;
|
||||
- panelBeforeNewValue = getUnitPixelValue(context, panelBefore.collapsedSize);
|
||||
- // Add the extra space created to the before panel
|
||||
- panelAfterNewValue = panelAfter.currentValue.value.add(panelBeforePreviousValue.minus(panelBeforeNewValue));
|
||||
- if (panelBefore.onCollapseChange?.current &&
|
||||
- !panelBefore.collapseIsControlled &&
|
||||
- !dragEvent.controlled &&
|
||||
- !dragEvent.isVirtual) {
|
||||
- panelBefore.onCollapseChange.current(true);
|
||||
- }
|
||||
- }
|
||||
+ // Drag-to-collapse is disabled in this fork: every consumer of the
|
||||
+ // library uses controlled `collapsed` props and triggers collapse
|
||||
+ // explicitly (close button, ESC, URL change, etc.). The original auto-
|
||||
+ // collapse-on-drag logic that lived here would notify the parent when a
|
||||
+ // collapsible panel reached its min during a drag — keeping it for our
|
||||
+ // (controlled-only) case caused state-machine deadlocks when handlers
|
||||
+ // were no-ops, so the block is removed entirely. Panels just clamp at
|
||||
+ // `min` during drag now.
|
||||
panelBefore.currentValue = { type: "pixel", value: panelBeforeNewValue };
|
||||
panelAfter.currentValue = { type: "pixel", value: panelAfterNewValue };
|
||||
const leftoverSpace = new Big(getGroupSize(context)).minus(newItems.reduce((acc, b) => acc.add(isPanelData(b) ? b.currentValue.value : b.size.value), new Big(0)));
|
||||
@@ -911,7 +895,12 @@ function setCookie(name, jsonData) {
|
||||
function getDeltaForEvent(context, event) {
|
||||
const panel = getPanelWithId(context, event.panelId);
|
||||
if (event.type === "expandPanel") {
|
||||
- return new Big(panel.sizeBeforeCollapse ?? getUnitPixelValue(context, panel.min)).minus(panel.currentValue.value);
|
||||
+ // Fall back to `default` before `min` so the first-ever expand of a
|
||||
+ // panel that started life collapsed lands at its configured default
|
||||
+ // size rather than getting stuck at `min`.
|
||||
+ const defaultPx = panel.default ? getUnitPixelValue(context, panel.default) : undefined;
|
||||
+ const target = panel.sizeBeforeCollapse ?? defaultPx ?? getUnitPixelValue(context, panel.min);
|
||||
+ return new Big(target).minus(panel.currentValue.value);
|
||||
}
|
||||
const collapsedSize = getUnitPixelValue(context, panel.collapsedSize);
|
||||
return panel.currentValue.value.minus(collapsedSize);
|
||||
@@ -0,0 +1,101 @@
|
||||
# Patches
|
||||
|
||||
This directory holds [pnpm patches](https://pnpm.io/cli/patch) applied on install via
|
||||
`pnpm.patchedDependencies` in the root `package.json`. Each `.patch` is a diff against the
|
||||
published package. Most are small and self-explanatory from the diff; the non-obvious ones
|
||||
are documented below.
|
||||
|
||||
---
|
||||
|
||||
## `@remix-run/router@1.23.2` — route-matching memoization
|
||||
|
||||
**File:** `patches/@remix-run__router@1.23.2.patch` (patches `dist/router.cjs.js`)
|
||||
|
||||
### What it does
|
||||
|
||||
Three changes to `matchRoutesImpl` / `compilePath`, all pure memoization of work that
|
||||
depends only on the **static** route manifest:
|
||||
|
||||
1. **Cache flattened + ranked branches per route-tree** (`WeakMap` keyed by the `routes`
|
||||
ref). `flattenRoutes()` + `rankRouteBranches()` were recomputed on *every* `matchRoutes`
|
||||
call across all ~436 webapp routes.
|
||||
2. **Hoist `decodePath(pathname)` out of the branch-match loop** — it's loop-invariant but
|
||||
was recomputed once per branch.
|
||||
3. **Memoize `compilePath` compiled regexes** by `path|caseSensitive|end` (bounded `Map`,
|
||||
cap 2000). The matcher RegExp was rebuilt on every `matchPath` call.
|
||||
|
||||
### Why
|
||||
|
||||
Profiling the realtime runs feed under load (100 concurrent tag feeds, ~425 req/s) found
|
||||
**~68% of webapp CPU was spent in react-router's `matchRoutes`** — re-flattening,
|
||||
re-ranking, and re-compiling the entire route table on every request. It is **not** a dev
|
||||
artifact: there is no `NODE_ENV` gate, and a `NODE_ENV=production` profile was identical
|
||||
(67.9% vs 68.3%). The realtime feed's high request rate (each long-poll returns fast and
|
||||
immediately re-polls) just amplifies a latent per-request cost that large route tables pay
|
||||
everywhere.
|
||||
|
||||
Measured on a single instance, same load, before vs after this patch:
|
||||
|
||||
| | before | after |
|
||||
|---|---|---|
|
||||
| active CPU (self-time / window) | 28.3s | 18.5s (**−34%**) |
|
||||
| route-matching self-time | 19.2s | 7.5s (**−61%**) |
|
||||
| event-loop lag p99 | 322ms | 113ms (**−65%**) |
|
||||
| idle headroom | 26% | 52% |
|
||||
|
||||
The realtime machinery itself (router/hydrate/serialize/diff) was ~0% — the bottleneck was
|
||||
entirely generic Remix request overhead.
|
||||
|
||||
### Upstream status (why we patch instead of upgrade)
|
||||
|
||||
This is a known, acknowledged inefficiency, and it is **only partially fixed in React
|
||||
Router v7** — which we can't adopt without a full Remix 2 → RR7 framework migration.
|
||||
|
||||
- [Issue #8653 "Performance issues"](https://github.com/remix-run/react-router/issues/8653)
|
||||
reported it (a user with 12k routes, ~67ms per match) and was closed as a dup of the
|
||||
route-ranking discussion [remix#4786](https://github.com/remix-run/remix/discussions/4786).
|
||||
- [PR #14866 "Optimize route matching performance with caching"](https://github.com/remix-run/react-router/pull/14866)
|
||||
implemented *exactly this patch* (hoist `decodePath`, cache `compilePath`, cache
|
||||
flatten/rank), claiming **~80% route-matching CPU reduction on a 400+ route app**. It was
|
||||
**closed, not merged.**
|
||||
- [PR #14967 "perf: cache flattened/ranked route branches"](https://github.com/remix-run/react-router/pull/14967)
|
||||
is the partial fix that *did* ship (in v7): it caches only the branches, threaded via a
|
||||
`precomputedBranches` param through the framework's server-runtime (~15% SSR gain). It
|
||||
does **not** cache `compilePath` — that regex rebuild remains even on `main`.
|
||||
([PR #14971](https://github.com/remix-run/react-router/pull/14971) added client-side wins.)
|
||||
|
||||
The maintainer's reasoning for closing the fuller PR (#14866), verbatim:
|
||||
|
||||
> "This is great as a `patch-package` optimization for those who want it, but we are
|
||||
> actively working on integrating the more performant route-pattern library from Remix 3 so
|
||||
> we'd rather just do the right 'fix' and ship the new algorithm instead of trying to
|
||||
> band-aide perf improvements to the existing algorithm which was written with a very
|
||||
> different set of constraints. Those constraints come from early v6 when it was only
|
||||
> declarative mode so route trees were defined at render time and thus had to be
|
||||
> re-flattened/re-ranked/re-compiled every time."
|
||||
|
||||
So: the re-compute-everything design is a holdover from early React Router v6 declarative
|
||||
mode (route trees defined at render time, so recomputing was correct then). The maintainer
|
||||
**explicitly endorsed patch-package as the interim approach** and is betting on the Remix 3
|
||||
route-pattern rewrite for the real fix. This patch is that sanctioned stopgap — and it also
|
||||
includes the `compilePath` cache the merged PR left on the table.
|
||||
|
||||
### Safety
|
||||
|
||||
Pure memoization of deterministic, internal-only values:
|
||||
|
||||
- `flattenRoutes`/`rankRouteBranches` and the compiled regexes depend solely on the static
|
||||
route manifest; the cached values are never returned to or mutated by the framework.
|
||||
- The compiled `RegExp` has no `/g` flag, so `.exec()` carries no cross-call state — safe to
|
||||
share under concurrency.
|
||||
- The branch cache is a `WeakMap` (collected with its route tree); the compile cache is
|
||||
bounded at 2000 entries (route patterns are a static set; the cap only guards any dynamic
|
||||
`matchPath()` use).
|
||||
- Targets the **CJS** build (`dist/router.cjs.js`), which the webapp server loads at runtime
|
||||
(`@remix-run/router` is not bundled into the server build).
|
||||
|
||||
### When to remove
|
||||
|
||||
Drop this patch if/when the webapp moves to React Router v7+ (which threads
|
||||
`precomputedBranches` itself) or the Remix 3 route-pattern matcher lands. Re-profile at that
|
||||
point — the `compilePath` cache may still be worth keeping since upstream never added it.
|
||||
@@ -0,0 +1,470 @@
|
||||
diff --git a/ANTLRInputStream.js b/ANTLRInputStream.js
|
||||
index eaeb0800e83d2a4bd21699ff5fc8b0bb8920efbb..ed6c85c047d1ead64653e212d579967536dca664 100644
|
||||
--- a/ANTLRInputStream.js
|
||||
+++ b/ANTLRInputStream.js
|
||||
@@ -43,7 +43,7 @@ class ANTLRInputStream {
|
||||
}
|
||||
consume() {
|
||||
if (this.p >= this.n) {
|
||||
- assert(this.LA(1) === IntStream_1.IntStream.EOF);
|
||||
+ assert.ok(this.LA(1) === IntStream_1.IntStream.EOF);
|
||||
throw new Error("cannot consume EOF");
|
||||
}
|
||||
//System.out.println("prev p="+p+", c="+(char)data[p]);
|
||||
diff --git a/BufferedTokenStream.js b/BufferedTokenStream.js
|
||||
index 9a3c6d19bf959819d96552d73267f93985a6fd67..11511d985b9b2b7dd0b140579032a0929d0a4342 100644
|
||||
--- a/BufferedTokenStream.js
|
||||
+++ b/BufferedTokenStream.js
|
||||
@@ -126,7 +126,7 @@ let BufferedTokenStream = class BufferedTokenStream {
|
||||
* @see #get(int i)
|
||||
*/
|
||||
sync(i) {
|
||||
- assert(i >= 0);
|
||||
+ assert.ok(i >= 0);
|
||||
let n = i - this.tokens.length + 1; // how many more elements we need?
|
||||
//System.out.println("sync("+i+") needs "+n);
|
||||
if (n > 0) {
|
||||
@@ -251,7 +251,7 @@ let BufferedTokenStream = class BufferedTokenStream {
|
||||
getTokens(start, stop, types) {
|
||||
this.lazyInit();
|
||||
if (start === undefined) {
|
||||
- assert(stop === undefined && types === undefined);
|
||||
+ assert.ok(stop === undefined && types === undefined);
|
||||
return this.tokens;
|
||||
}
|
||||
else if (stop === undefined) {
|
||||
diff --git a/CodePointBuffer.js b/CodePointBuffer.js
|
||||
index 7d50d372da9a1ccae48f55dd6e5ee388f583ace1..f6452956227847a4e2477c8eb1017e56ec9a58d1 100644
|
||||
--- a/CodePointBuffer.js
|
||||
+++ b/CodePointBuffer.js
|
||||
@@ -109,7 +109,7 @@ exports.CodePointBuffer = CodePointBuffer;
|
||||
}
|
||||
}
|
||||
appendArrayByte(utf16In) {
|
||||
- assert(this.prevHighSurrogate === -1);
|
||||
+ assert.ok(this.prevHighSurrogate === -1);
|
||||
let input = utf16In;
|
||||
let inOffset = 0;
|
||||
let inLimit = utf16In.length;
|
||||
@@ -140,7 +140,7 @@ exports.CodePointBuffer = CodePointBuffer;
|
||||
this.position = outOffset;
|
||||
}
|
||||
appendArrayChar(utf16In) {
|
||||
- assert(this.prevHighSurrogate === -1);
|
||||
+ assert.ok(this.prevHighSurrogate === -1);
|
||||
let input = utf16In;
|
||||
let inOffset = 0;
|
||||
let inLimit = utf16In.length;
|
||||
diff --git a/CodePointCharStream.js b/CodePointCharStream.js
|
||||
index 4c5398f24afdd378b36053391611404018925f71..e507525f0976219da6eae78136625b8b5a42db67 100644
|
||||
--- a/CodePointCharStream.js
|
||||
+++ b/CodePointCharStream.js
|
||||
@@ -28,7 +28,7 @@ class CodePointCharStream {
|
||||
// construct instances of this type.
|
||||
constructor(array, position, remaining, name) {
|
||||
// TODO
|
||||
- assert(position === 0);
|
||||
+ assert.ok(position === 0);
|
||||
this._array = array;
|
||||
this._size = remaining;
|
||||
this._name = name;
|
||||
@@ -55,7 +55,7 @@ class CodePointCharStream {
|
||||
}
|
||||
consume() {
|
||||
if (this._size - this._position === 0) {
|
||||
- assert(this.LA(1) === IntStream_1.IntStream.EOF);
|
||||
+ assert.ok(this.LA(1) === IntStream_1.IntStream.EOF);
|
||||
throw new RangeError("cannot consume EOF");
|
||||
}
|
||||
this._position++;
|
||||
diff --git a/atn/ATN.js b/atn/ATN.js
|
||||
index 0da2b8e836510546583685253ec828dbdaa0c1db..4d812a850b6b010576396e6e610f6df25cb585c9 100644
|
||||
--- a/atn/ATN.js
|
||||
+++ b/atn/ATN.js
|
||||
@@ -63,7 +63,7 @@ let ATN = class ATN {
|
||||
return PredictionContext_1.PredictionContext.getCachedContext(context, this.contextCache, new PredictionContext_1.PredictionContext.IdentityHashMap());
|
||||
}
|
||||
getDecisionToDFA() {
|
||||
- assert(this.decisionToDFA != null && this.decisionToDFA.length === this.decisionToState.length);
|
||||
+ assert.ok(this.decisionToDFA != null && this.decisionToDFA.length === this.decisionToState.length);
|
||||
return this.decisionToDFA;
|
||||
}
|
||||
nextTokens(s, ctx) {
|
||||
diff --git a/atn/ATNConfig.js b/atn/ATNConfig.js
|
||||
index 480d569b667f29437aeef8f2b9e6b0d3187c565f..bcacbc91ea61488f4b8e2ef40960c4f25a168758 100644
|
||||
--- a/atn/ATNConfig.js
|
||||
+++ b/atn/ATNConfig.js
|
||||
@@ -61,7 +61,7 @@ const SUPPRESS_PRECEDENCE_FILTER = 0x80000000;
|
||||
let ATNConfig = class ATNConfig {
|
||||
constructor(state, altOrConfig, context) {
|
||||
if (typeof altOrConfig === "number") {
|
||||
- assert((altOrConfig & 0xFFFFFF) === altOrConfig);
|
||||
+ assert.ok((altOrConfig & 0xFFFFFF) === altOrConfig);
|
||||
this._state = state;
|
||||
this.altAndOuterContextDepth = altOrConfig;
|
||||
this._context = context;
|
||||
@@ -120,7 +120,7 @@ let ATNConfig = class ATNConfig {
|
||||
return (this.altAndOuterContextDepth >>> 24) & 0x7F;
|
||||
}
|
||||
set outerContextDepth(outerContextDepth) {
|
||||
- assert(outerContextDepth >= 0);
|
||||
+ assert.ok(outerContextDepth >= 0);
|
||||
// saturate at 0x7F - everything but zero/positive is only used for debug information anyway
|
||||
outerContextDepth = Math.min(outerContextDepth, 0x7F);
|
||||
this.altAndOuterContextDepth = ((outerContextDepth << 24) | (this.altAndOuterContextDepth & ~0x7F000000) >>> 0);
|
||||
diff --git a/atn/ATNConfigSet.js b/atn/ATNConfigSet.js
|
||||
index 3ce0361c4ce7fef06b07a9a24c23251fd31dc0d1..f92be1dbeeed37a69b2aa3022ac5a7b7b29040f1 100644
|
||||
--- a/atn/ATNConfigSet.js
|
||||
+++ b/atn/ATNConfigSet.js
|
||||
@@ -125,7 +125,7 @@ class ATNConfigSet {
|
||||
if (this.outermostConfigSet && !outermostConfigSet) {
|
||||
throw new Error("IllegalStateException");
|
||||
}
|
||||
- assert(!outermostConfigSet || !this._dipsIntoOuterContext);
|
||||
+ assert.ok(!outermostConfigSet || !this._dipsIntoOuterContext);
|
||||
this.outermostConfigSet = outermostConfigSet;
|
||||
}
|
||||
getStates() {
|
||||
@@ -193,7 +193,7 @@ class ATNConfigSet {
|
||||
if (!this.mergedConfigs || !this.unmerged) {
|
||||
throw new Error("Covered by ensureWritable but duplicated here for strict null check limitation");
|
||||
}
|
||||
- assert(!this.outermostConfigSet || !e.reachesIntoOuterContext);
|
||||
+ assert.ok(!this.outermostConfigSet || !e.reachesIntoOuterContext);
|
||||
if (contextCache == null) {
|
||||
contextCache = PredictionContextCache_1.PredictionContextCache.UNCACHED;
|
||||
}
|
||||
@@ -247,7 +247,7 @@ class ATNConfigSet {
|
||||
updatePropertiesForMergedConfig(config) {
|
||||
// merged configs can't change the alt or semantic context
|
||||
this._dipsIntoOuterContext = this._dipsIntoOuterContext || config.reachesIntoOuterContext;
|
||||
- assert(!this.outermostConfigSet || !this._dipsIntoOuterContext);
|
||||
+ assert.ok(!this.outermostConfigSet || !this._dipsIntoOuterContext);
|
||||
}
|
||||
updatePropertiesForAddedConfig(config) {
|
||||
if (this.configs.length === 1) {
|
||||
@@ -258,7 +258,7 @@ class ATNConfigSet {
|
||||
}
|
||||
this._hasSemanticContext = this._hasSemanticContext || !SemanticContext_1.SemanticContext.NONE.equals(config.semanticContext);
|
||||
this._dipsIntoOuterContext = this._dipsIntoOuterContext || config.reachesIntoOuterContext;
|
||||
- assert(!this.outermostConfigSet || !this._dipsIntoOuterContext);
|
||||
+ assert.ok(!this.outermostConfigSet || !this._dipsIntoOuterContext);
|
||||
}
|
||||
canMerge(left, leftKey, right) {
|
||||
if (left.state.stateNumber !== right.state.stateNumber) {
|
||||
diff --git a/atn/LexerATNSimulator.js b/atn/LexerATNSimulator.js
|
||||
index d461d2063dddc78bbb15e56e5ae2559aadd3320d..c92994d52e226965e47a7e1fb28e8100252b289b 100644
|
||||
--- a/atn/LexerATNSimulator.js
|
||||
+++ b/atn/LexerATNSimulator.js
|
||||
@@ -258,7 +258,7 @@ let LexerATNSimulator = class LexerATNSimulator extends ATNSimulator_1.ATNSimula
|
||||
config = c.transform(target, true, lexerActionExecutor);
|
||||
}
|
||||
else {
|
||||
- assert(c.lexerActionExecutor == null);
|
||||
+ assert.ok(c.lexerActionExecutor == null);
|
||||
config = c.transform(target, true);
|
||||
}
|
||||
let treatEofAsEpsilon = t === IntStream_1.IntStream.EOF;
|
||||
@@ -543,7 +543,7 @@ let LexerATNSimulator = class LexerATNSimulator extends ATNSimulator_1.ATNSimula
|
||||
/* the lexer evaluates predicates on-the-fly; by this point configs
|
||||
* should not contain any configurations with unevaluated predicates.
|
||||
*/
|
||||
- assert(!configs.hasSemanticContext);
|
||||
+ assert.ok(!configs.hasSemanticContext);
|
||||
let proposed = new DFAState_1.DFAState(configs);
|
||||
let existing = this.atn.modeToDFA[this.mode].states.get(proposed);
|
||||
if (existing != null) {
|
||||
diff --git a/atn/ParserATNSimulator.js b/atn/ParserATNSimulator.js
|
||||
index c36395116d11c431b9f9ea5fea8afbc458bd0b50..0093ac18c7e31fe15bc0596e4f0886b199f41596 100644
|
||||
--- a/atn/ParserATNSimulator.js
|
||||
+++ b/atn/ParserATNSimulator.js
|
||||
@@ -307,7 +307,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
useContext = false;
|
||||
}
|
||||
let dfa = this.atn.decisionToDFA[decision];
|
||||
- assert(dfa != null);
|
||||
+ assert.ok(dfa != null);
|
||||
if (this.optimize_ll1 && !dfa.isPrecedenceDfa && !dfa.isEmpty) {
|
||||
let ll_1 = input.LA(1);
|
||||
if (ll_1 >= 0 && ll_1 <= 0xFFFF) {
|
||||
@@ -381,7 +381,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
return undefined;
|
||||
}
|
||||
let remainingContext = outerContext;
|
||||
- assert(outerContext != null);
|
||||
+ assert.ok(outerContext != null);
|
||||
let s0;
|
||||
if (dfa.isPrecedenceDfa) {
|
||||
s0 = dfa.getPrecedenceStartState(this._parser.precedence, true);
|
||||
@@ -393,7 +393,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
remainingContext = this.skipTailCalls(remainingContext);
|
||||
s0 = s0.getContextTarget(this.getReturnState(remainingContext));
|
||||
if (remainingContext.isEmpty) {
|
||||
- assert(s0 == null || !s0.isContextSensitive);
|
||||
+ assert.ok(s0 == null || !s0.isContextSensitive);
|
||||
}
|
||||
else {
|
||||
remainingContext = remainingContext.parent;
|
||||
@@ -433,7 +433,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
let initialState = new SimulatorState_1.SimulatorState(state.outerContext, s, state.useContext, remainingOuterContext);
|
||||
return this.execATN(dfa, input, startIndex, initialState);
|
||||
}
|
||||
- assert(remainingOuterContext != null);
|
||||
+ assert.ok(remainingOuterContext != null);
|
||||
remainingOuterContext = remainingOuterContext.parent;
|
||||
s = next;
|
||||
}
|
||||
@@ -456,7 +456,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
break;
|
||||
}
|
||||
// t is not updated if one of these states is reached
|
||||
- assert(!this.isAcceptState(s, state.useContext));
|
||||
+ assert.ok(!this.isAcceptState(s, state.useContext));
|
||||
// if no edge, pop over to ATN interpreter, update DFA and return
|
||||
let target = this.getExistingTargetState(s, t);
|
||||
if (target == null) {
|
||||
@@ -508,7 +508,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
//}
|
||||
}
|
||||
else {
|
||||
- assert(!state.useContext);
|
||||
+ assert.ok(!state.useContext);
|
||||
// Before attempting full context prediction, check to see if there are
|
||||
// disambiguating or validating predicates to evaluate which allow an
|
||||
// immediate decision
|
||||
@@ -664,9 +664,9 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
}
|
||||
let D = nextState.s0;
|
||||
// predicted alt => accept state
|
||||
- assert(D.isAcceptState || D.prediction === ATN_1.ATN.INVALID_ALT_NUMBER);
|
||||
+ assert.ok(D.isAcceptState || D.prediction === ATN_1.ATN.INVALID_ALT_NUMBER);
|
||||
// conflicted => accept state
|
||||
- assert(D.isAcceptState || D.configs.conflictInfo == null);
|
||||
+ assert.ok(D.isAcceptState || D.configs.conflictInfo == null);
|
||||
if (this.isAcceptState(D, useContext)) {
|
||||
let conflictingAlts = D.configs.conflictingAlts;
|
||||
let predictedAlt = conflictingAlts == null ? D.prediction : ATN_1.ATN.INVALID_ALT_NUMBER;
|
||||
@@ -731,8 +731,8 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
return predictedAlt;
|
||||
}
|
||||
else {
|
||||
- assert(!useContext);
|
||||
- assert(this.isAcceptState(D, false));
|
||||
+ assert.ok(!useContext);
|
||||
+ assert.ok(this.isAcceptState(D, false));
|
||||
if (ParserATNSimulator.debug) {
|
||||
console.log("RETRY with outerContext=" + outerContext);
|
||||
}
|
||||
@@ -877,12 +877,12 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
if (next == null) {
|
||||
break;
|
||||
}
|
||||
- assert(remainingGlobalContext != null);
|
||||
+ assert.ok(remainingGlobalContext != null);
|
||||
remainingGlobalContext = remainingGlobalContext.parent;
|
||||
s = next;
|
||||
}
|
||||
}
|
||||
- assert(!this.isAcceptState(s, useContext));
|
||||
+ assert.ok(!this.isAcceptState(s, useContext));
|
||||
if (this.isAcceptState(s, useContext)) {
|
||||
return new SimulatorState_1.SimulatorState(previous.outerContext, s, useContext, remainingGlobalContext);
|
||||
}
|
||||
@@ -896,7 +896,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
if (target === ATNSimulator_1.ATNSimulator.ERROR) {
|
||||
return undefined;
|
||||
}
|
||||
- assert(!useContext || !target.configs.dipsIntoOuterContext);
|
||||
+ assert.ok(!useContext || !target.configs.dipsIntoOuterContext);
|
||||
return new SimulatorState_1.SimulatorState(previous.outerContext, target, useContext, remainingGlobalContext);
|
||||
}
|
||||
/**
|
||||
@@ -955,7 +955,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
console.log("testing " + this.getTokenName(t) + " at " + c.toString());
|
||||
}
|
||||
if (c.state instanceof RuleStopState_1.RuleStopState) {
|
||||
- assert(c.context.isEmpty);
|
||||
+ assert.ok(c.context.isEmpty);
|
||||
if (useContext && !c.reachesIntoOuterContext || t === IntStream_1.IntStream.EOF) {
|
||||
if (skippedStopStates == null) {
|
||||
skippedStopStates = [];
|
||||
@@ -1018,7 +1018,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
* multiple alternatives are viable.
|
||||
*/
|
||||
if (skippedStopStates != null && (!useContext || !PredictionMode_1.PredictionMode.hasConfigInRuleStopState(reach))) {
|
||||
- assert(skippedStopStates.length > 0);
|
||||
+ assert.ok(skippedStopStates.length > 0);
|
||||
for (let c of skippedStopStates) {
|
||||
reach.add(c, contextCache);
|
||||
}
|
||||
@@ -1382,7 +1382,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
for (let i = 1; i < altToPred.length; i++) {
|
||||
let pred = altToPred[i];
|
||||
// unpredicated is indicated by SemanticContext.NONE
|
||||
- assert(pred != null);
|
||||
+ assert.ok(pred != null);
|
||||
// find first unpredicated but ambig alternative, if any.
|
||||
// Only ambiguous alternatives will have SemanticContext.NONE.
|
||||
// Any unambig alts or ambig naked alts after first ambig naked are ignored
|
||||
@@ -1497,7 +1497,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
// Make sure we track that we are now out of context.
|
||||
c.outerContextDepth = config.outerContextDepth;
|
||||
c.isPrecedenceFilterSuppressed = config.isPrecedenceFilterSuppressed;
|
||||
- assert(depth > MIN_INTEGER_VALUE);
|
||||
+ assert.ok(depth > MIN_INTEGER_VALUE);
|
||||
this.closureImpl(c, configs, intermediate, closureBusy, collectPredicates, hasMoreContexts, contextCache, depth - 1, treatEofAsEpsilon);
|
||||
}
|
||||
if (!hasEmpty || !hasMoreContexts) {
|
||||
@@ -1587,7 +1587,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
// avoid infinite recursion for right-recursive rules
|
||||
continue;
|
||||
}
|
||||
- assert(newDepth > MIN_INTEGER_VALUE);
|
||||
+ assert.ok(newDepth > MIN_INTEGER_VALUE);
|
||||
newDepth--;
|
||||
if (ParserATNSimulator.debug) {
|
||||
console.log("dips into outer ctx: " + c);
|
||||
@@ -1595,7 +1595,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
}
|
||||
else if (t instanceof RuleTransition_1.RuleTransition) {
|
||||
if (this.optimize_tail_calls && t.optimizedTailCall && (!this.tail_call_preserves_sll || !PredictionContext_1.PredictionContext.isEmptyLocal(config.context))) {
|
||||
- assert(c.context === config.context);
|
||||
+ assert.ok(c.context === config.context);
|
||||
if (newDepth === 0) {
|
||||
// the pop/push of a tail call would keep the depth
|
||||
// constant, except we latch if it goes negative
|
||||
@@ -1926,7 +1926,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
return false;
|
||||
}
|
||||
addDFAEdge(dfa, fromState, t, contextTransitions, toConfigs, contextCache) {
|
||||
- assert(contextTransitions == null || contextTransitions.isEmpty || dfa.isContextSensitive);
|
||||
+ assert.ok(contextTransitions == null || contextTransitions.isEmpty || dfa.isContextSensitive);
|
||||
let from = fromState;
|
||||
let to = this.addDFAState(dfa, toConfigs, contextCache);
|
||||
if (contextTransitions != null) {
|
||||
@@ -1944,7 +1944,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
continue;
|
||||
}
|
||||
next = this.addDFAContextState(dfa, from.configs, context, contextCache);
|
||||
- assert(context !== PredictionContext_1.PredictionContext.EMPTY_FULL_STATE_KEY || next.configs.isOutermostConfigSet);
|
||||
+ assert.ok(context !== PredictionContext_1.PredictionContext.EMPTY_FULL_STATE_KEY || next.configs.isOutermostConfigSet);
|
||||
from.setContextTarget(context, next);
|
||||
from = next;
|
||||
}
|
||||
@@ -1973,7 +1973,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
return this.addDFAState(dfa, contextConfigs, contextCache);
|
||||
}
|
||||
else {
|
||||
- assert(!configs.isOutermostConfigSet, "Shouldn't be adding a duplicate edge.");
|
||||
+ assert.ok(!configs.isOutermostConfigSet, "Shouldn't be adding a duplicate edge.");
|
||||
configs = configs.clone(true);
|
||||
configs.isOutermostConfigSet = true;
|
||||
return this.addDFAState(dfa, configs, contextCache);
|
||||
@@ -2081,7 +2081,7 @@ let ParserATNSimulator = class ParserATNSimulator extends ATNSimulator_1.ATNSimu
|
||||
}
|
||||
while (!context.isEmpty) {
|
||||
let state = this.atn.states[context.invokingState];
|
||||
- assert(state.numberOfTransitions === 1 && state.transition(0).serializationType === 3 /* RULE */);
|
||||
+ assert.ok(state.numberOfTransitions === 1 && state.transition(0).serializationType === 3 /* RULE */);
|
||||
let transition = state.transition(0);
|
||||
if (!transition.tailCall) {
|
||||
break;
|
||||
diff --git a/atn/PredictionContext.js b/atn/PredictionContext.js
|
||||
index 47d525fde0ca117193dd2b1cd2685420c23683d6..b269295802fc84b7cf7e1ce055cdba0a0c03ec53 100644
|
||||
--- a/atn/PredictionContext.js
|
||||
+++ b/atn/PredictionContext.js
|
||||
@@ -118,7 +118,7 @@ class PredictionContext {
|
||||
leftIndex++;
|
||||
}
|
||||
else {
|
||||
- assert(context1.getReturnState(rightIndex) < context0.getReturnState(leftIndex));
|
||||
+ assert.ok(context1.getReturnState(rightIndex) < context0.getReturnState(leftIndex));
|
||||
parentsList[count] = context1.getParent(rightIndex);
|
||||
returnStatesList[count] = context1.getReturnState(rightIndex);
|
||||
canReturnLeft = false;
|
||||
@@ -374,8 +374,8 @@ __decorate([
|
||||
let ArrayPredictionContext = class ArrayPredictionContext extends PredictionContext {
|
||||
constructor(parents, returnStates, hashCode) {
|
||||
super(hashCode || PredictionContext.calculateHashCode(parents, returnStates));
|
||||
- assert(parents.length === returnStates.length);
|
||||
- assert(returnStates.length > 1 || returnStates[0] !== PredictionContext.EMPTY_FULL_STATE_KEY, "Should be using PredictionContext.EMPTY instead.");
|
||||
+ assert.ok(parents.length === returnStates.length);
|
||||
+ assert.ok(returnStates.length > 1 || returnStates[0] !== PredictionContext.EMPTY_FULL_STATE_KEY, "Should be using PredictionContext.EMPTY instead.");
|
||||
this.parents = parents;
|
||||
this.returnStates = returnStates;
|
||||
}
|
||||
@@ -458,7 +458,7 @@ let ArrayPredictionContext = class ArrayPredictionContext extends PredictionCont
|
||||
result = new SingletonPredictionContext(updatedParents[0], updatedReturnStates[0]);
|
||||
}
|
||||
else {
|
||||
- assert(updatedParents.length > 1);
|
||||
+ assert.ok(updatedParents.length > 1);
|
||||
result = new ArrayPredictionContext(updatedParents, updatedReturnStates);
|
||||
}
|
||||
if (context.hasEmpty) {
|
||||
@@ -569,16 +569,16 @@ ArrayPredictionContext = __decorate([
|
||||
let SingletonPredictionContext = class SingletonPredictionContext extends PredictionContext {
|
||||
constructor(parent, returnState) {
|
||||
super(PredictionContext.calculateSingleHashCode(parent, returnState));
|
||||
- // assert(returnState != PredictionContext.EMPTY_FULL_STATE_KEY && returnState != PredictionContext.EMPTY_LOCAL_STATE_KEY);
|
||||
+ // assert.ok(returnState != PredictionContext.EMPTY_FULL_STATE_KEY && returnState != PredictionContext.EMPTY_LOCAL_STATE_KEY);
|
||||
this.parent = parent;
|
||||
this.returnState = returnState;
|
||||
}
|
||||
getParent(index) {
|
||||
- // assert(index == 0);
|
||||
+ // assert.ok(index == 0);
|
||||
return this.parent;
|
||||
}
|
||||
getReturnState(index) {
|
||||
- // assert(index == 0);
|
||||
+ // assert.ok(index == 0);
|
||||
return this.returnState;
|
||||
}
|
||||
findReturnState(returnState) {
|
||||
diff --git a/atn/PredictionContextCache.js b/atn/PredictionContextCache.js
|
||||
index d919815854f0519b2b602a316f93f702f06c9754..ecd697a2b7141ebf5c76198bb49088cff90c4d35 100644
|
||||
--- a/atn/PredictionContextCache.js
|
||||
+++ b/atn/PredictionContextCache.js
|
||||
@@ -104,8 +104,8 @@ PredictionContextCache.UNCACHED = new PredictionContextCache(false);
|
||||
PredictionContextCache.PredictionContextAndInt = PredictionContextAndInt;
|
||||
class IdentityCommutativePredictionContextOperands {
|
||||
constructor(x, y) {
|
||||
- assert(x != null);
|
||||
- assert(y != null);
|
||||
+ assert.ok(x != null);
|
||||
+ assert.ok(y != null);
|
||||
this._x = x;
|
||||
this._y = y;
|
||||
}
|
||||
diff --git a/dfa/DFAState.js b/dfa/DFAState.js
|
||||
index dcdd796eef9a8046033b233d6cc2ca33b198cb9d..d7a095dcc5680d1af58e6e213ebaed98eae4c1b1 100644
|
||||
--- a/dfa/DFAState.js
|
||||
+++ b/dfa/DFAState.js
|
||||
@@ -66,11 +66,11 @@ class DFAState {
|
||||
return this.contextSymbols.get(symbol);
|
||||
}
|
||||
setContextSymbol(symbol) {
|
||||
- assert(this.isContextSensitive);
|
||||
+ assert.ok(this.isContextSensitive);
|
||||
this.contextSymbols.set(symbol);
|
||||
}
|
||||
setContextSensitive(atn) {
|
||||
- assert(!this.configs.isOutermostConfigSet);
|
||||
+ assert.ok(!this.configs.isOutermostConfigSet);
|
||||
if (this.isContextSensitive) {
|
||||
return;
|
||||
}
|
||||
diff --git a/misc/Array2DHashSet.js b/misc/Array2DHashSet.js
|
||||
index 5e9b5dca143df940562734ce158c532a48fed78d..3796235c05d771f985a3e6d5cd9f5f8116188a5f 100644
|
||||
--- a/misc/Array2DHashSet.js
|
||||
+++ b/misc/Array2DHashSet.js
|
||||
@@ -153,7 +153,7 @@ class Array2DHashSet {
|
||||
newBucket.push(o);
|
||||
}
|
||||
}
|
||||
- assert(this.n === oldSize);
|
||||
+ assert.ok(this.n === oldSize);
|
||||
}
|
||||
add(t) {
|
||||
let existing = this.getOrAdd(t);
|
||||
@@ -0,0 +1,12 @@
|
||||
diff --git a/build/esm/index.d.ts b/build/esm/index.d.ts
|
||||
index f126d758bb0d2216fc2a3759c538fa15a741217b..54d6893aac1285fb1d78d854c1ab400496327570 100644
|
||||
--- a/build/esm/index.d.ts
|
||||
+++ b/build/esm/index.d.ts
|
||||
@@ -2,7 +2,6 @@
|
||||
import { encodePacket } from "./encodePacket.js";
|
||||
import { decodePacket } from "./decodePacket.js";
|
||||
import { Packet, PacketType, RawData, BinaryType } from "./commons.js";
|
||||
-import type { TransformStream } from "node:stream/web";
|
||||
declare const encodePayload: (packets: Packet[], callback: (encodedPayload: string) => void) => void;
|
||||
declare const decodePayload: (encodedPayload: string, binaryType?: BinaryType) => Packet[];
|
||||
export declare function createPacketEncoderStream(): TransformStream<Packet, any>;
|
||||
@@ -0,0 +1,27 @@
|
||||
diff --git a/dist/sql/getJob.js b/dist/sql/getJob.js
|
||||
index 70cc9b49d7d08c8dd32214f15c463b2a568abd15..5bcb50a4544046e56f6d5dd70e96e26e59998ad5 100644
|
||||
--- a/dist/sql/getJob.js
|
||||
+++ b/dist/sql/getJob.js
|
||||
@@ -61,7 +61,7 @@ async function getJob(compiledSharedOptions, withPgClient, tasks, workerId, flag
|
||||
*
|
||||
* I recommend you either use strat 0 if you can, or strat 2 otherwise.
|
||||
*/
|
||||
- const strategy = 2;
|
||||
+ const strategy = 0;
|
||||
const queueClause = strategy === 0
|
||||
? `and jobs.job_queue_id is null`
|
||||
: strategy === 1
|
||||
@@ -153,6 +153,13 @@ with j as (
|
||||
const name = !preparedStatements
|
||||
? undefined
|
||||
: `get_job${hasFlags ? "F" : ""}${useNodeTime ? "N" : ""}/${workerSchema}`;
|
||||
+
|
||||
+ logger.debug("Running getJob query...", {
|
||||
+ text,
|
||||
+ values,
|
||||
+ name
|
||||
+ });
|
||||
+
|
||||
const { rows: [jobRow], } = await withPgClient.withRetries((client) => client.query({
|
||||
text,
|
||||
values,
|
||||
@@ -0,0 +1,15 @@
|
||||
diff --git a/CHANGELOG.md b/CHANGELOG.md
|
||||
deleted file mode 100644
|
||||
index 8700963f5c9ec9fc1fdc53846846130bfc2f2108..0000000000000000000000000000000000000000
|
||||
diff --git a/package.json b/package.json
|
||||
index 606d1775fb0c11aab4918c50d20d72bce1684158..45e6d46410792ef273d7d2b2bc92cd5964a3eef5 100644
|
||||
--- a/package.json
|
||||
+++ b/package.json
|
||||
@@ -15,6 +15,7 @@
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
+ "types": "./dist/index.d.ts",
|
||||
"import": "./dist/esm/index.js",
|
||||
"require": "./dist/cjs/index.js"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user