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/README.ja.md +1 -1
- package/README.md +1 -1
- package/dist/haori.cjs.js +14 -14
- package/dist/haori.cjs.js.map +1 -1
- package/dist/haori.es.js +2060 -1505
- package/dist/haori.es.js.map +1 -1
- package/dist/haori.iife.js +14 -14
- package/dist/haori.iife.js.map +1 -1
- package/dist/index.d.ts +95 -0
- package/dist/package.json +1 -1
- package/dist/src/core.d.ts +67 -0
- package/dist/src/core.d.ts.map +1 -1
- package/dist/src/core.js +274 -10
- package/dist/src/core.js.map +1 -1
- package/dist/src/expression.d.ts +32 -0
- package/dist/src/expression.d.ts.map +1 -1
- package/dist/src/expression.js +106 -26
- package/dist/src/expression.js.map +1 -1
- package/dist/src/fragment.d.ts +28 -0
- package/dist/src/fragment.d.ts.map +1 -1
- package/dist/src/fragment.js +356 -42
- package/dist/src/fragment.js.map +1 -1
- package/dist/tests/data-derive.test.js +100 -0
- package/dist/tests/data-derive.test.js.map +1 -1
- package/dist/tests/evaluation-profile.test.d.ts +2 -0
- package/dist/tests/evaluation-profile.test.d.ts.map +1 -0
- package/dist/tests/evaluation-profile.test.js +92 -0
- package/dist/tests/evaluation-profile.test.js.map +1 -0
- package/dist/tests/expression.test.js +4 -0
- package/dist/tests/expression.test.js.map +1 -1
- package/package.json +1 -1
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
package/dist/src/core.d.ts
CHANGED
|
@@ -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
|
*
|
package/dist/src/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"
|
|
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(() =>
|
|
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
|
-
|
|
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
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
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
|
-
|
|
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
|
-
|
|
712
|
-
|
|
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
|