rooklang 0.4.1 → 0.4.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.
|
@@ -10,6 +10,12 @@ export declare function containsElement(node: ast.Node): boolean;
|
|
|
10
10
|
export declare function hasOptionalLink(node: ast.Expression): boolean;
|
|
11
11
|
export declare function endsWithJump(statements: readonly ast.Statement[]): boolean;
|
|
12
12
|
export declare function startsWithObjectLiteral(node: ast.Expression): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Function literals that an expression gives as its value, not to a call: `() => count++`, the
|
|
15
|
+
* branches of `ok ? save : () => {}`, the fields of `{ onSave: () => {...} }`. They run later, when
|
|
16
|
+
* whoever gets them calls them; a callback given to a call, as to `items.map`, may run right away.
|
|
17
|
+
*/
|
|
18
|
+
export declare function functionValues(node: ast.Expression): ast.Expression[];
|
|
13
19
|
/** The variable at the start of `a.b.c`, or `null`. */
|
|
14
20
|
export declare function rootName(node: ast.Expression): string | null;
|
|
15
21
|
/** Literals, which can be put into inlined code as they are. */
|
package/dist/codegen/analysis.js
CHANGED
|
@@ -104,6 +104,30 @@ export function startsWithObjectLiteral(node) {
|
|
|
104
104
|
return false;
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Function literals that an expression gives as its value, not to a call: `() => count++`, the
|
|
109
|
+
* branches of `ok ? save : () => {}`, the fields of `{ onSave: () => {...} }`. They run later, when
|
|
110
|
+
* whoever gets them calls them; a callback given to a call, as to `items.map`, may run right away.
|
|
111
|
+
*/
|
|
112
|
+
export function functionValues(node) {
|
|
113
|
+
switch (node.kind) {
|
|
114
|
+
case 'ArrowFunction':
|
|
115
|
+
case 'FuncExpression':
|
|
116
|
+
return [node];
|
|
117
|
+
case 'ConditionalExpression':
|
|
118
|
+
return [...functionValues(node.consequent), ...functionValues(node.alternate)];
|
|
119
|
+
case 'BinaryExpression':
|
|
120
|
+
return node.operator === '??' || node.operator === '||' || node.operator === '&&'
|
|
121
|
+
? [...functionValues(node.left), ...functionValues(node.right)]
|
|
122
|
+
: [];
|
|
123
|
+
case 'ArrayLiteral':
|
|
124
|
+
return node.elements.flatMap((element) => element.kind === 'SpreadElement' ? [] : functionValues(element));
|
|
125
|
+
case 'ObjectLiteral':
|
|
126
|
+
return node.properties.flatMap((property) => property.kind === 'Property' ? functionValues(property.value) : []);
|
|
127
|
+
default:
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
107
131
|
/** The variable at the start of `a.b.c`, or `null`. */
|
|
108
132
|
export function rootName(node) {
|
|
109
133
|
if (node.kind === 'Identifier')
|
|
@@ -19,6 +19,8 @@ export declare abstract class UpdateEmitter extends StatementEmitter {
|
|
|
19
19
|
* the markup, which would update it again; code that runs later (handlers) is not included.
|
|
20
20
|
*/
|
|
21
21
|
protected rendering: number;
|
|
22
|
+
/** Functions that live markup gives as values: they run later, not while it is rendered. */
|
|
23
|
+
private readonly later;
|
|
22
24
|
/**
|
|
23
25
|
* After a statement that changes state of the module, the updates of the components that read
|
|
24
26
|
* it; code that renders markup changes none, as with the state of a component.
|
|
@@ -41,9 +43,12 @@ export declare abstract class UpdateEmitter extends StatementEmitter {
|
|
|
41
43
|
protected liveFunction(node: ast.Expression): string;
|
|
42
44
|
/**
|
|
43
45
|
* An expression that is evaluated again on updates: elements inside it are created in place,
|
|
44
|
-
* so that each evaluation creates new ones.
|
|
46
|
+
* so that each evaluation creates new ones. A function that it gives as a value, as to a property
|
|
47
|
+
* `onAdd={() => count++}`, runs later, so what it changes updates the markup as it does in the
|
|
48
|
+
* value the markup was created with.
|
|
45
49
|
*/
|
|
46
50
|
protected liveExpression(node: ast.Expression, precedence?: number): string;
|
|
51
|
+
protected expression(node: ast.Expression, minPrecedence: number, forceParens?: boolean): string;
|
|
47
52
|
}
|
|
48
53
|
/**
|
|
49
54
|
* Replaces the markers of a component's sources: by the call of the update function, by the only
|
package/dist/codegen/updates.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { widenLiterals } from "../checker/types.js";
|
|
2
2
|
import { updatesOf } from "./reactive.js";
|
|
3
3
|
import { StatementEmitter } from "./statements.js";
|
|
4
|
-
import { startsWithObjectLiteral } from "./analysis.js";
|
|
4
|
+
import { functionValues, startsWithObjectLiteral } from "./analysis.js";
|
|
5
5
|
import { sharedWrites } from "./shared.js";
|
|
6
6
|
import { ARROW } from "./syntax.js";
|
|
7
7
|
/**
|
|
@@ -21,6 +21,8 @@ export class UpdateEmitter extends StatementEmitter {
|
|
|
21
21
|
* the markup, which would update it again; code that runs later (handlers) is not included.
|
|
22
22
|
*/
|
|
23
23
|
rendering = 0;
|
|
24
|
+
/** Functions that live markup gives as values: they run later, not while it is rendered. */
|
|
25
|
+
later = new WeakSet();
|
|
24
26
|
/**
|
|
25
27
|
* After a statement that changes state of the module, the updates of the components that read
|
|
26
28
|
* it; code that renders markup changes none, as with the state of a component.
|
|
@@ -157,11 +159,20 @@ export class UpdateEmitter extends StatementEmitter {
|
|
|
157
159
|
}
|
|
158
160
|
/**
|
|
159
161
|
* An expression that is evaluated again on updates: elements inside it are created in place,
|
|
160
|
-
* so that each evaluation creates new ones.
|
|
162
|
+
* so that each evaluation creates new ones. A function that it gives as a value, as to a property
|
|
163
|
+
* `onAdd={() => count++}`, runs later, so what it changes updates the markup as it does in the
|
|
164
|
+
* value the markup was created with.
|
|
161
165
|
*/
|
|
162
166
|
liveExpression(node, precedence = ARROW) {
|
|
167
|
+
for (const value of functionValues(node))
|
|
168
|
+
this.later.add(value);
|
|
163
169
|
return this.withRendering(this.rendering + 1, () => this.withHoisting(false, () => this.expression(node, precedence)));
|
|
164
170
|
}
|
|
171
|
+
expression(node, minPrecedence, forceParens = false) {
|
|
172
|
+
return this.later.has(node)
|
|
173
|
+
? this.withRendering(0, () => super.expression(node, minPrecedence, forceParens))
|
|
174
|
+
: super.expression(node, minPrecedence, forceParens);
|
|
175
|
+
}
|
|
165
176
|
}
|
|
166
177
|
/**
|
|
167
178
|
* Replaces the markers of a component's sources: by the call of the update function, by the only
|
package/package.json
CHANGED