@wcstack/state 1.24.0 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +262 -129
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -7102,7 +7102,7 @@ async function buildBindings(root) {
|
|
|
7102
7102
|
}
|
|
7103
7103
|
}
|
|
7104
7104
|
|
|
7105
|
-
var version = "1.
|
|
7105
|
+
var version = "1.25.0";
|
|
7106
7106
|
var pkg = {
|
|
7107
7107
|
version: version};
|
|
7108
7108
|
|
|
@@ -9970,6 +9970,108 @@ function setSwapInfoByAddress(address, swapInfo) {
|
|
|
9970
9970
|
}
|
|
9971
9971
|
}
|
|
9972
9972
|
|
|
9973
|
+
/**
|
|
9974
|
+
* topologicalRank.ts — 依存グラフ(パス単位)のトポロジカル順位。
|
|
9975
|
+
*
|
|
9976
|
+
* 依存ウォークは list → list.* を展開するために途中でリスト実体を読む。この読み取りが
|
|
9977
|
+
* 正しい値を返すには「そのパスの入力(先行パス)がすべて dirty 化済み」である必要がある。
|
|
9978
|
+
* DFS ではダイヤモンド依存で片腕しか dirty 化していない段階で合流点を評価してしまうため、
|
|
9979
|
+
* パス単位の rank(= 最長経路長)を先に求め、rank の昇順で訪問する。
|
|
9980
|
+
*
|
|
9981
|
+
* rank の定義から、辺 (u → v) が存在すれば必ず rank(u) < rank(v) となる。したがって
|
|
9982
|
+
* rank r のバケットを処理する時点で rank < r のパスはすべて訪問(dirty 化)済みであり、
|
|
9983
|
+
* 同じバケット内のパス同士は互いに先行関係を持たない。
|
|
9984
|
+
*
|
|
9985
|
+
* 値を読まないグラフ走査なので、ウォーク 1 回あたりの追加コストは実測で誤差に
|
|
9986
|
+
* 収まる(メモ化しても差が出なかったため、キャッシュは持たない)。
|
|
9987
|
+
*/
|
|
9988
|
+
function getTopologicalRanks(startPath, staticMap, dynamicMap, maxDepth) {
|
|
9989
|
+
// 1) startPath から到達可能なパス部分グラフと入次数を求める(値は一切読まない)
|
|
9990
|
+
const adjacency = new Map();
|
|
9991
|
+
const inDegree = new Map();
|
|
9992
|
+
const pending = [startPath];
|
|
9993
|
+
inDegree.set(startPath, 0);
|
|
9994
|
+
while (pending.length > 0) {
|
|
9995
|
+
const path = pending.pop();
|
|
9996
|
+
if (adjacency.has(path)) {
|
|
9997
|
+
continue;
|
|
9998
|
+
}
|
|
9999
|
+
const staticDeps = staticMap.get(path);
|
|
10000
|
+
const dynamicDeps = dynamicMap.get(path);
|
|
10001
|
+
let deps;
|
|
10002
|
+
if (staticDeps === undefined) {
|
|
10003
|
+
deps = dynamicDeps ?? [];
|
|
10004
|
+
}
|
|
10005
|
+
else if (dynamicDeps === undefined) {
|
|
10006
|
+
deps = staticDeps;
|
|
10007
|
+
}
|
|
10008
|
+
else {
|
|
10009
|
+
deps = staticDeps.concat(dynamicDeps);
|
|
10010
|
+
}
|
|
10011
|
+
adjacency.set(path, deps);
|
|
10012
|
+
for (let i = 0; i < deps.length; i++) {
|
|
10013
|
+
const dep = deps[i];
|
|
10014
|
+
inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);
|
|
10015
|
+
if (!adjacency.has(dep)) {
|
|
10016
|
+
pending.push(dep);
|
|
10017
|
+
}
|
|
10018
|
+
}
|
|
10019
|
+
}
|
|
10020
|
+
// 2) Kahn 法。rank は最長経路長(rank[v] = max(rank[u]) + 1)。
|
|
10021
|
+
// 入次数が 0 に落ちて queue に入ったパスだけが「確定」で、緩和の途中で
|
|
10022
|
+
// 暫定値が入っただけのパス(= 循環の一部)は確定扱いにしない。
|
|
10023
|
+
const ranks = new Map();
|
|
10024
|
+
const settled = new Set();
|
|
10025
|
+
const queue = [];
|
|
10026
|
+
for (const [path, degree] of inDegree) {
|
|
10027
|
+
if (degree === 0) {
|
|
10028
|
+
ranks.set(path, 0);
|
|
10029
|
+
settled.add(path);
|
|
10030
|
+
queue.push(path);
|
|
10031
|
+
}
|
|
10032
|
+
}
|
|
10033
|
+
for (let i = 0; i < queue.length; i++) {
|
|
10034
|
+
const path = queue[i];
|
|
10035
|
+
const nextRank = ranks.get(path) + 1;
|
|
10036
|
+
if (nextRank > maxDepth) {
|
|
10037
|
+
raiseError(`Maximum dependency depth of ${maxDepth} exceeded. Possible circular dependency detected at path: ${path}`);
|
|
10038
|
+
}
|
|
10039
|
+
const deps = adjacency.get(path);
|
|
10040
|
+
for (let j = 0; j < deps.length; j++) {
|
|
10041
|
+
const dep = deps[j];
|
|
10042
|
+
if (nextRank > (ranks.get(dep) ?? -1)) {
|
|
10043
|
+
ranks.set(dep, nextRank);
|
|
10044
|
+
}
|
|
10045
|
+
const remaining = inDegree.get(dep) - 1;
|
|
10046
|
+
inDegree.set(dep, remaining);
|
|
10047
|
+
if (remaining === 0) {
|
|
10048
|
+
settled.add(dep);
|
|
10049
|
+
queue.push(dep);
|
|
10050
|
+
}
|
|
10051
|
+
}
|
|
10052
|
+
}
|
|
10053
|
+
// 3) 循環に含まれるパスは rank が決まらない(入次数が 0 に落ちない)。
|
|
10054
|
+
// そもそも正しい評価順が存在しないので、順序保証を諦めて確定済みの
|
|
10055
|
+
// 最大 rank の次にまとめる。打ち切りは従来どおり visited が担う。
|
|
10056
|
+
// 暫定値が残っていると確定パスとの前後関係を誤って表すため、必ず上書きする。
|
|
10057
|
+
if (settled.size !== adjacency.size) {
|
|
10058
|
+
let maxRank = -1;
|
|
10059
|
+
for (const path of settled) {
|
|
10060
|
+
const rank = ranks.get(path);
|
|
10061
|
+
if (rank > maxRank) {
|
|
10062
|
+
maxRank = rank;
|
|
10063
|
+
}
|
|
10064
|
+
}
|
|
10065
|
+
const cycleRank = maxRank + 1;
|
|
10066
|
+
for (const path of adjacency.keys()) {
|
|
10067
|
+
if (!settled.has(path)) {
|
|
10068
|
+
ranks.set(path, cycleRank);
|
|
10069
|
+
}
|
|
10070
|
+
}
|
|
10071
|
+
}
|
|
10072
|
+
return ranks;
|
|
10073
|
+
}
|
|
10074
|
+
|
|
9973
10075
|
const MAX_DEPENDENCY_DEPTH = 1000;
|
|
9974
10076
|
function getIndexes(listDiff, searchType) {
|
|
9975
10077
|
switch (searchType) {
|
|
@@ -10076,152 +10178,178 @@ function getMovedRowExpansionPaths(context, wildcardPath, depPathInfo) {
|
|
|
10076
10178
|
return result ?? EMPTY_PATH_INFOS;
|
|
10077
10179
|
}
|
|
10078
10180
|
function _walkDependency(context, startAddress, callback) {
|
|
10079
|
-
|
|
10080
|
-
|
|
10081
|
-
|
|
10082
|
-
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10181
|
+
// rank ごとのバケットで訪問する。辺 (u → v) では必ず rank(u) < rank(v) なので、
|
|
10182
|
+
// バケット r を処理する時点で rank < r のパスは全て dirty 化済みになる
|
|
10183
|
+
// = ここでリスト実体を読んでも入力が揃っている(topologicalRank.ts 参照)。
|
|
10184
|
+
const buckets = [];
|
|
10185
|
+
const ranks = context.ranks;
|
|
10186
|
+
const enqueue = (address, minRank) => {
|
|
10187
|
+
let rank = ranks.get(address.pathInfo.path) ?? minRank;
|
|
10188
|
+
if (rank < minRank) {
|
|
10189
|
+
// 循環など rank が先行関係を表せないケース。現在のバケットに載せて
|
|
10190
|
+
// 同一ループ内で処理する(打ち切りは visited が担う)。
|
|
10191
|
+
rank = minRank;
|
|
10192
|
+
}
|
|
10193
|
+
(buckets[rank] ??= []).push(address);
|
|
10194
|
+
};
|
|
10195
|
+
enqueue(startAddress, 0);
|
|
10196
|
+
// 依存アドレスを収集するための一時バッファ(アドレスごとに使い回す)
|
|
10197
|
+
const nextEntries = [];
|
|
10198
|
+
for (let rank = 0; rank < buckets.length; rank++) {
|
|
10199
|
+
const bucket = buckets[rank];
|
|
10200
|
+
if (bucket === undefined) {
|
|
10086
10201
|
continue;
|
|
10087
10202
|
}
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
10110
|
-
|
|
10111
|
-
|
|
10112
|
-
|
|
10113
|
-
|
|
10114
|
-
|
|
10203
|
+
// 同一バケットへの push(循環時)で伸びるため length は都度読む
|
|
10204
|
+
for (let cursor = 0; cursor < bucket.length; cursor++) {
|
|
10205
|
+
const address = bucket[cursor];
|
|
10206
|
+
if (context.visited.has(address)) {
|
|
10207
|
+
continue;
|
|
10208
|
+
}
|
|
10209
|
+
context.visited.add(address);
|
|
10210
|
+
callback(address);
|
|
10211
|
+
nextEntries.length = 0;
|
|
10212
|
+
_collectDependencies(context, address, nextEntries);
|
|
10213
|
+
for (let i = 0; i < nextEntries.length; i++) {
|
|
10214
|
+
enqueue(nextEntries[i], rank + 1);
|
|
10215
|
+
}
|
|
10216
|
+
}
|
|
10217
|
+
}
|
|
10218
|
+
}
|
|
10219
|
+
/**
|
|
10220
|
+
* address の依存アドレスを nextEntries に集め、context.result にも登録する。
|
|
10221
|
+
* リスト展開(list → list.*)と動的依存のワイルドカード展開はここで値を読むが、
|
|
10222
|
+
* 呼び出し元がトポロジカル順を保証しているため入力は揃っている。
|
|
10223
|
+
*/
|
|
10224
|
+
function _collectDependencies(context, address, nextEntries) {
|
|
10225
|
+
const sourcePath = address.pathInfo.path;
|
|
10226
|
+
/**
|
|
10227
|
+
* パスから依存関係をたどる
|
|
10228
|
+
* users.*.name <= users.* <= users
|
|
10229
|
+
* ただし、users がリストであれば users.* の依存関係は展開する
|
|
10230
|
+
*/
|
|
10231
|
+
const staticDeps = context.staticMap.get(sourcePath);
|
|
10232
|
+
if (staticDeps) {
|
|
10233
|
+
for (const dep of staticDeps) {
|
|
10234
|
+
const depPathInfo = getPathInfo(dep);
|
|
10235
|
+
if (context.listPathSet.has(sourcePath) && depPathInfo.lastSegment === WILDCARD) {
|
|
10236
|
+
//expand indexes
|
|
10237
|
+
const newValue = context.stateProxy[getByAddressSymbol](address);
|
|
10238
|
+
const absPathInfo = getAbsolutePathInfo(context.stateElement, address.pathInfo);
|
|
10239
|
+
const absAddress = createAbsoluteStateAddress(absPathInfo, address.listIndex);
|
|
10240
|
+
const lastValue = getLastListValueByAbsoluteStateAddress(absAddress);
|
|
10241
|
+
const listDiff = createListDiff(address.listIndex, lastValue, newValue);
|
|
10242
|
+
const selection = selectExpansionIndexes(context, sourcePath, lastValue, newValue, listDiff);
|
|
10243
|
+
for (const listIndex of selection.fullRows) {
|
|
10244
|
+
const depAddress = createStateAddress(depPathInfo, listIndex);
|
|
10245
|
+
context.result.add(depAddress);
|
|
10246
|
+
nextEntries.push(depAddress);
|
|
10247
|
+
}
|
|
10248
|
+
if (selection.movedRows !== null) {
|
|
10249
|
+
const movedPathInfos = getMovedRowExpansionPaths(context, dep, depPathInfo);
|
|
10250
|
+
if (movedPathInfos === null) {
|
|
10251
|
+
// ネスト配下に index 依存 getter: 安全側で行全体を展開(従来挙動)
|
|
10252
|
+
for (const listIndex of selection.movedRows) {
|
|
10253
|
+
const depAddress = createStateAddress(depPathInfo, listIndex);
|
|
10254
|
+
context.result.add(depAddress);
|
|
10255
|
+
nextEntries.push(depAddress);
|
|
10256
|
+
}
|
|
10115
10257
|
}
|
|
10116
|
-
if (
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
const depAddress = createStateAddress(depPathInfo, listIndex);
|
|
10258
|
+
else if (movedPathInfos.length > 0) {
|
|
10259
|
+
// 位置のみ変わった行は index 依存 getter のパスだけを展開する
|
|
10260
|
+
for (const listIndex of selection.movedRows) {
|
|
10261
|
+
for (const pathInfo of movedPathInfos) {
|
|
10262
|
+
const depAddress = createStateAddress(pathInfo, listIndex);
|
|
10122
10263
|
context.result.add(depAddress);
|
|
10123
|
-
nextEntries.push(
|
|
10124
|
-
}
|
|
10125
|
-
}
|
|
10126
|
-
else if (movedPathInfos.length > 0) {
|
|
10127
|
-
// 位置のみ変わった行は index 依存 getter のパスだけを展開する
|
|
10128
|
-
for (const listIndex of selection.movedRows) {
|
|
10129
|
-
for (const pathInfo of movedPathInfos) {
|
|
10130
|
-
const depAddress = createStateAddress(pathInfo, listIndex);
|
|
10131
|
-
context.result.add(depAddress);
|
|
10132
|
-
nextEntries.push({ address: depAddress, depth: nextDepth });
|
|
10133
|
-
}
|
|
10264
|
+
nextEntries.push(depAddress);
|
|
10134
10265
|
}
|
|
10135
10266
|
}
|
|
10136
|
-
// movedPathInfos が空: index を読む getter が subtree に無い =
|
|
10137
|
-
// 位置のみ変わった行の値は不変。展開・dirty 化とも不要。
|
|
10138
10267
|
}
|
|
10268
|
+
// movedPathInfos が空: index を読む getter が subtree に無い =
|
|
10269
|
+
// 位置のみ変わった行の値は不変。展開・dirty 化とも不要。
|
|
10139
10270
|
}
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10271
|
+
}
|
|
10272
|
+
else {
|
|
10273
|
+
const depAddress = createStateAddress(depPathInfo, address.listIndex);
|
|
10274
|
+
context.result.add(depAddress);
|
|
10275
|
+
nextEntries.push(depAddress);
|
|
10145
10276
|
}
|
|
10146
10277
|
}
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
|
|
10162
|
-
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
raiseError(`Cannot expand dynamic dependency with wildcard for non-list address: ${address.pathInfo.path}`);
|
|
10181
|
-
}
|
|
10182
|
-
listIndex = address.listIndex.at(wildcardLen - 1);
|
|
10183
|
-
}
|
|
10184
|
-
else {
|
|
10185
|
-
// selectedIndex => items.*.selected
|
|
10186
|
-
// 同じ親を持たない場合はnullから開始
|
|
10187
|
-
listIndex = null;
|
|
10188
|
-
}
|
|
10189
|
-
const expandContext = {
|
|
10190
|
-
stateElement: context.stateElement,
|
|
10191
|
-
targetListIndexes: [],
|
|
10192
|
-
wildcardPaths: depPathInfo.wildcardPaths,
|
|
10193
|
-
wildcardParentPaths: depPathInfo.wildcardParentPaths,
|
|
10194
|
-
stateProxy: context.stateProxy,
|
|
10195
|
-
searchType: context.searchType,
|
|
10196
|
-
};
|
|
10197
|
-
_walkExpandWildcard(expandContext, wildcardLen, listIndex);
|
|
10198
|
-
listIndexes.push(...expandContext.targetListIndexes);
|
|
10199
|
-
}
|
|
10200
|
-
else {
|
|
10201
|
-
// products.*.price => products.*.tax
|
|
10202
|
-
// ワイルドカードを含む同じ親(products.*)を持つので、リストインデックスは引き継ぐ
|
|
10278
|
+
}
|
|
10279
|
+
/**
|
|
10280
|
+
* 動的依存関係をたどる
|
|
10281
|
+
* 動的依存関係は、getterの実行時に決定される
|
|
10282
|
+
*
|
|
10283
|
+
* source, target
|
|
10284
|
+
*
|
|
10285
|
+
* products.*.price => products.*.tax
|
|
10286
|
+
* get "products.*.tax"() { return this["products.*.price"] * 0.1; }
|
|
10287
|
+
*
|
|
10288
|
+
* products.*.price => products.summary
|
|
10289
|
+
* get "products.summary"() { return this.$getAll("products.*.price", []).reduce(sum); }
|
|
10290
|
+
*
|
|
10291
|
+
* categories.*.name => categories.*.products.*.categoryName
|
|
10292
|
+
* get "categories.*.products.*.categoryName"() { return this["categories.*.name"]; }
|
|
10293
|
+
*/
|
|
10294
|
+
const dynamicDeps = context.dynamicMap.get(sourcePath);
|
|
10295
|
+
if (dynamicDeps) {
|
|
10296
|
+
for (const dep of dynamicDeps) {
|
|
10297
|
+
const depPathInfo = getPathInfo(dep);
|
|
10298
|
+
const listIndexes = [];
|
|
10299
|
+
if (depPathInfo.wildcardCount > 0) {
|
|
10300
|
+
// ワイルドカードを含む依存関係の処理
|
|
10301
|
+
// 同じ親を持つかをパスの集合積で判定する
|
|
10302
|
+
// polyfills.tsにてSetのintersectionメソッドを定義している
|
|
10303
|
+
const wildcardLen = calcWildcardLen(address.pathInfo, depPathInfo);
|
|
10304
|
+
const expandable = (depPathInfo.wildcardCount - wildcardLen) >= 1;
|
|
10305
|
+
if (expandable) {
|
|
10306
|
+
let listIndex;
|
|
10307
|
+
if (wildcardLen > 0) {
|
|
10308
|
+
// categories.*.name => categories.*.products.*.categoryName
|
|
10309
|
+
// ワイルドカードを含む同じ親(products.*)を持つのが、
|
|
10310
|
+
// さらに下位にワイルドカードがあるので展開する
|
|
10203
10311
|
if (address.listIndex === null) {
|
|
10204
10312
|
raiseError(`Cannot expand dynamic dependency with wildcard for non-list address: ${address.pathInfo.path}`);
|
|
10205
10313
|
}
|
|
10206
|
-
|
|
10207
|
-
listIndexes.push(listIndex);
|
|
10314
|
+
listIndex = address.listIndex.at(wildcardLen - 1);
|
|
10208
10315
|
}
|
|
10316
|
+
else {
|
|
10317
|
+
// selectedIndex => items.*.selected
|
|
10318
|
+
// 同じ親を持たない場合はnullから開始
|
|
10319
|
+
listIndex = null;
|
|
10320
|
+
}
|
|
10321
|
+
const expandContext = {
|
|
10322
|
+
stateName: context.stateName,
|
|
10323
|
+
stateElement: context.stateElement,
|
|
10324
|
+
targetListIndexes: [],
|
|
10325
|
+
wildcardPaths: depPathInfo.wildcardPaths,
|
|
10326
|
+
wildcardParentPaths: depPathInfo.wildcardParentPaths,
|
|
10327
|
+
stateProxy: context.stateProxy,
|
|
10328
|
+
searchType: context.searchType,
|
|
10329
|
+
};
|
|
10330
|
+
_walkExpandWildcard(expandContext, wildcardLen, listIndex);
|
|
10331
|
+
listIndexes.push(...expandContext.targetListIndexes);
|
|
10209
10332
|
}
|
|
10210
10333
|
else {
|
|
10211
|
-
// products.*.
|
|
10212
|
-
//
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
const
|
|
10217
|
-
|
|
10218
|
-
nextEntries.push({ address: depAddress, depth: nextDepth });
|
|
10334
|
+
// products.*.price => products.*.tax
|
|
10335
|
+
// ワイルドカードを含む同じ親(products.*)を持つので、リストインデックスは引き継ぐ
|
|
10336
|
+
if (address.listIndex === null) {
|
|
10337
|
+
raiseError(`Cannot expand dynamic dependency with wildcard for non-list address: ${address.pathInfo.path}`);
|
|
10338
|
+
}
|
|
10339
|
+
const listIndex = address.listIndex.at(wildcardLen - 1);
|
|
10340
|
+
listIndexes.push(listIndex);
|
|
10219
10341
|
}
|
|
10220
10342
|
}
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10343
|
+
else {
|
|
10344
|
+
// products.*.tax => currentTaxRate
|
|
10345
|
+
// 同じ親を持たないので、リストインデックスはnull
|
|
10346
|
+
listIndexes.push(null);
|
|
10347
|
+
}
|
|
10348
|
+
for (const listIndex of listIndexes) {
|
|
10349
|
+
const depAddress = createStateAddress(depPathInfo, listIndex);
|
|
10350
|
+
context.result.add(depAddress);
|
|
10351
|
+
nextEntries.push(depAddress);
|
|
10352
|
+
}
|
|
10225
10353
|
}
|
|
10226
10354
|
}
|
|
10227
10355
|
}
|
|
@@ -10235,7 +10363,12 @@ function walkDependency(stateName, stateElement, startAddress, staticDependency,
|
|
|
10235
10363
|
callback(startAddress);
|
|
10236
10364
|
return [];
|
|
10237
10365
|
}
|
|
10366
|
+
// パス単位のトポロジカル順位。値を一切読まずに求まり、依存グラフは追記のみで
|
|
10367
|
+
// 成長するため epoch でメモ化される(topologicalRank.ts)。
|
|
10368
|
+
const ranks = getTopologicalRanks(startPath, staticDependency, dynamicDependency, MAX_DEPENDENCY_DEPTH);
|
|
10238
10369
|
const context = {
|
|
10370
|
+
ranks: ranks,
|
|
10371
|
+
stateName: stateName,
|
|
10239
10372
|
stateElement: stateElement,
|
|
10240
10373
|
staticMap: staticDependency,
|
|
10241
10374
|
dynamicMap: dynamicDependency,
|