@milaboratories/uikit 2.15.32 → 2.15.34
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/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-formatter$colon$check.log +2 -2
- package/.turbo/turbo-linter$colon$check.log +2 -2
- package/.turbo/turbo-types$colon$check.log +1 -1
- package/CHANGELOG.md +29 -0
- package/dist/composition/computedCached.d.ts +11 -0
- package/dist/composition/computedCached.d.ts.map +1 -1
- package/dist/composition/computedCached.js +7 -3
- package/dist/composition/computedCached.js.map +1 -1
- package/package.json +5 -5
- package/src/composition/computedCached.ts +25 -5
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @milaboratories/uikit@2.15.
|
|
3
|
+
> @milaboratories/uikit@2.15.34 build /home/runner/_work/platforma/platforma/lib/ui/uikit
|
|
4
4
|
> ts-builder build --target browser-lib --build-config ./build.browser-lib.config.js
|
|
5
5
|
|
|
6
6
|
Building browser-lib project...
|
|
@@ -18,7 +18,7 @@ Using custom config: ./build.browser-lib.config.js
|
|
|
18
18
|
rendering chunks...
|
|
19
19
|
|
|
20
20
|
[unplugin:dts] Start generate declaration files...
|
|
21
|
-
[unplugin:dts] Declaration files built in
|
|
21
|
+
[unplugin:dts] Declaration files built in 6683ms.
|
|
22
22
|
|
|
23
23
|
computing gzip size...
|
|
24
24
|
dist/components/PlClipboard/PlClipboard.vue?vue&type=style&index=0&lang.css 0.04 kB │ gzip: 0.06 kB
|
|
@@ -500,7 +500,6 @@ dist/assets/icons/icon-assets-min/24_edit.js
|
|
|
500
500
|
dist/assets/icons/icon-assets-min/24_line-error.js 0.58 kB │ gzip: 0.34 kB │ map: 0.67 kB
|
|
501
501
|
dist/assets/icons/icon-assets-min/16_copy.js 0.59 kB │ gzip: 0.37 kB │ map: 0.68 kB
|
|
502
502
|
dist/assets/icons/icon-assets-min/24_reverse.js 0.59 kB │ gzip: 0.36 kB │ map: 0.66 kB
|
|
503
|
-
dist/composition/computedCached.js 0.59 kB │ gzip: 0.36 kB │ map: 2.72 kB
|
|
504
503
|
dist/assets/icons/icon-assets-min/24_files-export.js 0.59 kB │ gzip: 0.38 kB │ map: 0.68 kB
|
|
505
504
|
dist/assets/icons/icon-assets-min/16_edit.js 0.59 kB │ gzip: 0.38 kB │ map: 0.67 kB
|
|
506
505
|
dist/assets/icons/icon-assets-min/24_files-import.js 0.60 kB │ gzip: 0.38 kB │ map: 0.68 kB
|
|
@@ -528,12 +527,13 @@ dist/composition/useQuery.js
|
|
|
528
527
|
dist/assets/icons/icon-assets-min/16_settings.js 0.64 kB │ gzip: 0.37 kB │ map: 0.71 kB
|
|
529
528
|
dist/assets/icons/icon-assets-min/24_table-upload.js 0.64 kB │ gzip: 0.38 kB │ map: 0.73 kB
|
|
530
529
|
dist/assets/icons/icon-assets-min/16_data-dimentions.js 0.64 kB │ gzip: 0.42 kB │ map: 0.74 kB
|
|
530
|
+
dist/composition/computedCached.js 0.64 kB │ gzip: 0.39 kB │ map: 3.88 kB
|
|
531
531
|
[33m[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugins. Here is a breakdown:
|
|
532
|
-
- vite:asset (
|
|
533
|
-
- sourcemaps (13%)
|
|
532
|
+
- vite:asset (38%)
|
|
534
533
|
- vite:css-post (12%)
|
|
535
|
-
-
|
|
536
|
-
- unplugin-dts (
|
|
534
|
+
- sourcemaps (11%)
|
|
535
|
+
- unplugin-dts (10%)
|
|
536
|
+
- vite:vue (10%)
|
|
537
537
|
See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
538
538
|
[39m
|
|
539
539
|
dist/assets/icons/icon-assets-min/16_clipboard.js 0.64 kB │ gzip: 0.38 kB │ map: 0.72 kB
|
|
@@ -790,5 +790,5 @@ dist/composition/filters/metadata.js
|
|
|
790
790
|
dist/index.js 12.53 kB │ gzip: 2.96 kB │ map: 21.32 kB
|
|
791
791
|
dist/components/PlSvg/PlSvg.vue_vue_type_script_setup_true_lang.js 39.41 kB │ gzip: 3.40 kB │ map: 8.66 kB
|
|
792
792
|
|
|
793
|
-
[32m✓ built in
|
|
793
|
+
[32m✓ built in 8.95s[39m
|
|
794
794
|
Build completed successfully
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @milaboratories/uikit@2.15.
|
|
3
|
+
> @milaboratories/uikit@2.15.34 formatter:check /home/runner/_work/platforma/platforma/lib/ui/uikit
|
|
4
4
|
> ts-builder formatter --check
|
|
5
5
|
|
|
6
6
|
Checking formatting...
|
|
@@ -8,5 +8,5 @@ Checking formatting...
|
|
|
8
8
|
Checking formatting...
|
|
9
9
|
|
|
10
10
|
All matched files use the correct format.
|
|
11
|
-
Finished in
|
|
11
|
+
Finished in 4101ms on 383 files using 16 threads.
|
|
12
12
|
Format check completed successfully
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @milaboratories/uikit@2.15.
|
|
3
|
+
> @milaboratories/uikit@2.15.34 linter:check /home/runner/_work/platforma/platforma/lib/ui/uikit
|
|
4
4
|
> ts-builder linter --check
|
|
5
5
|
|
|
6
6
|
Linting project...
|
|
7
7
|
↳ oxlint --config /home/runner/_work/platforma/platforma/lib/ui/uikit/.oxlintrc.json --deny-warnings
|
|
8
8
|
Found 0 warnings and 0 errors.
|
|
9
|
-
Finished in
|
|
9
|
+
Finished in 27ms on 310 files with 108 rules using 16 threads.
|
|
10
10
|
Linting completed successfully
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @milaboratories/uikit@2.15.
|
|
3
|
+
> @milaboratories/uikit@2.15.34 types:check /home/runner/_work/platforma/platforma/lib/ui/uikit
|
|
4
4
|
> ts-builder type-check --target browser-lib
|
|
5
5
|
|
|
6
6
|
↳ vue-tsc-ts6.cjs --noEmit --project ./tsconfig.json --customConditions default
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @milaboratories/uikit
|
|
2
2
|
|
|
3
|
+
## 2.15.34
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @platforma-sdk/model@1.84.3
|
|
8
|
+
|
|
9
|
+
## 2.15.33
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 43e07a3: Fix an infinite grid-remount loop in `PlAgDataTableV2` that recreated the whole
|
|
14
|
+
AG Grid around twenty times a second — strobing the column headers and filling
|
|
15
|
+
the console with AG Grid licence banners — on opening a page whose table had a
|
|
16
|
+
saved grid state, most often right after a block rebuild.
|
|
17
|
+
|
|
18
|
+
`computedCached`'s `writeThrough` made a set visible to readers immediately, but
|
|
19
|
+
the cache was still overwritten whenever the source re-emitted. A set is
|
|
20
|
+
debounced, so between the write and its arrival in the project state the source
|
|
21
|
+
still holds the value the write moved away from; a running block has that state
|
|
22
|
+
pushed back repeatedly, and each push reverted the cache. The stored grid state
|
|
23
|
+
therefore flipped between what the grid had and what the project still held, and
|
|
24
|
+
every flip made the reload watch destroy and recreate the grid — which, because
|
|
25
|
+
the flips never stopped on their own, never converged.
|
|
26
|
+
|
|
27
|
+
A write-through value now stays authoritative until the source reports it back.
|
|
28
|
+
Since `get` maps set values to themselves, that is exactly when the round trip
|
|
29
|
+
has completed; a change from elsewhere arriving mid-flight is dropped in favour
|
|
30
|
+
of the local write that is about to land.
|
|
31
|
+
|
|
3
32
|
## 2.15.32
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
|
@@ -6,6 +6,17 @@ import { ComputedGetter, ComputedSetter, ComputedRef, WritableComputedRef } from
|
|
|
6
6
|
* With `writeThrough`, a set updates the cache synchronously, so a read reflects
|
|
7
7
|
* the write immediately even when `set` defers its work (e.g. debounced); the
|
|
8
8
|
* getter must then map set values to themselves (`get(x)` deep-equals `x`).
|
|
9
|
+
*
|
|
10
|
+
* A deferred set also leaves a window in which the source still holds the value
|
|
11
|
+
* the write moved away from, and anything that re-emits the source during that
|
|
12
|
+
* window — a running block having its project state pushed back, say — used to
|
|
13
|
+
* revert the cache to it. The next write moved the cache forward again: a
|
|
14
|
+
* ping-pong that never settled, and that whoever watches the value (the data
|
|
15
|
+
* table rebuilds its whole grid) pays for on every swing. So a write-through
|
|
16
|
+
* value stays authoritative until the source reports it back; since `get` maps
|
|
17
|
+
* set values to themselves, that is exactly when the round trip has completed.
|
|
18
|
+
* A change from elsewhere that arrives mid-flight is therefore dropped in
|
|
19
|
+
* favour of the local write, which is about to land anyway.
|
|
9
20
|
*/
|
|
10
21
|
export declare function computedCached<T>(options: {
|
|
11
22
|
get: ComputedGetter<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computedCached.d.ts","sourceRoot":"","sources":["../../src/composition/computedCached.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACzB,MAAM,KAAK,CAAC;AAEb
|
|
1
|
+
{"version":3,"file":"computedCached.d.ts","sourceRoot":"","sources":["../../src/composition/computedCached.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACzB,MAAM,KAAK,CAAC;AAEb;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE;IACzC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACvB,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAC3B,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -4,13 +4,17 @@ import { deepClone as r, isJsonEqual as i } from "@milaboratories/helpers";
|
|
|
4
4
|
function a(a) {
|
|
5
5
|
let o, s, c = !1;
|
|
6
6
|
typeof a == "function" ? o = a : (o = a.get, s = a.set, c = a.writeThrough ?? !1);
|
|
7
|
-
let l = t(o());
|
|
7
|
+
let l = t(o()), u = !1;
|
|
8
8
|
return n(o, (e) => {
|
|
9
|
-
i(e, l.value)
|
|
9
|
+
if (i(e, l.value)) {
|
|
10
|
+
u = !1;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
u || (l.value = r(e));
|
|
10
14
|
}, { deep: !0 }), s ? e({
|
|
11
15
|
get: () => l.value,
|
|
12
16
|
set: c ? (e) => {
|
|
13
|
-
i(e, l.value) || (l.value = r(e)), s(e);
|
|
17
|
+
i(e, l.value) || (l.value = r(e), u = !0), s(e);
|
|
14
18
|
} : s
|
|
15
19
|
}) : l;
|
|
16
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computedCached.js","names":[],"sources":["../../src/composition/computedCached.ts"],"sourcesContent":["import { deepClone, isJsonEqual } from \"@milaboratories/helpers\";\nimport {\n computed,\n ref,\n watch,\n type ComputedGetter,\n type ComputedSetter,\n type ComputedRef,\n type WritableComputedRef,\n} from \"vue\";\n\n/**\n * Alternative to `computed`, but triggering only on actual data changes.\n * Always `deep` as the plain `computed` is.\n *\n * With `writeThrough`, a set updates the cache synchronously, so a read reflects\n * the write immediately even when `set` defers its work (e.g. debounced); the\n * getter must then map set values to themselves (`get(x)` deep-equals `x`).\n */\nexport function computedCached<T>(options: {\n get: ComputedGetter<T>;\n set: ComputedSetter<T>;\n writeThrough?: boolean;\n}): WritableComputedRef<T>;\nexport function computedCached<T>(getter: ComputedGetter<T>): ComputedRef<T>;\nexport function computedCached<T>(\n arg:\n | ComputedGetter<T>\n | {\n get: ComputedGetter<T>;\n set: ComputedSetter<T>;\n writeThrough?: boolean;\n },\n) {\n let getter: ComputedGetter<T>;\n let setter: ComputedSetter<T> | undefined = undefined;\n let writeThrough = false;\n if (typeof arg === \"function\") {\n getter = arg;\n } else {\n getter = arg.get;\n setter = arg.set;\n writeThrough = arg.writeThrough ?? false;\n }\n\n const cachedValue = ref<T>(getter());\n watch(\n getter,\n (newValue) => {\n if (
|
|
1
|
+
{"version":3,"file":"computedCached.js","names":[],"sources":["../../src/composition/computedCached.ts"],"sourcesContent":["import { deepClone, isJsonEqual } from \"@milaboratories/helpers\";\nimport {\n computed,\n ref,\n watch,\n type ComputedGetter,\n type ComputedSetter,\n type ComputedRef,\n type WritableComputedRef,\n} from \"vue\";\n\n/**\n * Alternative to `computed`, but triggering only on actual data changes.\n * Always `deep` as the plain `computed` is.\n *\n * With `writeThrough`, a set updates the cache synchronously, so a read reflects\n * the write immediately even when `set` defers its work (e.g. debounced); the\n * getter must then map set values to themselves (`get(x)` deep-equals `x`).\n *\n * A deferred set also leaves a window in which the source still holds the value\n * the write moved away from, and anything that re-emits the source during that\n * window — a running block having its project state pushed back, say — used to\n * revert the cache to it. The next write moved the cache forward again: a\n * ping-pong that never settled, and that whoever watches the value (the data\n * table rebuilds its whole grid) pays for on every swing. So a write-through\n * value stays authoritative until the source reports it back; since `get` maps\n * set values to themselves, that is exactly when the round trip has completed.\n * A change from elsewhere that arrives mid-flight is therefore dropped in\n * favour of the local write, which is about to land anyway.\n */\nexport function computedCached<T>(options: {\n get: ComputedGetter<T>;\n set: ComputedSetter<T>;\n writeThrough?: boolean;\n}): WritableComputedRef<T>;\nexport function computedCached<T>(getter: ComputedGetter<T>): ComputedRef<T>;\nexport function computedCached<T>(\n arg:\n | ComputedGetter<T>\n | {\n get: ComputedGetter<T>;\n set: ComputedSetter<T>;\n writeThrough?: boolean;\n },\n) {\n let getter: ComputedGetter<T>;\n let setter: ComputedSetter<T> | undefined = undefined;\n let writeThrough = false;\n if (typeof arg === \"function\") {\n getter = arg;\n } else {\n getter = arg.get;\n setter = arg.set;\n writeThrough = arg.writeThrough ?? false;\n }\n\n const cachedValue = ref<T>(getter());\n /** A write-through value the source has not reported back yet. */\n let writePending = false;\n watch(\n getter,\n (newValue) => {\n if (isJsonEqual(newValue, cachedValue.value)) {\n // The source has caught up with the write (or never diverged from it).\n writePending = false;\n return;\n }\n if (writePending) return;\n // `deepClone` is needed because in case some fields are patched the deep would be triggered,\n // but objects would be equal as the saved value was also patched\n cachedValue.value = deepClone(newValue);\n },\n { deep: true },\n );\n\n if (setter) {\n return computed({\n get: () => cachedValue.value,\n set: writeThrough\n ? (newValue) => {\n // Reflect the value in the cache now; `set` itself may defer its work.\n if (!isJsonEqual(newValue, cachedValue.value)) {\n cachedValue.value = deepClone(newValue);\n writePending = true;\n }\n setter(newValue);\n }\n : setter,\n });\n } else {\n return cachedValue;\n }\n}\n"],"mappings":";;;AAoCA,SAAgB,EACd,GAOA;CACA,IAAI,GACA,GACA,IAAe;AACnB,CAAI,OAAO,KAAQ,aACjB,IAAS,KAET,IAAS,EAAI,KACb,IAAS,EAAI,KACb,IAAe,EAAI,gBAAgB;CAGrC,IAAM,IAAc,EAAO,GAAQ,CAAC,EAEhC,IAAe;AAgCjB,QA/BF,EACE,IACC,MAAa;AACZ,MAAI,EAAY,GAAU,EAAY,MAAM,EAAE;AAE5C,OAAe;AACf;;AAEE,QAGJ,EAAY,QAAQ,EAAU,EAAS;IAEzC,EAAE,MAAM,IAAM,CACf,EAEG,IACK,EAAS;EACd,WAAW,EAAY;EACvB,KAAK,KACA,MAAa;AAMZ,GAJK,EAAY,GAAU,EAAY,MAAM,KAC3C,EAAY,QAAQ,EAAU,EAAS,EACvC,IAAe,KAEjB,EAAO,EAAS;MAElB;EACL,CAAC,GAEK"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/uikit",
|
|
3
|
-
"version": "2.15.
|
|
3
|
+
"version": "2.15.34",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"resize-observer-polyfill": "^1.5.1",
|
|
32
32
|
"sortablejs": "^1.15.6",
|
|
33
33
|
"vue": "3.5.24",
|
|
34
|
-
"@
|
|
35
|
-
"@
|
|
34
|
+
"@platforma-sdk/model": "1.84.3",
|
|
35
|
+
"@milaboratories/helpers": "1.14.5"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@vitest/coverage-istanbul": "^4.1.3",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"typescript": "7.0.2",
|
|
42
42
|
"vitest": "^4.1.3",
|
|
43
43
|
"@milaboratories/ts-builder": "1.7.2",
|
|
44
|
-
"@milaboratories/
|
|
45
|
-
"@milaboratories/
|
|
44
|
+
"@milaboratories/ts-configs": "1.4.0",
|
|
45
|
+
"@milaboratories/build-configs": "2.0.2"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"dev": "ts-builder serve --target browser-lib --build-config ./build.browser-lib.config.js",
|
|
@@ -16,6 +16,17 @@ import {
|
|
|
16
16
|
* With `writeThrough`, a set updates the cache synchronously, so a read reflects
|
|
17
17
|
* the write immediately even when `set` defers its work (e.g. debounced); the
|
|
18
18
|
* getter must then map set values to themselves (`get(x)` deep-equals `x`).
|
|
19
|
+
*
|
|
20
|
+
* A deferred set also leaves a window in which the source still holds the value
|
|
21
|
+
* the write moved away from, and anything that re-emits the source during that
|
|
22
|
+
* window — a running block having its project state pushed back, say — used to
|
|
23
|
+
* revert the cache to it. The next write moved the cache forward again: a
|
|
24
|
+
* ping-pong that never settled, and that whoever watches the value (the data
|
|
25
|
+
* table rebuilds its whole grid) pays for on every swing. So a write-through
|
|
26
|
+
* value stays authoritative until the source reports it back; since `get` maps
|
|
27
|
+
* set values to themselves, that is exactly when the round trip has completed.
|
|
28
|
+
* A change from elsewhere that arrives mid-flight is therefore dropped in
|
|
29
|
+
* favour of the local write, which is about to land anyway.
|
|
19
30
|
*/
|
|
20
31
|
export function computedCached<T>(options: {
|
|
21
32
|
get: ComputedGetter<T>;
|
|
@@ -44,14 +55,20 @@ export function computedCached<T>(
|
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
const cachedValue = ref<T>(getter());
|
|
58
|
+
/** A write-through value the source has not reported back yet. */
|
|
59
|
+
let writePending = false;
|
|
47
60
|
watch(
|
|
48
61
|
getter,
|
|
49
62
|
(newValue) => {
|
|
50
|
-
if (
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
63
|
+
if (isJsonEqual(newValue, cachedValue.value)) {
|
|
64
|
+
// The source has caught up with the write (or never diverged from it).
|
|
65
|
+
writePending = false;
|
|
66
|
+
return;
|
|
54
67
|
}
|
|
68
|
+
if (writePending) return;
|
|
69
|
+
// `deepClone` is needed because in case some fields are patched the deep would be triggered,
|
|
70
|
+
// but objects would be equal as the saved value was also patched
|
|
71
|
+
cachedValue.value = deepClone(newValue);
|
|
55
72
|
},
|
|
56
73
|
{ deep: true },
|
|
57
74
|
);
|
|
@@ -62,7 +79,10 @@ export function computedCached<T>(
|
|
|
62
79
|
set: writeThrough
|
|
63
80
|
? (newValue) => {
|
|
64
81
|
// Reflect the value in the cache now; `set` itself may defer its work.
|
|
65
|
-
if (!isJsonEqual(newValue, cachedValue.value))
|
|
82
|
+
if (!isJsonEqual(newValue, cachedValue.value)) {
|
|
83
|
+
cachedValue.value = deepClone(newValue);
|
|
84
|
+
writePending = true;
|
|
85
|
+
}
|
|
66
86
|
setter(newValue);
|
|
67
87
|
}
|
|
68
88
|
: setter,
|