@octane-xplat/patches 0.14.0 → 0.15.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@octane-xplat/patches",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "pnpm config dependency carrying the framework patch files",
5
5
  "keywords": [
6
6
  "framework",
@@ -1,20 +1,195 @@
1
1
  diff --git a/dist/driver.js b/dist/driver.js
2
- index c88828e30337ee566bc1a919940e58b4b0227aba..52cde3f8f8acffcc05a1db8e0fcd90515efc70f6 100644
2
+ index c88828e30337ee566bc1a919940e58b4b0227aba..5fcee7ffb92d8ddf937b65b27825cbb81944a195 100644
3
3
  --- a/dist/driver.js
4
4
  +++ b/dist/driver.js
5
- @@ -85,6 +85,11 @@ function setProp(node, view, name, value) {
5
+ @@ -56,15 +56,34 @@ function applyProps(node, props) {
6
+ }
7
+ }
8
+ /**
9
+ - * `update` carries the host's dynamic-prop snapshot; attributes that were
10
+ - * static in the compiled plan arrive only with `create`. Merge instead of
11
+ - * replace, or a first update would strip a node's static layout props.
12
+ + * `update` carries the host's complete prop bag: a key present in the last
13
+ + * applied bag but absent from the next is a removal, and the view state it
14
+ + * installed returns to the prop's documented default. `undefined` never
15
+ + * crosses the wire (the runtime elides it); `null` is "not supplied" for
16
+ + * props without an explicit nullable contract — both reset through setProp.
17
+ */
18
+ function updateProps(node, next) {
19
+ + const dropped = [];
20
+ + for (const name in node.props) {
21
+ + if (node.props[name] != null && !(name in next))
22
+ + dropped.push(name);
23
+ + }
24
+ applyProps(node, next);
25
+ - node.props = { ...node.props, ...next };
26
+ + for (const name of dropped) {
27
+ + resetProp(node, node.view, name);
28
+ + }
29
+ + node.props = next;
30
+ }
31
+ function setProp(node, view, name, value) {
32
+ + // Keep authored placement separate from Grid's computed native coordinates.
33
+ + // NativeScript does not retain a setter write equal to its default (row/col 0).
34
+ + if (name === 'row' || name === 'col' || name === 'rowSpan' || name === 'colSpan') {
35
+ + const key = Symbol.for('octane-xplat.grid-placement');
36
+ + const placement = view[key] ?? (view[key] = {});
37
+ + if (value == null || value === unsetValue) delete placement[name];
38
+ + else placement[name] = value;
39
+ + view.notify({ eventName: 'xplatGridPlacementChange', object: view });
40
+ + }
41
+ if (name === 'children' || name === 'key' || name === 'ref')
42
+ return;
43
+ // Event props arrive as their own `event` commands.
44
+ @@ -78,13 +97,28 @@ function setProp(node, view, name, value) {
45
+ return;
46
+ }
47
+ if (name === 'style') {
48
+ - applyStyle(view, value);
49
+ + applyStyle(node, view, value);
50
+ return;
51
+ }
52
+ if (name === 'renderItem' && view instanceof ListView) {
6
53
  setRenderItem(view, value ?? null, createNativeScriptRoot);
7
54
  return;
8
55
  }
9
- + // `undefined` means "prop not supplied" — skip the write. NativeScript
10
- + // native setters coerce it (e.g. editable → ios.userInteractionEnabled =
11
- + // NO) leaving dead UI that still has its JS listeners.
12
- + if (value === undefined)
56
+ + // `null`/`unsetValue` restore the prop's default rather than writing a
57
+ + // literal null through a native setter. `undefined` is a removal: skip it
58
+ + // when nothing applied (NativeScript setters coerce it badly) and reset
59
+ + // when a real value did.
60
+ + if (value == null || value === unsetValue) {
61
+ + if (value === undefined && node.props[name] == null)
62
+ + return;
63
+ + resetProp(node, view, name);
13
64
  + return;
65
+ + }
66
+ + // Capture the pre-prop value once so a plain (non-Property) field can be
67
+ + // restored when the prop is removed later.
68
+ + const defaults = (node.propDefaults ??= {});
69
+ + if (!(name in defaults))
70
+ + defaults[name] = view[name];
14
71
  // Core raises `<name>Change` for a script write exactly as for a user
15
72
  // edit; a controlled input must not see its own value come back as one.
16
73
  const echo = `${name}Change`;
17
- @@ -482,7 +487,7 @@ function applyCommand(container, command) {
74
+ @@ -99,6 +133,44 @@ function setProp(node, view, name, value) {
75
+ node.muted.delete(echo);
76
+ }
77
+ }
78
+ +/** Restore a removed prop to the value it holds when never supplied. */
79
+ +function resetProp(node, view, name) {
80
+ + if (view === null)
81
+ + return;
82
+ + if (name === 'children' || name === 'key' || name === 'ref')
83
+ + return;
84
+ + // `on*` handlers unbind through `event` commands, not props.
85
+ + if (EVENT_PROP.test(name))
86
+ + return;
87
+ + if (name === 'className' || name === 'class') {
88
+ + view.className = unsetValue;
89
+ + return;
90
+ + }
91
+ + if (name === 'style') {
92
+ + applyStyle(node, view, null);
93
+ + return;
94
+ + }
95
+ + if (name === 'renderItem' && view instanceof ListView) {
96
+ + setRenderItem(view, null, createNativeScriptRoot);
97
+ + return;
98
+ + }
99
+ + const echo = `${name}Change`;
100
+ + const listening = node.listeners.has(echo);
101
+ + if (listening)
102
+ + node.muted.add(echo);
103
+ + try {
104
+ + // Property/CssProperty setters consume the sentinel and restore the
105
+ + // declared default. A plain field stores it raw — detect that and
106
+ + // write back the captured pre-prop value instead.
107
+ + view[name] = unsetValue;
108
+ + if (view[name] === unsetValue)
109
+ + view[name] = node.propDefaults?.[name];
110
+ + }
111
+ + finally {
112
+ + if (listening)
113
+ + node.muted.delete(echo);
114
+ + }
115
+ +}
116
+ // `class`/`className` compose clsx-style on the DOM renderer; join arrays
117
+ // with spaces so NativeScript's class selectors can match each class.
118
+ function normalizeClass(value) {
119
+ @@ -112,15 +184,67 @@ function normalizeClass(value) {
120
+ .join(' ');
121
+ return '';
122
+ }
123
+ -function applyStyle(view, value) {
124
+ - if (value == null || value === unsetValue)
125
+ - return;
126
+ +/**
127
+ + * The `style` prop replaces wholesale — a key dropped or nulled since the last
128
+ + * apply resets what it installed (`unsetValue` clears a local CssProperty
129
+ + * value so the cascade can re-apply). String styles are parsed for their
130
+ + * declared names so a later object or removal can reset them.
131
+ + */
132
+ +function applyStyle(node, view, value) {
133
+ + const applied = node.styleKeys;
134
+ + node.styleKeys = undefined;
135
+ if (typeof value === 'string') {
136
+ + clearStyleKeys(view, applied);
137
+ view.setInlineStyle(value);
138
+ + node.styleKeys = inlineStyleKeys(value);
139
+ + return;
140
+ + }
141
+ + if (value == null || value === unsetValue || typeof value !== 'object') {
142
+ + clearStyleKeys(view, applied);
143
+ return;
144
+ }
145
+ - if (typeof value === 'object')
146
+ - Object.assign(view.style, value);
147
+ + if (applied !== undefined) {
148
+ + for (const key of applied) {
149
+ + if (!(key in value))
150
+ + unsetStyleKey(view, key);
151
+ + }
152
+ + }
153
+ + for (const [key, nextValue] of Object.entries(value)) {
154
+ + if (nextValue == null)
155
+ + unsetStyleKey(view, key);
156
+ + else
157
+ + view.style[key] = nextValue;
158
+ + }
159
+ + node.styleKeys = new Set(Object.keys(value));
160
+ +}
161
+ +function clearStyleKeys(view, keys) {
162
+ + if (keys === undefined)
163
+ + return;
164
+ + for (const key of keys)
165
+ + unsetStyleKey(view, key);
166
+ +}
167
+ +function unsetStyleKey(view, name) {
168
+ + const style = view.style;
169
+ + if (name.startsWith('--')) {
170
+ + style.setUnscopedCssVariable?.(name, unsetValue);
171
+ + return;
172
+ + }
173
+ + style[name] = unsetValue;
174
+ + // A style field outside the CssProperty registry stores the sentinel raw.
175
+ + if (style[name] === unsetValue)
176
+ + style[name] = undefined;
177
+ +}
178
+ +function inlineStyleKeys(style) {
179
+ + const keys = new Set();
180
+ + for (const declaration of style.split(';')) {
181
+ + const colon = declaration.indexOf(':');
182
+ + if (colon === -1)
183
+ + continue;
184
+ + const name = declaration.slice(0, colon).trim();
185
+ + if (name !== '')
186
+ + keys.add(name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()));
187
+ + }
188
+ + return keys;
189
+ }
190
+ /** Recompute a text host's `text` from its `#text` children. */
191
+ function syncText(parent) {
192
+ @@ -482,7 +606,7 @@ function applyCommand(container, command) {
18
193
  }
19
194
  export const nativeScriptDriver = {
20
195
  id: NATIVESCRIPT_RENDERER_ID,
@@ -0,0 +1,225 @@
1
+ diff --git a/dist/driver.js b/dist/driver.js
2
+ index 8bc563add4cb675a12651184b63805b10224274d..a10f12af74fd32a630b71811c3f10f9338d63a50 100644
3
+ --- a/dist/driver.js
4
+ +++ b/dist/driver.js
5
+ @@ -91,15 +91,34 @@
6
+ }
7
+ }
8
+ /**
9
+ - * `update` carries the host's dynamic-prop snapshot; attributes that were
10
+ - * static in the compiled plan arrive only with `create`. Merge instead of
11
+ - * replace, or a first update would strip a node's static layout props.
12
+ + * `update` carries the host's complete prop bag: a key present in the last
13
+ + * applied bag but absent from the next is a removal, and the view state it
14
+ + * installed returns to the prop's documented default. `undefined` never
15
+ + * crosses the wire (the runtime elides it); `null` is "not supplied" for
16
+ + * props without an explicit nullable contract — both reset through setProp.
17
+ */
18
+ function updateProps(node, next) {
19
+ + const dropped = [];
20
+ + for (const name in node.props) {
21
+ + if (node.props[name] != null && !(name in next))
22
+ + dropped.push(name);
23
+ + }
24
+ applyProps(node, next);
25
+ - node.props = { ...node.props, ...next };
26
+ + for (const name of dropped) {
27
+ + resetProp(node, node.view, name);
28
+ + }
29
+ + node.props = next;
30
+ }
31
+ function setProp(node, view, name, value) {
32
+ + // Keep authored placement separate from Grid's computed native coordinates.
33
+ + // NativeScript does not retain a setter write equal to its default (row/col 0).
34
+ + if (name === 'row' || name === 'col' || name === 'rowSpan' || name === 'colSpan') {
35
+ + const key = Symbol.for('octane-xplat.grid-placement');
36
+ + const placement = view[key] ?? (view[key] = {});
37
+ + if (value == null || value === unsetValue) delete placement[name];
38
+ + else placement[name] = value;
39
+ + view.notify({ eventName: 'xplatGridPlacementChange', object: view });
40
+ + }
41
+ if (name === 'children' || name === 'key' || name === 'ref')
42
+ return;
43
+ // Event props arrive as their own `event` commands.
44
+ @@ -113,13 +132,28 @@
45
+ return;
46
+ }
47
+ if (name === 'style') {
48
+ - applyStyle(view, value);
49
+ + applyStyle(node, view, value);
50
+ return;
51
+ }
52
+ if (name === 'renderItem' && view instanceof ListView) {
53
+ setRenderItem(view, value ?? null, createNativeScriptRoot);
54
+ return;
55
+ }
56
+ + // `null`/`unsetValue` restore the prop's default rather than writing a
57
+ + // literal null through a native setter. `undefined` is a removal: skip it
58
+ + // when nothing applied (NativeScript setters coerce it badly) and reset
59
+ + // when a real value did.
60
+ + if (value == null || value === unsetValue) {
61
+ + if (value === undefined && node.props[name] == null)
62
+ + return;
63
+ + resetProp(node, view, name);
64
+ + return;
65
+ + }
66
+ + // Capture the pre-prop value once so a plain (non-Property) field can be
67
+ + // restored when the prop is removed later.
68
+ + const defaults = (node.propDefaults ??= {});
69
+ + if (!(name in defaults))
70
+ + defaults[name] = view[name];
71
+ // Core raises `<name>Change` for a script write exactly as for a user
72
+ // edit; a controlled input must not see its own value come back as one.
73
+ const echo = `${name}Change`;
74
+ @@ -128,6 +162,44 @@
75
+ node.muted.add(echo);
76
+ try {
77
+ view[name] = value;
78
+ + }
79
+ + finally {
80
+ + if (listening)
81
+ + node.muted.delete(echo);
82
+ + }
83
+ +}
84
+ +/** Restore a removed prop to the value it holds when never supplied. */
85
+ +function resetProp(node, view, name) {
86
+ + if (view === null)
87
+ + return;
88
+ + if (name === 'children' || name === 'key' || name === 'ref')
89
+ + return;
90
+ + // `on*` handlers unbind through `event` commands, not props.
91
+ + if (EVENT_PROP.test(name))
92
+ + return;
93
+ + if (name === 'className' || name === 'class') {
94
+ + view.className = unsetValue;
95
+ + return;
96
+ + }
97
+ + if (name === 'style') {
98
+ + applyStyle(node, view, null);
99
+ + return;
100
+ + }
101
+ + if (name === 'renderItem' && view instanceof ListView) {
102
+ + setRenderItem(view, null, createNativeScriptRoot);
103
+ + return;
104
+ + }
105
+ + const echo = `${name}Change`;
106
+ + const listening = node.listeners.has(echo);
107
+ + if (listening)
108
+ + node.muted.add(echo);
109
+ + try {
110
+ + // Property/CssProperty setters consume the sentinel and restore the
111
+ + // declared default. A plain field stores it raw — detect that and
112
+ + // write back the captured pre-prop value instead.
113
+ + view[name] = unsetValue;
114
+ + if (view[name] === unsetValue)
115
+ + view[name] = node.propDefaults?.[name];
116
+ }
117
+ finally {
118
+ if (listening)
119
+ @@ -147,15 +219,67 @@
120
+ .join(' ');
121
+ return '';
122
+ }
123
+ -function applyStyle(view, value) {
124
+ - if (value == null || value === unsetValue)
125
+ - return;
126
+ +/**
127
+ + * The `style` prop replaces wholesale — a key dropped or nulled since the last
128
+ + * apply resets what it installed (`unsetValue` clears a local CssProperty
129
+ + * value so the cascade can re-apply). String styles are parsed for their
130
+ + * declared names so a later object or removal can reset them.
131
+ + */
132
+ +function applyStyle(node, view, value) {
133
+ + const applied = node.styleKeys;
134
+ + node.styleKeys = undefined;
135
+ if (typeof value === 'string') {
136
+ + clearStyleKeys(view, applied);
137
+ view.setInlineStyle(value);
138
+ + node.styleKeys = inlineStyleKeys(value);
139
+ return;
140
+ }
141
+ - if (typeof value === 'object')
142
+ - Object.assign(view.style, value);
143
+ + if (value == null || value === unsetValue || typeof value !== 'object') {
144
+ + clearStyleKeys(view, applied);
145
+ + return;
146
+ + }
147
+ + if (applied !== undefined) {
148
+ + for (const key of applied) {
149
+ + if (!(key in value))
150
+ + unsetStyleKey(view, key);
151
+ + }
152
+ + }
153
+ + for (const [key, nextValue] of Object.entries(value)) {
154
+ + if (nextValue == null)
155
+ + unsetStyleKey(view, key);
156
+ + else
157
+ + view.style[key] = nextValue;
158
+ + }
159
+ + node.styleKeys = new Set(Object.keys(value));
160
+ +}
161
+ +function clearStyleKeys(view, keys) {
162
+ + if (keys === undefined)
163
+ + return;
164
+ + for (const key of keys)
165
+ + unsetStyleKey(view, key);
166
+ +}
167
+ +function unsetStyleKey(view, name) {
168
+ + const style = view.style;
169
+ + if (name.startsWith('--')) {
170
+ + style.setUnscopedCssVariable?.(name, unsetValue);
171
+ + return;
172
+ + }
173
+ + style[name] = unsetValue;
174
+ + // A style field outside the CssProperty registry stores the sentinel raw.
175
+ + if (style[name] === unsetValue)
176
+ + style[name] = undefined;
177
+ +}
178
+ +function inlineStyleKeys(style) {
179
+ + const keys = new Set();
180
+ + for (const declaration of style.split(';')) {
181
+ + const colon = declaration.indexOf(':');
182
+ + if (colon === -1)
183
+ + continue;
184
+ + const name = declaration.slice(0, colon).trim();
185
+ + if (name !== '')
186
+ + keys.add(name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()));
187
+ + }
188
+ + return keys;
189
+ }
190
+ /** Recompute a text host's `text` from its `#text` children. */
191
+ function syncText(parent) {
192
+ @@ -641,7 +765,7 @@
193
+ }
194
+ export const nativeScriptDriver = {
195
+ id: NATIVESCRIPT_RENDERER_ID,
196
+ - capabilities: { text: 'host' },
197
+ + capabilities: { text: 'host', visibility: true },
198
+ events: {
199
+ classify(name) {
200
+ if (!EVENT_PROP.test(name))
201
+ diff --git a/dist/intrinsics.d.ts b/dist/intrinsics.d.ts
202
+ index 45a47cbbce199df9635852ca4cdb2849e9bbc83d..d555b50c08276e925132b2be9bb62302fe0a4228 100644
203
+ --- a/dist/intrinsics.d.ts
204
+ +++ b/dist/intrinsics.d.ts
205
+ @@ -24,9 +24,9 @@
206
+ */
207
+ import type * as NS from '@nativescript/core';
208
+ export type NativeScriptNode = unknown;
209
+ -type Ref<TInstance> = ((instance: TInstance | null) => void) | {
210
+ +type Ref<TInstance> = ((instance: TInstance | null) => void | (() => void)) | {
211
+ current: TInstance | null;
212
+ -} | null;
213
+ +} | readonly Ref<TInstance>[] | null | undefined;
214
+ /**
215
+ * The driver assigns every non-event prop onto the view instance, so a JSX
216
+ * attribute is a NativeScript view property rather than a DOM attribute.
217
+ @@ -117,7 +117,7 @@ export interface ListViewAttributes {
218
+ }
219
+ export interface OctaneAttributes<TInstance> {
220
+ key?: string | number;
221
+ - ref?: Ref<TInstance> | readonly Ref<TInstance>[];
222
+ + ref?: Ref<TInstance>;
223
+ children?: NativeScriptNode;
224
+ }
225
+ type Overridden = keyof CommonAttributes | keyof OctaneAttributes<unknown> | keyof CommonEvents<unknown>;
@@ -1,5 +1,5 @@
1
1
  diff --git a/dist/cjs/runtime.cjs b/dist/cjs/runtime.cjs
2
- index a035f05..9912e51 100644
2
+ index a035f05..e1c9ca1 100644
3
3
  --- a/dist/cjs/runtime.cjs
4
4
  +++ b/dist/cjs/runtime.cjs
5
5
  @@ -365,6 +365,7 @@ var import_stream_protocol = require("./stream-protocol.cjs");
@@ -18,6 +18,15 @@ index a035f05..9912e51 100644
18
18
  function useState(initial, slot) {
19
19
  const s = readStateHook(initial, slot, arguments.length === 1);
20
20
  return [s.value, s.setter];
21
+ @@ -9659,6 +9661,8 @@ function renderClientContextProvider(context, props, renderScope) {
22
+ ensureHooks(scope).set(CHILDREN_DIALECT_SLOT, dialect);
23
+ }
24
+ renderSharedBody(childrenAsBody(children), void 0, scope, void 0);
25
+ + } else {
26
+ + resetScopeChildren(scope);
27
+ }
28
+ }
29
+ let SHARED_BODY_SCOPE = null;
21
30
  diff --git a/dist/cjs/signals/client.cjs b/dist/cjs/signals/client.cjs
22
31
  index 28e2844..af40518 100644
23
32
  --- a/dist/cjs/signals/client.cjs
@@ -453,7 +462,7 @@ index 90848a6..474c2bb 100644
453
462
  + let specifiers = signalHelperImports.get(request);
454
463
  + if (specifiers === undefined) signalHelperImports.set(request, (specifiers = []));
455
464
  diff --git a/dist/node/runtime.js b/dist/node/runtime.js
456
- index 927d060..cef6b5b 100644
465
+ index 927d060..d311ac9 100644
457
466
  --- a/dist/node/runtime.js
458
467
  +++ b/dist/node/runtime.js
459
468
  @@ -185,6 +185,7 @@ import {
@@ -472,6 +481,15 @@ index 927d060..cef6b5b 100644
472
481
  function useState(initial, slot) {
473
482
  const s = readStateHook(initial, slot, arguments.length === 1);
474
483
  return [s.value, s.setter];
484
+ @@ -9532,6 +9534,8 @@ function renderClientContextProvider(context, props, renderScope) {
485
+ ensureHooks(scope).set(CHILDREN_DIALECT_SLOT, dialect);
486
+ }
487
+ renderSharedBody(childrenAsBody(children), void 0, scope, void 0);
488
+ + } else {
489
+ + resetScopeChildren(scope);
490
+ }
491
+ }
492
+ let SHARED_BODY_SCOPE = null;
475
493
  diff --git a/dist/node/signals/client.js b/dist/node/signals/client.js
476
494
  index 21a39c3..3f85700 100644
477
495
  --- a/dist/node/signals/client.js
@@ -1034,7 +1052,7 @@ index 6427a01..8049b78 100644
1034
1052
  createContext,
1035
1053
  createSubSlot,
1036
1054
  diff --git a/dist/runtime.js b/dist/runtime.js
1037
- index 67ace09..ef61a91 100644
1055
+ index 67ace09..afeb8ea 100644
1038
1056
  --- a/dist/runtime.js
1039
1057
  +++ b/dist/runtime.js
1040
1058
  @@ -184,6 +184,7 @@ import {
@@ -1053,6 +1071,15 @@ index 67ace09..ef61a91 100644
1053
1071
  function useState(initial, slot) {
1054
1072
  const s = readStateHook(initial, slot, arguments.length === 1);
1055
1073
  return [s.value, s.setter];
1074
+ @@ -9531,6 +9533,8 @@ function renderClientContextProvider(context, props, renderScope) {
1075
+ ensureHooks(scope).set(CHILDREN_DIALECT_SLOT, dialect);
1076
+ }
1077
+ renderSharedBody(childrenAsBody(children), void 0, scope, void 0);
1078
+ + } else {
1079
+ + resetScopeChildren(scope);
1080
+ }
1081
+ }
1082
+ let SHARED_BODY_SCOPE = null;
1056
1083
  diff --git a/dist/signals/client.d.ts b/dist/signals/client.d.ts
1057
1084
  index 6388c2f..f9e9862 100644
1058
1085
  --- a/dist/signals/client.d.ts