haori 0.6.1 → 0.6.2

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.d.ts CHANGED
@@ -64,6 +64,8 @@ export declare class Core {
64
64
  private static readonly REACTIVE_FETCH_STATES;
65
65
  /** data-import の自動再評価状態 */
66
66
  private static readonly REACTIVE_IMPORT_STATES;
67
+ /** data-derive subtree skip の開発用プロファイル */
68
+ private static readonly DERIVE_SUBTREE_PROFILES;
67
69
  /**
68
70
  * 遅延属性かどうか(完全名で判定)を判定します。
69
71
  *
@@ -311,6 +313,71 @@ export declare class Core {
311
313
  * @returns 省略可能なら true
312
314
  */
313
315
  private static canSkipUnchangedNestedEach;
316
+ /**
317
+ * data-derive subtree の入力が同値で、保守条件も満たす場合に
318
+ * 子走査を省略できるかどうかを返します。
319
+ *
320
+ * @param fragment 判定対象フラグメント
321
+ * @returns 省略可能なら true
322
+ */
323
+ private static canSkipStableDerivedSubtree;
324
+ /**
325
+ * data-derive subtree skip の初期 PoC で扱わない子孫要素を含むかを返します。
326
+ *
327
+ * @param fragment 判定対象フラグメント
328
+ * @returns 含むなら true
329
+ */
330
+ private static hasDisallowedDerivedSubtreeDescendant;
331
+ /**
332
+ * data-derive host が子孫要素へ公開している binding の署名を返します。
333
+ *
334
+ * @param fragment 対象フラグメント
335
+ * @returns binding 署名
336
+ */
337
+ private static createDescendantBindingSignature;
338
+ /**
339
+ * data-derive 実行前の入力署名を返します。
340
+ *
341
+ * @param fragment 対象フラグメント
342
+ * @param deriveExpression 導出式
343
+ * @param deriveName 導出名
344
+ * @returns 入力署名。導出が無効なら null
345
+ */
346
+ private static createDeriveInputSignature;
347
+ /**
348
+ * data-derive subtree skip 用の署名を現在状態で更新します。
349
+ *
350
+ * @param fragment 対象フラグメント
351
+ */
352
+ private static refreshDerivedSubtreeSignature;
353
+ /**
354
+ * data-derive subtree skip のプロファイルを取得または初期化します。
355
+ *
356
+ * @param fragment 対象フラグメント
357
+ * @returns プロファイル
358
+ */
359
+ private static getOrCreateDerivedSubtreeProfile;
360
+ /**
361
+ * data-derive subtree host の識別子を作成します。
362
+ *
363
+ * @param fragment 対象フラグメント
364
+ * @returns host 識別子
365
+ */
366
+ private static createDerivedSubtreeHostId;
367
+ /**
368
+ * data-derive subtree の署名計算回数を記録します。
369
+ *
370
+ * @param fragment 対象フラグメント
371
+ * @param source 計算元
372
+ */
373
+ private static recordDerivedSubtreeSignatureComputation;
374
+ /**
375
+ * data-derive subtree の現在プロファイルをログ出力します。
376
+ *
377
+ * @param fragment 対象フラグメント
378
+ * @param reason ログ理由
379
+ */
380
+ private static logDerivedSubtreeProfileSnapshot;
314
381
  /**
315
382
  * data-each 以外の動的要素状態を持つかどうかを返します。
316
383
  *
@@ -427,6 +494,10 @@ declare class ElementFragment extends Fragment {
427
494
  private renderSignature;
428
495
  /** 直近に描画した data-each 全体の入力署名 */
429
496
  private eachInputSignature;
497
+ /** 直近に公開した data-derive subtree の入力署名 */
498
+ private deriveSubtreeSignature;
499
+ /** 直近に評価した data-derive の入力署名 */
500
+ private deriveInputSignature;
430
501
  /** fresh clone 初期化を subtree ごと省略できるかどうか */
431
502
  private freshInitializationSkippable;
432
503
  /** valueプロパティの値 */
@@ -585,6 +656,30 @@ declare class ElementFragment extends Fragment {
585
656
  * @param signature 入力署名
586
657
  */
587
658
  setEachInputSignature(signature: string | null): void;
659
+ /**
660
+ * 直近に公開した data-derive subtree の入力署名を取得します。
661
+ *
662
+ * @returns 入力署名
663
+ */
664
+ getDeriveSubtreeSignature(): string | null;
665
+ /**
666
+ * 直近に公開した data-derive subtree の入力署名を設定します。
667
+ *
668
+ * @param signature 入力署名
669
+ */
670
+ setDeriveSubtreeSignature(signature: string | null): void;
671
+ /**
672
+ * 直近に評価した data-derive の入力署名を取得します。
673
+ *
674
+ * @returns 入力署名
675
+ */
676
+ getDeriveInputSignature(): string | null;
677
+ /**
678
+ * 直近に評価した data-derive の入力署名を設定します。
679
+ *
680
+ * @param signature 入力署名
681
+ */
682
+ setDeriveInputSignature(signature: string | null): void;
588
683
  /**
589
684
  * fresh clone 初期化を subtree ごと省略できるかどうかを返します。
590
685
  *
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haori",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "A lightweight HTML-first UI engine powered by declarative data bindings and expressions.",
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -18,6 +18,8 @@ export default class Core {
18
18
  private static readonly REACTIVE_FETCH_STATES;
19
19
  /** data-import の自動再評価状態 */
20
20
  private static readonly REACTIVE_IMPORT_STATES;
21
+ /** data-derive subtree skip の開発用プロファイル */
22
+ private static readonly DERIVE_SUBTREE_PROFILES;
21
23
  /**
22
24
  * 遅延属性かどうか(完全名で判定)を判定します。
23
25
  *
@@ -265,6 +267,71 @@ export default class Core {
265
267
  * @returns 省略可能なら true
266
268
  */
267
269
  private static canSkipUnchangedNestedEach;
270
+ /**
271
+ * data-derive subtree の入力が同値で、保守条件も満たす場合に
272
+ * 子走査を省略できるかどうかを返します。
273
+ *
274
+ * @param fragment 判定対象フラグメント
275
+ * @returns 省略可能なら true
276
+ */
277
+ private static canSkipStableDerivedSubtree;
278
+ /**
279
+ * data-derive subtree skip の初期 PoC で扱わない子孫要素を含むかを返します。
280
+ *
281
+ * @param fragment 判定対象フラグメント
282
+ * @returns 含むなら true
283
+ */
284
+ private static hasDisallowedDerivedSubtreeDescendant;
285
+ /**
286
+ * data-derive host が子孫要素へ公開している binding の署名を返します。
287
+ *
288
+ * @param fragment 対象フラグメント
289
+ * @returns binding 署名
290
+ */
291
+ private static createDescendantBindingSignature;
292
+ /**
293
+ * data-derive 実行前の入力署名を返します。
294
+ *
295
+ * @param fragment 対象フラグメント
296
+ * @param deriveExpression 導出式
297
+ * @param deriveName 導出名
298
+ * @returns 入力署名。導出が無効なら null
299
+ */
300
+ private static createDeriveInputSignature;
301
+ /**
302
+ * data-derive subtree skip 用の署名を現在状態で更新します。
303
+ *
304
+ * @param fragment 対象フラグメント
305
+ */
306
+ private static refreshDerivedSubtreeSignature;
307
+ /**
308
+ * data-derive subtree skip のプロファイルを取得または初期化します。
309
+ *
310
+ * @param fragment 対象フラグメント
311
+ * @returns プロファイル
312
+ */
313
+ private static getOrCreateDerivedSubtreeProfile;
314
+ /**
315
+ * data-derive subtree host の識別子を作成します。
316
+ *
317
+ * @param fragment 対象フラグメント
318
+ * @returns host 識別子
319
+ */
320
+ private static createDerivedSubtreeHostId;
321
+ /**
322
+ * data-derive subtree の署名計算回数を記録します。
323
+ *
324
+ * @param fragment 対象フラグメント
325
+ * @param source 計算元
326
+ */
327
+ private static recordDerivedSubtreeSignatureComputation;
328
+ /**
329
+ * data-derive subtree の現在プロファイルをログ出力します。
330
+ *
331
+ * @param fragment 対象フラグメント
332
+ * @param reason ログ理由
333
+ */
334
+ private static logDerivedSubtreeProfileSnapshot;
268
335
  /**
269
336
  * data-each 以外の動的要素状態を持つかどうかを返します。
270
337
  *
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"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"}
package/dist/src/core.js CHANGED
@@ -5,6 +5,7 @@
5
5
  * アプリケーションの中心的な機能を提供します。
6
6
  */
7
7
  import Env from './env';
8
+ import Dev from './dev';
8
9
  import Expression from './expression';
9
10
  import Form from './form';
10
11
  import Fragment, { ElementFragment, TextFragment } from './fragment';
@@ -327,6 +328,7 @@ class Core {
327
328
  }
328
329
  return Core.initializeElementAttributes(fragment).then(() => {
329
330
  if (Core.shouldSkipChildInitialization(fragment, stopAtEach)) {
331
+ Core.refreshDerivedSubtreeSignature(fragment);
330
332
  return undefined;
331
333
  }
332
334
  const childPromises = [];
@@ -338,7 +340,10 @@ class Core {
338
340
  childPromises.push(Core.evaluateText(child));
339
341
  }
340
342
  });
341
- return Promise.all(childPromises).then(() => undefined);
343
+ return Promise.all(childPromises).then(() => {
344
+ Core.refreshDerivedSubtreeSignature(fragment);
345
+ return undefined;
346
+ });
342
347
  });
