@barefootjs/mojolicious 0.31.8 → 0.31.10
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-render.d.ts","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKxE;AAkCD,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,8BAA8B;IAC9B,OAAO,EAAE,OAAO,iBAAiB,EAAE,eAAe,CAAA;IAClD,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"test-render.d.ts","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKxE;AAkCD,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,8BAA8B;IAC9B,OAAO,EAAE,OAAO,iBAAiB,EAAE,eAAe,CAAA;IAClD,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAgPjF"}
|
package/dist/vite.js
CHANGED
|
@@ -3025,6 +3025,34 @@ var SVG_ROOT_TAGS = new Set([
|
|
|
3025
3025
|
"animateTransform",
|
|
3026
3026
|
"animateMotion"
|
|
3027
3027
|
]);
|
|
3028
|
+
var MATHML_ROOT_TAGS = new Set([
|
|
3029
|
+
"math",
|
|
3030
|
+
"mrow",
|
|
3031
|
+
"mfrac",
|
|
3032
|
+
"msup",
|
|
3033
|
+
"msub",
|
|
3034
|
+
"msubsup",
|
|
3035
|
+
"mn",
|
|
3036
|
+
"mi",
|
|
3037
|
+
"mo",
|
|
3038
|
+
"mtext",
|
|
3039
|
+
"munder",
|
|
3040
|
+
"mover",
|
|
3041
|
+
"munderover",
|
|
3042
|
+
"mtable",
|
|
3043
|
+
"mtr",
|
|
3044
|
+
"mtd",
|
|
3045
|
+
"msqrt",
|
|
3046
|
+
"mroot",
|
|
3047
|
+
"mstyle",
|
|
3048
|
+
"merror",
|
|
3049
|
+
"mpadded",
|
|
3050
|
+
"mphantom",
|
|
3051
|
+
"menclose",
|
|
3052
|
+
"semantics",
|
|
3053
|
+
"annotation",
|
|
3054
|
+
"annotation-xml"
|
|
3055
|
+
]);
|
|
3028
3056
|
|
|
3029
3057
|
// ../jsx/src/ir-to-client-js/collect-elements.ts
|
|
3030
3058
|
var EMPTY_RENDER_EXPRS = new Set(["null", "undefined", "false", "''", '""', "``"]);
|
|
@@ -3888,6 +3916,38 @@ function classify(name, origin, expr, parsed, available) {
|
|
|
3888
3916
|
}
|
|
3889
3917
|
return { kind: "derived", name, origin, expr, parsed, frees: [...frees] };
|
|
3890
3918
|
}
|
|
3919
|
+
function localConstExprsByName(metadata) {
|
|
3920
|
+
const out = new Map;
|
|
3921
|
+
for (const c of metadata.localConstants ?? []) {
|
|
3922
|
+
if (c.isModule || c.declarationKind !== "const" || c.value === undefined)
|
|
3923
|
+
continue;
|
|
3924
|
+
out.set(c.name, c.parsed ?? parseExpression(c.value.trim()));
|
|
3925
|
+
}
|
|
3926
|
+
return out;
|
|
3927
|
+
}
|
|
3928
|
+
function resolveThroughLocalConsts(parsed, localConsts) {
|
|
3929
|
+
let current = parsed;
|
|
3930
|
+
const maxIter = localConsts.size + 1;
|
|
3931
|
+
for (let i = 0;i < maxIter; i++) {
|
|
3932
|
+
const frees = freeIdentifiers(current);
|
|
3933
|
+
if (frees === null)
|
|
3934
|
+
break;
|
|
3935
|
+
let changed = false;
|
|
3936
|
+
for (const name of frees) {
|
|
3937
|
+
const value = localConsts.get(name);
|
|
3938
|
+
if (!value)
|
|
3939
|
+
continue;
|
|
3940
|
+
const inlined = inlineBinding(current, name, value);
|
|
3941
|
+
if (inlined === null)
|
|
3942
|
+
continue;
|
|
3943
|
+
current = inlined;
|
|
3944
|
+
changed = true;
|
|
3945
|
+
}
|
|
3946
|
+
if (!changed)
|
|
3947
|
+
break;
|
|
3948
|
+
}
|
|
3949
|
+
return current;
|
|
3950
|
+
}
|
|
3891
3951
|
function computeSsrSeedPlan(metadata) {
|
|
3892
3952
|
const baseScope = metadata.propsParams.map((p) => p.name);
|
|
3893
3953
|
if (metadata.propsObjectName)
|
|
@@ -3896,6 +3956,7 @@ function computeSsrSeedPlan(metadata) {
|
|
|
3896
3956
|
baseScope.push(name);
|
|
3897
3957
|
}
|
|
3898
3958
|
const available = new Set(baseScope);
|
|
3959
|
+
const localConsts = localConstExprsByName(metadata);
|
|
3899
3960
|
const steps = [];
|
|
3900
3961
|
for (const signal of metadata.signals) {
|
|
3901
3962
|
if (signal.envReader) {
|
|
@@ -3907,13 +3968,13 @@ function computeSsrSeedPlan(metadata) {
|
|
|
3907
3968
|
}
|
|
3908
3969
|
}
|
|
3909
3970
|
const expr = signal.initialValue.trim();
|
|
3910
|
-
steps.push(expr === "" ? { kind: "opaque", name: signal.getter, origin: "signal" } : classify(signal.getter, "signal", expr, parseExpression(expr), available));
|
|
3971
|
+
steps.push(expr === "" ? { kind: "opaque", name: signal.getter, origin: "signal" } : classify(signal.getter, "signal", expr, resolveThroughLocalConsts(parseExpression(expr), localConsts), available));
|
|
3911
3972
|
available.add(signal.getter);
|
|
3912
3973
|
}
|
|
3913
3974
|
for (const memo of metadata.memos) {
|
|
3914
3975
|
const body = extractArrowBodyExpression(memo.computation);
|
|
3915
3976
|
const expr = body?.trim() ?? "";
|
|
3916
|
-
steps.push(expr === "" ? { kind: "opaque", name: memo.name, origin: "memo" } : classify(memo.name, "memo", expr, memo.parsed ?? parseExpression(expr), available));
|
|
3977
|
+
steps.push(expr === "" ? { kind: "opaque", name: memo.name, origin: "memo" } : classify(memo.name, "memo", expr, resolveThroughLocalConsts(memo.parsed ?? parseExpression(expr), localConsts), available));
|
|
3917
3978
|
available.add(memo.name);
|
|
3918
3979
|
}
|
|
3919
3980
|
return { baseScope, steps };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/mojolicious",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.10",
|
|
4
4
|
"description": "Mojolicious EP template adapter for BarefootJS - generates .html.ep files from IR",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"directory": "packages/adapter-mojolicious"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@barefootjs/shared": "0.31.
|
|
55
|
+
"@barefootjs/shared": "0.31.10"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"@barefootjs/jsx": ">=0.2.0",
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@barefootjs/adapter-tests": "0.1.0",
|
|
73
|
-
"@barefootjs/jsx": "0.31.
|
|
74
|
-
"@barefootjs/vite": "0.31.
|
|
75
|
-
"@barefootjs/client": "0.31.
|
|
73
|
+
"@barefootjs/jsx": "0.31.10",
|
|
74
|
+
"@barefootjs/vite": "0.31.10",
|
|
75
|
+
"@barefootjs/client": "0.31.10",
|
|
76
76
|
"vite": "^6.0.0"
|
|
77
77
|
}
|
|
78
78
|
}
|
package/src/test-render.ts
CHANGED
|
@@ -229,7 +229,7 @@ export async function renderMojoComponent(options: RenderOptions): Promise<strin
|
|
|
229
229
|
// bare `$var` aborts under Mojo::Template's strict vars.
|
|
230
230
|
augmentInheritedPropAccesses(ir)
|
|
231
231
|
// Build props hash for Perl
|
|
232
|
-
const propsPerl = buildPerlProps(componentName, props, ir)
|
|
232
|
+
const { propsPerl, userPropsPerl } = buildPerlProps(componentName, props, ir)
|
|
233
233
|
|
|
234
234
|
// Honour `__instanceId` from props for the root scope id so
|
|
235
235
|
// shared-component fixtures (which pin `<ComponentName>_test`) match
|
|
@@ -281,6 +281,18 @@ my $bf = BarefootJS->new($c, {});
|
|
|
281
281
|
# (which pin <ComponentName>_test scope ids for cross-adapter normalisation)
|
|
282
282
|
# match what Hono renderHonoComponent emits. Default to 'test' otherwise.
|
|
283
283
|
$bf->_scope_id('${rootScopeId}');
|
|
284
|
+
# Mirrors production's \`props_attr\` contract (BarefootJS.pm's \`_props\`
|
|
285
|
+
# accessor): the caller is expected to seed it before rendering the root
|
|
286
|
+
# component, so this harness must call it explicitly.
|
|
287
|
+
#
|
|
288
|
+
# \$user_props — NOT \$props above — is what \`_props\` gets: \$props is
|
|
289
|
+
# this harness's internal vars hash (scope_id, inherited-attribute \`undef\`
|
|
290
|
+
# placeholders, signal/memo seed values, and — when the component imports
|
|
291
|
+
# searchParams — a SearchParams reader object), none of which a real
|
|
292
|
+
# Mojolicious route handler has or passes. Production's bf-p carries none
|
|
293
|
+
# of those, only the caller-facing props.
|
|
294
|
+
my $user_props = ${userPropsPerl};
|
|
295
|
+
$bf->_props($user_props);
|
|
284
296
|
|
|
285
297
|
${childRenderers}
|
|
286
298
|
|
|
@@ -502,11 +514,37 @@ function buildChildDefaultsPerl(ir: ComponentIR): string {
|
|
|
502
514
|
// semantic divergence from those adapters.
|
|
503
515
|
for (const signal of ir.metadata.signals) {
|
|
504
516
|
if (signal.envReader) continue // env signal is the request reader, not a stashed value (#2057)
|
|
517
|
+
// #2669: a self-derivation collision (the signal's initializer derives
|
|
518
|
+
// from a same-named prop) gets a `propName`-carrying entry from
|
|
519
|
+
// `extractSsrDefaults` (see its docstring's invariant) — that entry
|
|
520
|
+
// MUST stay a hashref so `_derive_stash_from_defaults` resolves it
|
|
521
|
+
// against the REAL child props at runtime; the declared-prop loop above
|
|
522
|
+
// already emitted it for a DECLARED prop, so only an undeclared one
|
|
523
|
+
// needs adding here. Either way, do NOT fall through to this harness's
|
|
524
|
+
// own `evaluateSignalInit(..., undefined)` recompute below — that call
|
|
525
|
+
// sees no props at all and would silently re-flatten the collision back
|
|
526
|
+
// to a bare, non-caller-overridable value.
|
|
527
|
+
const d = ssrDefaults[signal.getter]
|
|
528
|
+
if (d?.propName !== undefined) {
|
|
529
|
+
if (!declared.has(signal.getter)) {
|
|
530
|
+
entries.push(`${signal.getter} => ${ssrDefaultEntryToPerl(d)}`)
|
|
531
|
+
declared.add(signal.getter)
|
|
532
|
+
}
|
|
533
|
+
continue
|
|
534
|
+
}
|
|
505
535
|
const value = evaluateSignalInit(signal.initialValue.trim(), undefined)
|
|
506
536
|
entries.push(`${signal.getter} => ${value !== null ? toPerlLiteral(value) : 'undef'}`)
|
|
507
537
|
}
|
|
508
538
|
for (const memo of ir.metadata.memos) {
|
|
509
539
|
const entry = ssrDefaults[memo.name]
|
|
540
|
+
// #2669: same self-derivation handling as the signal loop above.
|
|
541
|
+
if (entry?.propName !== undefined) {
|
|
542
|
+
if (!declared.has(memo.name)) {
|
|
543
|
+
entries.push(`${memo.name} => ${ssrDefaultEntryToPerl(entry)}`)
|
|
544
|
+
declared.add(memo.name)
|
|
545
|
+
}
|
|
546
|
+
continue
|
|
547
|
+
}
|
|
510
548
|
const value = entry ? entry.value : undefined
|
|
511
549
|
entries.push(
|
|
512
550
|
`${memo.name} => ${value !== undefined && value !== null ? toPerlLiteral(value) : 'undef'}`,
|
|
@@ -515,11 +553,22 @@ function buildChildDefaultsPerl(ir: ComponentIR): string {
|
|
|
515
553
|
return `{${entries.join(', ')}}`
|
|
516
554
|
}
|
|
517
555
|
|
|
556
|
+
/**
|
|
557
|
+
* Returns the full internal vars-hash Perl literal (`props`, what the
|
|
558
|
+
* inline `Mojo::Template` renders against) AND `userPropsPerl` — the
|
|
559
|
+
* exact raw fixture props (no defaults, no null-fill, no signal/memo
|
|
560
|
+
* seeding, no rest-bag nesting), mirroring production's route-handler
|
|
561
|
+
* call `$bf->_props($props)` verbatim. `userPropsPerl` is for
|
|
562
|
+
* `$bf->_props(...)` (bf-p hydration payload) only — these must NOT be
|
|
563
|
+
* the same value, and `userPropsPerl` must NOT be derived from
|
|
564
|
+
* `entries` or the defaulted stash: production's own bf-p carries only
|
|
565
|
+
* what the caller actually passed in, unmodified.
|
|
566
|
+
*/
|
|
518
567
|
function buildPerlProps(
|
|
519
568
|
_componentName: string,
|
|
520
569
|
props: Record<string, unknown> | undefined,
|
|
521
570
|
ir: ComponentIR,
|
|
522
|
-
): string {
|
|
571
|
+
): { propsPerl: string; userPropsPerl: string } {
|
|
523
572
|
const entries: string[] = []
|
|
524
573
|
|
|
525
574
|
// Add scope_id — honour an explicit `__instanceId` from props so
|
|
@@ -552,7 +601,8 @@ function buildPerlProps(
|
|
|
552
601
|
// emits a literal `$label` reference where the BF101 path used
|
|
553
602
|
// to emit `''`, exposing this latent test-harness gap.
|
|
554
603
|
const value = derivedProps[param.name]
|
|
555
|
-
|
|
604
|
+
const literal = value !== undefined && value !== null ? toPerlLiteral(value) : 'undef'
|
|
605
|
+
entries.push(`${param.name} => ${literal}`)
|
|
556
606
|
}
|
|
557
607
|
|
|
558
608
|
// (#checkbox) SolidJS props-object pattern: `function Checkbox(props:
|
|
@@ -623,8 +673,12 @@ function buildPerlProps(
|
|
|
623
673
|
const localParamNames = new Set(ir.metadata.propsParams.map(p => p.name))
|
|
624
674
|
if (props) {
|
|
625
675
|
for (const [key, value] of Object.entries(props)) {
|
|
676
|
+
// Internal hydration markers (`__instanceId` etc.) are routed by
|
|
677
|
+
// the framework, never a real caller-facing prop.
|
|
678
|
+
if (key.startsWith('__')) continue
|
|
626
679
|
if (routedKeys.has(key)) continue
|
|
627
680
|
if (localParamNames.has(key)) continue
|
|
681
|
+
let literal: string | null = null
|
|
628
682
|
if (value === null) {
|
|
629
683
|
// An explicit-null prop must still DECLARE the template var —
|
|
630
684
|
// `typeof null === 'object'` fails every branch below, so the key
|
|
@@ -632,15 +686,15 @@ function buildPerlProps(
|
|
|
632
686
|
// `my $user`, tripping Perl's strict-mode "Global symbol requires
|
|
633
687
|
// explicit package name" before the `//` fallback could apply
|
|
634
688
|
// (data-point conformance, optional-chaining-prop:null-user).
|
|
635
|
-
|
|
689
|
+
literal = 'undef'
|
|
636
690
|
} else if (typeof value === 'string') {
|
|
637
|
-
|
|
691
|
+
literal = `'${value.replace(/'/g, "\\'")}'`
|
|
638
692
|
} else if (typeof value === 'number') {
|
|
639
|
-
|
|
693
|
+
literal = `${value}`
|
|
640
694
|
} else if (typeof value === 'boolean') {
|
|
641
695
|
// Mojo::JSON sentinels so BarefootJS helpers can detect
|
|
642
696
|
// booleans via ref() (see toPerlLiteral / spread_attrs).
|
|
643
|
-
|
|
697
|
+
literal = value ? 'Mojo::JSON::true' : 'Mojo::JSON::false'
|
|
644
698
|
} else if (Array.isArray(value)) {
|
|
645
699
|
// Array → Perl arrayref literal. Fixtures that exercise
|
|
646
700
|
// array-receiver methods (`items.every(...)`, `items.some(...)`,
|
|
@@ -651,17 +705,38 @@ function buildPerlProps(
|
|
|
651
705
|
// declares `my $items` (the key is absent from the vars
|
|
652
706
|
// hash) and the template trips Perl's strict-mode "Global
|
|
653
707
|
// symbol $items requires explicit package name" check.
|
|
654
|
-
|
|
708
|
+
literal = toPerlLiteral(value)
|
|
655
709
|
} else if (value && typeof value === 'object') {
|
|
656
710
|
// Plain object → Perl hashref literal (#1407 follow-up).
|
|
657
711
|
// Used by the destructured-rest / propsObject fixtures
|
|
658
712
|
// (`jsx-spread-rest-prop`, `jsx-spread-props-object`) so
|
|
659
713
|
// the test harness can pass through bag-shaped props that
|
|
660
714
|
// weren't enumerated by the analyzer.
|
|
661
|
-
|
|
715
|
+
literal = toPerlLiteral(value)
|
|
662
716
|
}
|
|
717
|
+
if (literal !== null) {
|
|
718
|
+
entries.push(`${key} => ${literal}`)
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// `$bf->_props(...)` payload (bf-p hydration): mirrors production's
|
|
724
|
+
// route-handler call `$bf->_props($props)` verbatim — the caller's raw
|
|
725
|
+
// props hash, unmodified. No default-filling, no signal/memo seeding,
|
|
726
|
+
// no rest-bag nesting: a real Mojolicious route handler never
|
|
727
|
+
// rearranges the hash it received before handing it to `_props`.
|
|
728
|
+
// Excludes internal harness-only keys (`__instanceId` etc.), which are
|
|
729
|
+
// never a real caller-facing prop. Bareword key relies on Perl's
|
|
730
|
+
// fat-comma auto-quoting, matching this function's other hash-literal
|
|
731
|
+
// construction above.
|
|
732
|
+
const userEntries: string[] = []
|
|
733
|
+
if (props) {
|
|
734
|
+
for (const [key, value] of Object.entries(props)) {
|
|
735
|
+
if (key.startsWith('__')) continue
|
|
736
|
+
userEntries.push(`${key} => ${toPerlLiteral(value)}`)
|
|
663
737
|
}
|
|
664
738
|
}
|
|
739
|
+
const userPropsPerl = `{${userEntries.join(', ')}}`
|
|
665
740
|
|
|
666
741
|
// Add signal values evaluated from props (must come after user props).
|
|
667
742
|
// Seed `undef` for a null / unevaluable initial (e.g. a
|
|
@@ -671,6 +746,12 @@ function buildPerlProps(
|
|
|
671
746
|
// rule `buildChildDefaultsPerl` applies to child signals (#1897).
|
|
672
747
|
for (const signal of ir.metadata.signals) {
|
|
673
748
|
if (signal.envReader) continue // env signal bound below via search_params('') (#2057)
|
|
749
|
+
// #2669: a self-derivation collision already got the correct RAW-prop
|
|
750
|
+
// seed above via `derivedProps` — `extractSsrDefaults` marks that with
|
|
751
|
+
// a `propName`-carrying entry (see its docstring's invariant). Skip
|
|
752
|
+
// re-seeding here or this harness's own `evaluateSignalInit` recompute
|
|
753
|
+
// clobbers the correctly-derived caller value.
|
|
754
|
+
if (rootSsrDefaults[signal.getter]?.propName !== undefined) continue
|
|
674
755
|
const value = evaluateSignalInit(signal.initialValue.trim(), props)
|
|
675
756
|
entries.push(`${signal.getter} => ${value !== null ? toPerlLiteral(value) : 'undef'}`)
|
|
676
757
|
}
|
|
@@ -682,6 +763,8 @@ function buildPerlProps(
|
|
|
682
763
|
// from the plugin: hard-coding `0` masked memos with non-zero
|
|
683
764
|
// initial values until #1423 added a fixture that exposed the gap.
|
|
684
765
|
for (const memo of ir.metadata.memos) {
|
|
766
|
+
// #2669: same self-derivation skip as the signal loop above.
|
|
767
|
+
if (rootSsrDefaults[memo.name]?.propName !== undefined) continue
|
|
685
768
|
const entry = rootSsrDefaults[memo.name]
|
|
686
769
|
const value = entry ? entry.value : 0
|
|
687
770
|
entries.push(`${memo.name} => ${toPerlLiteral(value ?? 0)}`)
|
|
@@ -697,7 +780,7 @@ function buildPerlProps(
|
|
|
697
780
|
entries.push(`searchParams => BarefootJS->search_params('')`)
|
|
698
781
|
}
|
|
699
782
|
|
|
700
|
-
return `{${entries.join(', ')}}
|
|
783
|
+
return { propsPerl: `{${entries.join(', ')}}`, userPropsPerl }
|
|
701
784
|
}
|
|
702
785
|
|
|
703
786
|
/**
|