ripple 0.2.147 → 0.2.148
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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Ripple is an elegant TypeScript UI framework",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.148",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -81,6 +81,6 @@
|
|
|
81
81
|
"typescript": "^5.9.2"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
|
-
"ripple": "0.2.
|
|
84
|
+
"ripple": "0.2.148"
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -45,8 +45,6 @@ function mark_control_flow_has_template(path) {
|
|
|
45
45
|
|
|
46
46
|
function visit_function(node, context) {
|
|
47
47
|
node.metadata = {
|
|
48
|
-
hoisted: false,
|
|
49
|
-
hoisted_params: [],
|
|
50
48
|
scope: context.state.scope,
|
|
51
49
|
tracked: false,
|
|
52
50
|
};
|
|
@@ -722,12 +720,7 @@ const visitors = {
|
|
|
722
720
|
const handler = visit(attr.value, state);
|
|
723
721
|
const delegated_event = get_delegated_event(event_name, handler, state);
|
|
724
722
|
|
|
725
|
-
if (delegated_event
|
|
726
|
-
if (delegated_event.hoisted) {
|
|
727
|
-
delegated_event.function.metadata.hoisted = true;
|
|
728
|
-
delegated_event.hoisted = true;
|
|
729
|
-
}
|
|
730
|
-
|
|
723
|
+
if (delegated_event) {
|
|
731
724
|
if (attr.metadata === undefined) {
|
|
732
725
|
attr.metadata = {};
|
|
733
726
|
}
|
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
} from '../../../../constants.js';
|
|
18
18
|
import { sanitize_template_string } from '../../../../utils/sanitize_template_string.js';
|
|
19
19
|
import {
|
|
20
|
-
build_hoisted_params,
|
|
21
20
|
is_inside_component,
|
|
22
21
|
build_assignment,
|
|
23
22
|
visit_assignment_expression,
|
|
@@ -75,16 +74,6 @@ function visit_function(node, context) {
|
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
if (metadata?.hoisted === true) {
|
|
79
|
-
const params = build_hoisted_params(node, context);
|
|
80
|
-
|
|
81
|
-
return /** @type {FunctionExpression} */ ({
|
|
82
|
-
...node,
|
|
83
|
-
params,
|
|
84
|
-
body: context.visit(node.body, state),
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
77
|
let body = context.visit(node.body, {
|
|
89
78
|
...state,
|
|
90
79
|
// we are new context so tracking no longer applies
|
|
@@ -132,13 +121,7 @@ function visit_head_element(node, context) {
|
|
|
132
121
|
'_$_.head',
|
|
133
122
|
b.arrow(
|
|
134
123
|
[b.id('__anchor')],
|
|
135
|
-
b.block([
|
|
136
|
-
...init,
|
|
137
|
-
...update.map((u) => {
|
|
138
|
-
debugger;
|
|
139
|
-
}),
|
|
140
|
-
...final,
|
|
141
|
-
]),
|
|
124
|
+
b.block([...init, ...update.map((u) => u.operation), ...final]),
|
|
142
125
|
),
|
|
143
126
|
),
|
|
144
127
|
);
|
|
@@ -985,21 +968,7 @@ const visitors = {
|
|
|
985
968
|
state.events.add(event_name);
|
|
986
969
|
}
|
|
987
970
|
|
|
988
|
-
|
|
989
|
-
if (attr.metadata.delegated.hoisted) {
|
|
990
|
-
if (attr.metadata.delegated.function === attr.value) {
|
|
991
|
-
const func_name = state.scope.root.unique('on_' + event_name);
|
|
992
|
-
state.hoisted.push(b.var(func_name, handler));
|
|
993
|
-
handler = func_name;
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
const hoisted_params = /** @type {Expression[]} */ (
|
|
997
|
-
attr.metadata.delegated.function.metadata.hoisted_params
|
|
998
|
-
);
|
|
999
|
-
|
|
1000
|
-
const args = [handler, b.id('__block'), ...hoisted_params];
|
|
1001
|
-
delegated_assignment = b.array(args);
|
|
1002
|
-
} else if (
|
|
971
|
+
if (
|
|
1003
972
|
(handler.type === 'Identifier' &&
|
|
1004
973
|
is_declared_function_within_component(handler, context)) ||
|
|
1005
974
|
handler.type === 'ArrowFunctionExpression' ||
|
|
@@ -2125,7 +2094,6 @@ function transform_ts_child(node, context) {
|
|
|
2125
2094
|
.map((child) => visit(child, state))
|
|
2126
2095
|
.filter((child) => child.type !== 'JSXText' || child.value.trim() !== '');
|
|
2127
2096
|
|
|
2128
|
-
debugger;
|
|
2129
2097
|
state.init.push(b.stmt(b.jsx_fragment(children)));
|
|
2130
2098
|
} else {
|
|
2131
2099
|
throw new Error('TODO');
|
|
@@ -323,8 +323,5 @@ export interface TransformContext {
|
|
|
323
323
|
* Delegated event result
|
|
324
324
|
*/
|
|
325
325
|
export interface DelegatedEventResult {
|
|
326
|
-
/** Whether event was hoisted */
|
|
327
|
-
hoisted: boolean;
|
|
328
|
-
/** The hoisted function */
|
|
329
326
|
function?: FunctionExpression | FunctionDeclaration | ArrowFunctionExpression;
|
|
330
327
|
}
|
package/src/compiler/utils.js
CHANGED
|
@@ -169,206 +169,19 @@ export function is_dom_property(name) {
|
|
|
169
169
|
return DOM_PROPERTIES.includes(name);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
const unhoisted = { hoisted: false };
|
|
173
|
-
|
|
174
172
|
/**
|
|
175
|
-
* Determines if an event handler can be
|
|
173
|
+
* Determines if an event handler can be delegated
|
|
176
174
|
* @param {string} event_name
|
|
177
175
|
* @param {Expression} handler
|
|
178
176
|
* @param {CompilerState} state
|
|
179
|
-
* @returns {
|
|
177
|
+
* @returns {boolean}
|
|
180
178
|
*/
|
|
181
179
|
export function get_delegated_event(event_name, handler, state) {
|
|
182
180
|
// Handle delegated event handlers. Bail out if not a delegated event.
|
|
183
181
|
if (!handler || !is_delegated(event_name)) {
|
|
184
|
-
return
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/** @type {FunctionExpression | FunctionDeclaration | ArrowFunctionExpression | null} */
|
|
188
|
-
let target_function = null;
|
|
189
|
-
let binding = null;
|
|
190
|
-
|
|
191
|
-
if (handler.type === 'ArrowFunctionExpression' || handler.type === 'FunctionExpression') {
|
|
192
|
-
target_function = handler;
|
|
193
|
-
} else if (handler.type === 'Identifier') {
|
|
194
|
-
binding = state.scope.get(handler.name);
|
|
195
|
-
|
|
196
|
-
if (state.analysis.module.scope.references.has(handler.name)) {
|
|
197
|
-
// If a binding with the same name is referenced in the module scope (even if not declared there), bail out
|
|
198
|
-
return unhoisted;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (binding != null) {
|
|
202
|
-
for (const { path } of binding.references) {
|
|
203
|
-
const parent = path.at(-1);
|
|
204
|
-
if (parent === undefined) {
|
|
205
|
-
return unhoisted;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const grandparent = path.at(-2);
|
|
209
|
-
|
|
210
|
-
/** @type {Element | null} */
|
|
211
|
-
let element = null;
|
|
212
|
-
/** @type {string | null} */
|
|
213
|
-
let event_name = null;
|
|
214
|
-
if (
|
|
215
|
-
parent.type === 'Expression' &&
|
|
216
|
-
grandparent?.type === 'Attribute' &&
|
|
217
|
-
is_event_attribute(grandparent)
|
|
218
|
-
) {
|
|
219
|
-
element = /** @type {Element} */ (path.at(-3));
|
|
220
|
-
const attribute = /** @type {Attribute} */ (grandparent);
|
|
221
|
-
event_name = get_attribute_event_name(attribute.name.name);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (element && event_name) {
|
|
225
|
-
if (
|
|
226
|
-
element.type !== 'Element' ||
|
|
227
|
-
element.metadata.has_spread ||
|
|
228
|
-
!is_delegated(event_name)
|
|
229
|
-
) {
|
|
230
|
-
return unhoisted;
|
|
231
|
-
}
|
|
232
|
-
} else if (
|
|
233
|
-
parent.type !== 'FunctionDeclaration' &&
|
|
234
|
-
parent.type !== 'VariableDeclarator' &&
|
|
235
|
-
parent.type !== 'Attribute'
|
|
236
|
-
) {
|
|
237
|
-
return unhoisted;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// If the binding is exported, bail out
|
|
243
|
-
if (
|
|
244
|
-
state.analysis?.exports?.find(
|
|
245
|
-
(/** @type {{name: string}} */ node) => node.name === handler.name,
|
|
246
|
-
)
|
|
247
|
-
) {
|
|
248
|
-
return unhoisted;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
if (binding !== null && binding.initial !== null && !binding.updated && !binding.is_called) {
|
|
252
|
-
const binding_type = binding.initial.type;
|
|
253
|
-
|
|
254
|
-
if (
|
|
255
|
-
binding_type === 'ArrowFunctionExpression' ||
|
|
256
|
-
binding_type === 'FunctionDeclaration' ||
|
|
257
|
-
binding_type === 'FunctionExpression'
|
|
258
|
-
) {
|
|
259
|
-
target_function = binding.initial;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// If we can't find a function, or the function has multiple parameters, bail out
|
|
265
|
-
if (target_function == null || target_function.params.length > 1) {
|
|
266
|
-
return unhoisted;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const visited_references = new Set();
|
|
270
|
-
const scope = target_function.metadata.scope;
|
|
271
|
-
for (const [reference, ref_nodes] of scope.references) {
|
|
272
|
-
// Bail out if the arguments keyword is used or $host is referenced
|
|
273
|
-
if (reference === 'arguments') return unhoisted;
|
|
274
|
-
|
|
275
|
-
const binding = scope.get(reference);
|
|
276
|
-
const local_binding = state.scope.get(reference);
|
|
277
|
-
|
|
278
|
-
if (local_binding === null || binding == null) {
|
|
279
|
-
return unhoisted;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// If we are referencing a binding that is shadowed in another scope then bail out.
|
|
283
|
-
if (local_binding.node !== binding.node) {
|
|
284
|
-
return unhoisted;
|
|
285
|
-
}
|
|
286
|
-
const is_tracked = ref_nodes.some(({ node }) => node.tracked);
|
|
287
|
-
|
|
288
|
-
if (
|
|
289
|
-
binding !== null &&
|
|
290
|
-
// Bail out if the the binding is a rest param
|
|
291
|
-
(binding.declaration_kind === 'rest_param' || // or any normal not reactive bindings that are mutated.
|
|
292
|
-
// Bail out if we reference anything from the EachBlock (for now) that mutates in non-runes mode,
|
|
293
|
-
(binding.kind === 'normal' && !is_tracked && binding.updated))
|
|
294
|
-
) {
|
|
295
|
-
return unhoisted;
|
|
296
|
-
}
|
|
297
|
-
visited_references.add(reference);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return { hoisted: true, function: target_function };
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* @param {Node} node
|
|
305
|
-
* @param {TransformContext} context
|
|
306
|
-
* @returns {Identifier[]}
|
|
307
|
-
*/
|
|
308
|
-
function get_hoisted_params(node, context) {
|
|
309
|
-
const scope = context.state.scope;
|
|
310
|
-
|
|
311
|
-
/** @type {Identifier[]} */
|
|
312
|
-
const params = [];
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* We only want to push if it's not already present to avoid name clashing
|
|
316
|
-
* @param {Identifier} id
|
|
317
|
-
*/
|
|
318
|
-
function push_unique(id) {
|
|
319
|
-
if (!params.find((param) => param.name === id.name)) {
|
|
320
|
-
params.push(id);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
for (const [reference] of scope.references) {
|
|
325
|
-
let binding = scope.get(reference);
|
|
326
|
-
|
|
327
|
-
if (binding !== null && !scope.declarations.has(reference) && binding.initial !== node) {
|
|
328
|
-
if (binding.kind === 'prop') {
|
|
329
|
-
push_unique(b.id('__props'));
|
|
330
|
-
} else if (binding.kind === 'for_pattern') {
|
|
331
|
-
push_unique(binding.metadata.pattern);
|
|
332
|
-
} else if (binding.kind === 'prop_fallback') {
|
|
333
|
-
push_unique(b.id(binding.node.name));
|
|
334
|
-
} else if (
|
|
335
|
-
// imports don't need to be hoisted
|
|
336
|
-
binding.declaration_kind !== 'import'
|
|
337
|
-
) {
|
|
338
|
-
// create a copy to remove start/end tags which would mess up source maps
|
|
339
|
-
push_unique(b.id(binding.node.name));
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
return params;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Builds the parameter list for a hoisted function
|
|
348
|
-
* @param {FunctionDeclaration|FunctionExpression|ArrowFunctionExpression} node
|
|
349
|
-
* @param {TransformContext} context
|
|
350
|
-
* @returns {Pattern[]}
|
|
351
|
-
*/
|
|
352
|
-
export function build_hoisted_params(node, context) {
|
|
353
|
-
const hoisted_params = get_hoisted_params(node, context);
|
|
354
|
-
node.metadata.hoisted_params = hoisted_params;
|
|
355
|
-
|
|
356
|
-
/** @type {Pattern[]} */
|
|
357
|
-
const params = [];
|
|
358
|
-
|
|
359
|
-
if (node.params.length === 0) {
|
|
360
|
-
if (hoisted_params.length > 0) {
|
|
361
|
-
// For the event object
|
|
362
|
-
params.push(b.id(context.state.scope.generate('_')));
|
|
363
|
-
}
|
|
364
|
-
} else {
|
|
365
|
-
for (const param of node.params) {
|
|
366
|
-
params.push(/** @type {Pattern} */ (context.visit(param)));
|
|
367
|
-
}
|
|
182
|
+
return false;
|
|
368
183
|
}
|
|
369
|
-
|
|
370
|
-
params.push(...hoisted_params, b.id('__block'));
|
|
371
|
-
return params;
|
|
184
|
+
return true;
|
|
372
185
|
}
|
|
373
186
|
|
|
374
187
|
/**
|