343
348
  }
344
349
  /**
@@ -434,6 +439,7 @@ class Core {
434
439
  }
435
440
  const promises = [];
436
441
  let deriveChangedPromise = null;
442
+ let nextDeriveInputSignature = null;
437
443
  switch (name) {
438
444
  case `${Env.prefix}bind`: {
439
445
  if (value === null) {
@@ -446,10 +452,12 @@ class Core {
446
452
  break;
447
453
  }
448
454
  case `${Env.prefix}derive`:
455
+ nextDeriveInputSignature = Core.createDeriveInputSignature(fragment, value, fragment.getRawAttribute(`${Env.prefix}derive-name`));
449
456
  deriveChangedPromise = Core.evaluateDerive(fragment, value, fragment.getRawAttribute(`${Env.prefix}derive-name`));
450
457
  promises.push(deriveChangedPromise.then(() => undefined));
451
458
  break;
452
459
  case `${Env.prefix}derive-name`:
460
+ nextDeriveInputSignature = Core.createDeriveInputSignature(fragment, fragment.getRawAttribute(`${Env.prefix}derive`), value);
453
461
  deriveChangedPromise = Core.evaluateDerive(fragment, fragment.getRawAttribute(`${Env.prefix}derive`), value);
454
462
  promises.push(deriveChangedPromise.then(() => undefined));
455
463
  break;
@@ -490,6 +498,7 @@ class Core {
490
498
  return Promise.all(promises)
491
499
  .then(() => {
492
500
  if (deriveChangedPromise !== null) {
501
+ fragment.setDeriveInputSignature(nextDeriveInputSignature);
493
502
  return deriveChangedPromise.then(changed => {
494
503
  if (!changed) {
495
504
  return undefined;
@@ -688,31 +697,90 @@ class Core {
688
697
  const hasDerive = fragment.hasAttribute(`${Env.prefix}derive`);
689
698
  const hasIf = fragment.hasAttribute(`${Env.prefix}if`);
690
699
  const hasEach = fragment.hasAttribute(`${Env.prefix}each`);
700
+ const deriveExpression = fragment.getRawAttribute(`${Env.prefix}derive`);
701
+ const deriveName = fragment.getRawAttribute(`${Env.prefix}derive-name`);
702
+ let shouldSkipDerivedSubtree = false;
703
+ let shouldRecordDerivedSubtreeSignature = false;
704
+ let nextDerivedSubtreeSignature = null;
705
+ if (!hasDerive && fragment.getDeriveSubtreeSignature() !== null) {
706
+ fragment.setDeriveSubtreeSignature(null);
707
+ }
708
+ if (!hasDerive && fragment.getDeriveInputSignature() !== null) {
709
+ fragment.setDeriveInputSignature(null);
710
+ }
691
711
  if (hasDerive) {
692
- chain = chain.then(() => Core.evaluateDerive(fragment).then(() => undefined));
712
+ const nextDeriveInputSignature = Core.createDeriveInputSignature(fragment, deriveExpression, deriveName);
713
+ if (nextDeriveInputSignature === null) {
714
+ if (fragment.getDeriveInputSignature() !== null) {
715
+ fragment.setDeriveInputSignature(null);
716
+ }
717
+ chain = chain.then(() => Core.evaluateDerive(fragment, deriveExpression, deriveName).then(() => undefined));
718
+ }
719
+ else if (fragment.getDeriveInputSignature() !== nextDeriveInputSignature) {
720
+ chain = chain.then(() => {
721
+ return Core.evaluateDerive(fragment, deriveExpression, deriveName).then(() => {
722
+ fragment.setDeriveInputSignature(nextDeriveInputSignature);
723
+ return undefined;
724
+ });
725
+ });
726
+ }
693
727
  }
694
728
  if (hasIf) {
695
729
  chain = chain.then(() => Core.evaluateIf(fragment));
696
730
  }
697
731
  if (hasEach) {
732
+ if (fragment.getDeriveSubtreeSignature() !== null) {
733
+ fragment.setDeriveSubtreeSignature(null);
734
+ }
698
735
  return chain.then(() => Core.evaluateEach(fragment));
699
736
  }
700
737
  if (hasIf) {
738
+ if (fragment.getDeriveSubtreeSignature() !== null) {
739
+ fragment.setDeriveSubtreeSignature(null);
740
+ }
701
741
  return chain.then(() => undefined);
702
742
  }
703
- const promises = [];
704
- fragment.getChildren().forEach(child => {
705
- if (child instanceof ElementFragment) {
706
- if (Core.canSkipUnchangedNestedEach(child)) {
743
+ if (hasDerive) {
744
+ chain = chain.then(() => {
745
+ if (!Core.canSkipStableDerivedSubtree(fragment)) {
746
+ fragment.setDeriveSubtreeSignature(null);
747
+ Core.logDerivedSubtreeProfileSnapshot(fragment, 'skip-ineligible');
707
748
  return;
708
749
  }
709
- promises.push(Core.evaluateAll(child, skipFragments));
750
+ nextDerivedSubtreeSignature = Core.createDescendantBindingSignature(fragment, 'evaluateAll');
751
+ shouldRecordDerivedSubtreeSignature = true;
752
+ shouldSkipDerivedSubtree =
753
+ fragment.getDeriveSubtreeSignature() !== null &&
754
+ fragment.getDeriveSubtreeSignature() === nextDerivedSubtreeSignature;
755
+ Core.logDerivedSubtreeProfileSnapshot(fragment, shouldSkipDerivedSubtree ? 'skip-hit' : 'skip-miss');
756
+ });
757
+ }
758
+ return chain
759
+ .then(() => {
760
+ if (shouldSkipDerivedSubtree) {
761
+ return undefined;
710
762
  }
711
- else if (child instanceof TextFragment) {
712
- promises.push(Core.evaluateText(child));
763
+ const promises = [];
764
+ fragment.getChildren().forEach(child => {
765
+ if (child instanceof ElementFragment) {
766
+ if (Core.canSkipUnchangedNestedEach(child)) {
767
+ return;
768
+ }
769
+ promises.push(Core.evaluateAll(child, skipFragments));
770
+ }
771
+ else if (child instanceof TextFragment) {
772
+ promises.push(Core.evaluateText(child));
773
+ }
774
+ });
775
+ return Promise.all(promises).then(() => undefined);
776
+ })
777
+ .then(() => {
778
+ if (shouldRecordDerivedSubtreeSignature &&
779
+ nextDerivedSubtreeSignature !== null) {
780
+ fragment.setDeriveSubtreeSignature(nextDerivedSubtreeSignature);
713
781
  }
782
+ return undefined;
714
783
  });
715
- return chain.then(() => Promise.all(promises)).then(() => undefined);
716
784
  }
717
785
  /**
718
786
  * data-derive / data-derive-name を評価し、子孫要素向けの派生値を更新します。
@@ -914,6 +982,200 @@ class Core {
914
982
  });
915
983
  return fragment.getEachInputSignature() === nextEachInputSignature;
916
984
  }
985
+ /**
986
+ * data-derive subtree の入力が同値で、保守条件も満たす場合に
987
+ * 子走査を省略できるかどうかを返します。
988
+ *
989
+ * @param fragment 判定対象フラグメント
990
+ * @returns 省略可能なら true
991
+ */
992
+ static canSkipStableDerivedSubtree(fragment) {
993
+ if (!fragment.hasAttribute(`${Env.prefix}derive`)) {
994
+ return false;
995
+ }
996
+ if (fragment.hasAttribute(`${Env.prefix}if`) ||
997
+ fragment.hasAttribute(`${Env.prefix}each`) ||
998
+ fragment.hasAttribute(`${Env.prefix}fetch`) ||
999
+ fragment.hasAttribute(`${Env.prefix}import`)) {
1000
+ return false;
1001
+ }
1002
+ return !Core.hasDisallowedDerivedSubtreeDescendant(fragment);
1003
+ }
1004
+ /**
1005
+ * data-derive subtree skip の初期 PoC で扱わない子孫要素を含むかを返します。
1006
+ *
1007
+ * @param fragment 判定対象フラグメント
1008
+ * @returns 含むなら true
1009
+ */
1010
+ static hasDisallowedDerivedSubtreeDescendant(fragment) {
1011
+ return fragment.getChildren().some(child => {
1012
+ if (!(child instanceof ElementFragment)) {
1013
+ return false;
1014
+ }
1015
+ if (child.hasAttribute(`${Env.prefix}derive`) ||
1016
+ child.hasAttribute(`${Env.prefix}derive-name`) ||
1017
+ child.hasAttribute(`${Env.prefix}fetch`) ||
1018
+ child.hasAttribute(`${Env.prefix}import`)) {
1019
+ return true;
1020
+ }
1021
+ return Core.hasDisallowedDerivedSubtreeDescendant(child);
1022
+ });
1023
+ }
1024
+ /**
1025
+ * data-derive host が子孫要素へ公開している binding の署名を返します。
1026
+ *
1027
+ * @param fragment 対象フラグメント
1028
+ * @returns binding 署名
1029
+ */
1030
+ static createDescendantBindingSignature(fragment, source) {
1031
+ Core.recordDerivedSubtreeSignatureComputation(fragment, source);
1032
+ return Core.createBindingSignature(fragment.getDescendantBindingData());
1033
+ }
1034
+ /**
1035
+ * data-derive 実行前の入力署名を返します。
1036
+ *
1037
+ * @param fragment 対象フラグメント
1038
+ * @param deriveExpression 導出式
1039
+ * @param deriveName 導出名
1040
+ * @returns 入力署名。導出が無効なら null
1041
+ */
1042
+ static createDeriveInputSignature(fragment, deriveExpression, deriveName) {
1043
+ const normalizedName = typeof deriveName === 'string' ? deriveName.trim() : '';
1044
+ if (!deriveExpression || normalizedName === '') {
1045
+ return null;
1046
+ }
1047
+ return Core.createBindingSignature({
1048
+ expression: deriveExpression,
1049
+ name: normalizedName,
1050
+ scope: fragment.getBindingData(),
1051
+ });
1052
+ }
1053
+ /**
1054
+ * data-derive subtree skip 用の署名を現在状態で更新します。
1055
+ *
1056
+ * @param fragment 対象フラグメント
1057
+ */
1058
+ static refreshDerivedSubtreeSignature(fragment) {
1059
+ if (!Core.canSkipStableDerivedSubtree(fragment)) {
1060
+ fragment.setDeriveSubtreeSignature(null);
1061
+ Core.logDerivedSubtreeProfileSnapshot(fragment, 'skip-ineligible');
1062
+ return;
1063
+ }
1064
+ fragment.setDeriveSubtreeSignature(Core.createDescendantBindingSignature(fragment, 'refresh'));
1065
+ Core.logDerivedSubtreeProfileSnapshot(fragment, 'refresh');
1066
+ }
1067
+ /**
1068
+ * data-derive subtree skip のプロファイルを取得または初期化します。
1069
+ *
1070
+ * @param fragment 対象フラグメント
1071
+ * @returns プロファイル
1072
+ */
1073
+ static getOrCreateDerivedSubtreeProfile(fragment) {
1074
+ if (!Dev.isEnabled() || !fragment.hasAttribute(`${Env.prefix}derive`)) {
1075
+ return null;
1076
+ }
1077
+ const existing = Core.DERIVE_SUBTREE_PROFILES.get(fragment);
1078
+ if (existing) {
1079
+ return existing;
1080
+ }
1081
+ const profile = {
1082
+ hostId: Core.createDerivedSubtreeHostId(fragment),
1083
+ signatureComputeTotal: 0,
1084
+ signatureComputeFromEvaluateAll: 0,
1085
+ signatureComputeFromRefresh: 0,
1086
+ skipHitCount: 0,
1087
+ skipMissCount: 0,
1088
+ skipIneligibleCount: 0,
1089
+ };
1090
+ Core.DERIVE_SUBTREE_PROFILES.set(fragment, profile);
1091
+ return profile;
1092
+ }
1093
+ /**
1094
+ * data-derive subtree host の識別子を作成します。
1095
+ *
1096
+ * @param fragment 対象フラグメント
1097
+ * @returns host 識別子
1098
+ */
1099
+ static createDerivedSubtreeHostId(fragment) {
1100
+ const segments = [];
1101
+ let current = fragment;
1102
+ while (current) {
1103
+ const target = current.getTarget();
1104
+ if (!(target instanceof HTMLElement)) {
1105
+ break;
1106
+ }
1107
+ let segment = target.tagName.toLowerCase();
1108
+ if (target.id.trim() !== '') {
1109
+ segment += `#${target.id.trim()}`;
1110
+ segments.unshift(segment);
1111
+ break;
1112
+ }
1113
+ const deriveName = current.getRawAttribute(`${Env.prefix}derive-name`);
1114
+ if (typeof deriveName === 'string' && deriveName.trim() !== '') {
1115
+ segment += `[${Env.prefix}derive-name="${deriveName.trim()}"]`;
1116
+ }
1117
+ const parent = current.getParent();
1118
+ if (parent) {
1119
+ const siblingIndex = parent
1120
+ .getChildren()
1121
+ .filter(child => child instanceof ElementFragment)
1122
+ .findIndex(child => child === current);
1123
+ segment += `:nth-child(${siblingIndex + 1})`;
1124
+ }
1125
+ segments.unshift(segment);
1126
+ current = parent;
1127
+ }
1128
+ return segments.join(' > ');
1129
+ }
1130
+ /**
1131
+ * data-derive subtree の署名計算回数を記録します。
1132
+ *
1133
+ * @param fragment 対象フラグメント
1134
+ * @param source 計算元
1135
+ */
1136
+ static recordDerivedSubtreeSignatureComputation(fragment, source) {
1137
+ const profile = Core.getOrCreateDerivedSubtreeProfile(fragment);
1138
+ if (profile === null) {
1139
+ return;
1140
+ }
1141
+ profile.signatureComputeTotal += 1;
1142
+ if (source === 'refresh') {
1143
+ profile.signatureComputeFromRefresh += 1;
1144
+ return;
1145
+ }
1146
+ profile.signatureComputeFromEvaluateAll += 1;
1147
+ }
1148
+ /**
1149
+ * data-derive subtree の現在プロファイルをログ出力します。
1150
+ *
1151
+ * @param fragment 対象フラグメント
1152
+ * @param reason ログ理由
1153
+ */
1154
+ static logDerivedSubtreeProfileSnapshot(fragment, reason) {
1155
+ const profile = Core.getOrCreateDerivedSubtreeProfile(fragment);
1156
+ if (profile === null) {
1157
+ return;
1158
+ }
1159
+ if (reason === 'skip-hit') {
1160
+ profile.skipHitCount += 1;
1161
+ }
1162
+ else if (reason === 'skip-miss') {
1163
+ profile.skipMissCount += 1;
1164
+ }
1165
+ else if (reason === 'skip-ineligible') {
1166
+ profile.skipIneligibleCount += 1;
1167
+ }
1168
+ Log.info('[Haori][derive-profile]', {
1169
+ reason,
1170
+ hostId: profile.hostId,
1171
+ signatureComputeTotal: profile.signatureComputeTotal,
1172
+ signatureComputeFromEvaluateAll: profile.signatureComputeFromEvaluateAll,
1173
+ signatureComputeFromRefresh: profile.signatureComputeFromRefresh,
1174
+ skipHitCount: profile.skipHitCount,
1175
+ skipMissCount: profile.skipMissCount,
1176
+ skipIneligibleCount: profile.skipIneligibleCount,
1177
+ });
1178
+ }
917
1179
  /**
918
1180
  * data-each 以外の動的要素状態を持つかどうかを返します。
919
1181
  *
@@ -1296,5 +1558,7 @@ Core.ATTRIBUTE_PLACEHOLDER_REGEX = /\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/;
1296
1558
  Core.REACTIVE_FETCH_STATES = new WeakMap();
1297
1559
  /** data-import の自動再評価状態 */
1298
1560
  Core.REACTIVE_IMPORT_STATES = new WeakMap();
1561
+ /** data-derive subtree skip の開発用プロファイル */
1562
+ Core.DERIVE_SUBTREE_PROFILES = new WeakMap();
1299
1563
  export default Core;
1300
1564
  //# sourceMappingURL=core.js.map