steel-frame 7.2.1 → 7.2.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.
- package/README.md +2 -2
- package/build/babel-plugin/expression.js +3 -3
- package/build/babel-plugin/internal.d.ts +3 -3
- package/build/babel-plugin/jsx.js +38 -13
- package/build/babel-plugin/lib.d.ts +8 -2
- package/build/babel-plugin/lib.js +69 -15
- package/build/babel-plugin/mesh.js +16 -20
- package/build/babel-plugin/transformer.js +28 -13
- package/build/cli/lib/compile-lib.js +2 -0
- package/build/cli/vite-plugins/jsx.js +2 -0
- package/build/export/index.d.ts +3 -3
- package/package.json +4 -4
- package/build/cli/sf.d.ts +0 -2
- package/build/cli/sf.js +0 -2
package/README.md
CHANGED
|
@@ -135,8 +135,6 @@ We respect semantic versioning:
|
|
|
135
135
|
|
|
136
136
|
### 7.0 - 7.2
|
|
137
137
|
|
|
138
|
-
- **7.2**: Add tracking of the builtin models size. Reactive array/set/map can be converted into a builtin model.
|
|
139
|
-
- **7.1**: Add support for ARIA attributes.
|
|
140
138
|
- Add `debounced` and `field` functions, which extend the reativity system.
|
|
141
139
|
- Add `Zombie` component, it keeps HTML elements alive some time after destruction.
|
|
142
140
|
- Add `abortSignal` to cancel fetch requests and timers when component is destroyed.
|
|
@@ -154,6 +152,8 @@ We respect semantic versioning:
|
|
|
154
152
|
- New reactivity marks `r_` & `wr_` insted of `$`,
|
|
155
153
|
workaround with `v4-naming` compilation flag. **[API change]**
|
|
156
154
|
- Component files have strict structure (imports, export, helpers, CSS). **[API change]**
|
|
155
|
+
- `7.1`: Add support for ARIA attributes.
|
|
156
|
+
- `7.2`: Add tracking of the builtin models size. Reactive array/set/map can be converted into a builtin model.
|
|
157
157
|
|
|
158
158
|
### 6.0 RC (never released)
|
|
159
159
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
2
|
import { calledFn, calls, hintFunctions, isDiCall, unwrapFunctions } from "./call.js";
|
|
3
3
|
import { ctx, V, VariablesStatus } from "./internal.js";
|
|
4
|
-
import { checkNonReactiveName, err, Errors, forceReactiveName,
|
|
4
|
+
import { checkNonReactiveName, err, Errors, forceReactiveName, reactivityTypeOfNodePath } from "./lib.js";
|
|
5
5
|
import { checkStyleUsage, ignoreParams, meshAllUnknown, meshExpression } from "./mesh.js";
|
|
6
6
|
import { routerReplace } from "./router.js";
|
|
7
7
|
import { stringify } from "./utils.js";
|
|
@@ -217,7 +217,7 @@ export function checkExpression(nodePath, search, allowOuterScope = false) {
|
|
|
217
217
|
if (arg1 &&
|
|
218
218
|
arg2 &&
|
|
219
219
|
arg1.isExpression() &&
|
|
220
|
-
|
|
220
|
+
reactivityTypeOfNodePath(arg1, search.external) === "writable" &&
|
|
221
221
|
arg2.isExpression()) {
|
|
222
222
|
checkExpression(arg2, search);
|
|
223
223
|
path.replaceWith(search.external.updateIValue(path.node, arg1.node, arg2.node));
|
|
@@ -248,7 +248,7 @@ export function checkExpression(nodePath, search, allowOuterScope = false) {
|
|
|
248
248
|
const path = nodePath;
|
|
249
249
|
const left = path.get("left");
|
|
250
250
|
const right = path.get("right");
|
|
251
|
-
if (
|
|
251
|
+
if (reactivityTypeOfNodePath(left, search.external)) {
|
|
252
252
|
err(Errors.RulesOfVasille, left, "Assigment are forbidden in live values and effects", search.external);
|
|
253
253
|
}
|
|
254
254
|
meshLValue(left, search.external);
|
|
@@ -90,9 +90,9 @@ export interface Internal {
|
|
|
90
90
|
expr(func: types.Expression, values: types.Expression[], codes: string[], area: types.Node, name: string | undefined, safe: boolean): types.Expression;
|
|
91
91
|
fieldRef(obj: types.Expression, field: types.Expression, area: types.Node, name?: string): types.Expression;
|
|
92
92
|
deepFieldRef(obj: types.Expression, fields: types.Expression[], area: types.Node, name?: string): types.Expression;
|
|
93
|
-
setModel(arg: types.Expression | types.SpreadElement | types.ArgumentPlaceholder | null, usage: types.Node, name: string | undefined): types.Expression;
|
|
94
|
-
mapModel(arg: types.Expression | types.SpreadElement | types.ArgumentPlaceholder | null, usage: types.Node, name: string | undefined): types.Expression;
|
|
95
|
-
arrayModel(arg: types.Expression | types.SpreadElement | types.ArgumentPlaceholder | null, usage: types.Node, name: string | undefined): types.Expression;
|
|
93
|
+
setModel(arg: types.Expression | types.SpreadElement | types.ArgumentPlaceholder | null, size: types.Expression | types.SpreadElement | types.ArgumentPlaceholder | null | undefined, usage: types.Node, name: string | undefined): types.Expression;
|
|
94
|
+
mapModel(arg: types.Expression | types.SpreadElement | types.ArgumentPlaceholder | null, size: types.Expression | types.SpreadElement | types.ArgumentPlaceholder | null | undefined, usage: types.Node, name: string | undefined): types.Expression;
|
|
95
|
+
arrayModel(arg: types.Expression | types.SpreadElement | types.ArgumentPlaceholder | null, length: types.Expression | types.SpreadElement | types.ArgumentPlaceholder | null | undefined, usage: types.Node, name: string | undefined): types.Expression;
|
|
96
96
|
ensure(arg: types.MemberExpression | types.OptionalMemberExpression, area: types.Node): types.Expression;
|
|
97
97
|
set(obj: types.Expression, field: types.Expression, value: types.Expression, area: types.Node): types.CallExpression;
|
|
98
98
|
safeInit(arg: types.Expression): types.Expression;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as t from "@babel/types";
|
|
2
2
|
import { ctx } from "./internal.js";
|
|
3
3
|
import { bodyHasJsx } from "./jsx-detect.js";
|
|
4
|
-
import { checkNonReactiveName, checkReactiveName, err, Errors, exprCall, isReactiveName, isReadableName, isWritableName, nodeIsUnsafe, reactivityTypeOfNode, toKebabCase, } from "./lib.js";
|
|
4
|
+
import { checkNonReactiveName, checkReactiveName, err, Errors, exprCall, isReactiveName, isReadableName, isWritableName, nodeIsUnsafe, reactivityTypeByName, reactivityTypeOfNode, reactivityTypeOfNodePath, replaceReactivityMark, toKebabCase, } from "./lib.js";
|
|
5
5
|
import { compose, meshExpression, processRefCall } from "./mesh.js";
|
|
6
6
|
import { nodeToStaticPosition } from "./transformer.js";
|
|
7
7
|
import { processFieldRefCall, toFieldRef } from "./field-reference.js";
|
|
8
8
|
import { calls } from "./call.js";
|
|
9
9
|
import { validateRouterPath } from "./router.js";
|
|
10
10
|
const strongSlotMap = {
|
|
11
|
-
ArrayView: ["
|
|
12
|
-
ArrayModelView: ["passive", "
|
|
13
|
-
MapModelView: ["
|
|
11
|
+
ArrayView: ["any", "readable"],
|
|
12
|
+
ArrayModelView: ["writable or passive", "readable"],
|
|
13
|
+
MapModelView: ["any", "passive"],
|
|
14
14
|
};
|
|
15
15
|
export function transformJsx(path, conditions, internal) {
|
|
16
16
|
if (path.isJSXElement()) {
|
|
@@ -535,7 +535,7 @@ function transformJsxElement(path, conditions, internal) {
|
|
|
535
535
|
const nameIsWritable = isWritableName(attrName, internal) && (!isReadableName(attrName, internal) || callsField);
|
|
536
536
|
let valueIsWritable = nameIsWritable &&
|
|
537
537
|
valuePath.isJSXExpressionContainer() &&
|
|
538
|
-
|
|
538
|
+
reactivityTypeOfNodePath(valuePath.get("expression"), internal) === "writable";
|
|
539
539
|
if (nameIsWritable !== valueIsWritable) {
|
|
540
540
|
let fieldRef;
|
|
541
541
|
// attr={field(wr_x.y)}
|
|
@@ -743,6 +743,22 @@ function transformJsxElement(path, conditions, internal) {
|
|
|
743
743
|
err(Errors.RulesOfVasille, path, "Malformed JSX ForEach tag must have value and slot", internal);
|
|
744
744
|
}
|
|
745
745
|
}
|
|
746
|
+
if (mapped && ["ArrayView", "ArrayModelView", "MapModelView"].includes(mapped)) {
|
|
747
|
+
const model = props.find(item => t.isObjectProperty(item) && t.isIdentifier(item.key) && item.key.name === "r_of");
|
|
748
|
+
const slot = props.find(item => t.isObjectProperty(item) && t.isIdentifier(item.key) && item.key.name === "slot");
|
|
749
|
+
if (slot &&
|
|
750
|
+
(t.isArrowFunctionExpression(slot.value) || t.isFunctionExpression(slot.value)) &&
|
|
751
|
+
t.isIdentifier(slot.value.params[1]) &&
|
|
752
|
+
reactivityTypeByName(slot.value.params[1].name, internal) === "writable") {
|
|
753
|
+
if (mapped === "ArrayView" && !(model && reactivityTypeOfNode(model.value, internal) === "writable")) {
|
|
754
|
+
const fixedName = replaceReactivityMark(slot.value.params[1].name, "");
|
|
755
|
+
err(Errors.RulesOfVasille, path, `Malformed ${mapped}: writable item in slot requires a writable collection. ` +
|
|
756
|
+
`Renaming ${slot.value.params[1].name} parameter to "${fixedName}" will fix this error.`, internal);
|
|
757
|
+
}
|
|
758
|
+
// add writable param to properties
|
|
759
|
+
props.push(t.objectProperty(t.identifier("writable"), t.booleanLiteral(true)));
|
|
760
|
+
}
|
|
761
|
+
}
|
|
746
762
|
function addAwait(node) {
|
|
747
763
|
if (internal.asyncComposing) {
|
|
748
764
|
return t.awaitExpression(node);
|
|
@@ -777,18 +793,27 @@ function precheckSlotParams(mapped, slot, internal) {
|
|
|
777
793
|
}
|
|
778
794
|
for (let i = 0; i < params.length && i < args.length; i++) {
|
|
779
795
|
const param = params[i];
|
|
780
|
-
|
|
796
|
+
const expected = args[i];
|
|
797
|
+
if (expected === "passive") {
|
|
798
|
+
/* istanbul ignore else */
|
|
799
|
+
if (param.isIdentifier()) {
|
|
800
|
+
checkNonReactiveName(param, internal);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
else {
|
|
781
804
|
if (!param.isIdentifier()) {
|
|
782
805
|
err(Errors.ParserError, slot, `The ${mapped} slot must have only identifiers as parameters`, internal);
|
|
783
806
|
}
|
|
784
807
|
else {
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
808
|
+
if (expected === "writable or passive") {
|
|
809
|
+
const type = reactivityTypeByName(param.node.name, internal);
|
|
810
|
+
if (type !== "writable" && type !== false) {
|
|
811
|
+
err(Errors.RulesOfVasille, param, "Expected writable or non reactive parameter.", internal);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
checkReactiveName(param, expected, internal);
|
|
816
|
+
}
|
|
792
817
|
}
|
|
793
818
|
}
|
|
794
819
|
}
|
|
@@ -24,17 +24,23 @@ export declare function ref(expr: types.Node | null | undefined, internal: Inter
|
|
|
24
24
|
export declare function arrayModel(args: types.CallExpression["arguments"], usage: types.Node, internal: Internal, name?: string): types.Expression;
|
|
25
25
|
export declare function setModel(args: types.CallExpression["arguments"], usage: types.Node, internal: Internal, name?: string): types.Expression;
|
|
26
26
|
export declare function mapModel(args: types.CallExpression["arguments"], usage: types.Node, internal: Internal, name?: string): types.Expression;
|
|
27
|
+
export declare function checkBuildInModelArgs(path: NodePath<types.CallExpression | types.OptionalCallExpression | types.NewExpression>, internal: Internal): (types.ArgumentPlaceholder | types.SpreadElement | types.Expression)[];
|
|
27
28
|
export declare function processModelCall(path: NodePath<types.CallExpression | types.NewExpression>, usage: types.Node, type: "Map" | "Set" | "Array", isConst: boolean, internal: Internal, name?: string): void;
|
|
28
29
|
export declare function checkReactiveName(idPath: NodePath<unknown>, type: ReactiveType, internal: Internal): void;
|
|
29
30
|
export declare function checkNonReactiveName(idPath: NodePath<Identifier>, internal: Internal): void;
|
|
30
31
|
export declare function toKebabCase(name: string): string;
|
|
31
|
-
export declare function pathIsReactiveValue(path: NodePath<
|
|
32
|
+
export declare function pathIsReactiveValue(path: NodePath<types.Node | null | undefined>, _type: "any", internal: Internal, checkForBreakpoints?: boolean): path is NodePath<types.MemberExpression | types.OptionalMemberExpression | types.Identifier>;
|
|
32
33
|
export declare function removeExtension(name: string): string;
|
|
33
34
|
export declare function isReadableName(name: string, internal: Internal): boolean;
|
|
34
35
|
export declare function isWritableName(name: string, internal: Internal): boolean;
|
|
35
36
|
export declare function reactivityTypeByName(name: string, internal: Internal): false | "any" | "readable" | "writable";
|
|
36
|
-
export declare function reactivityTypeOfNode(node:
|
|
37
|
+
export declare function reactivityTypeOfNode(node: types.Node, internal: Internal): ReactiveType | false;
|
|
38
|
+
export declare function reactivityTypeOfNodePath(path: NodePath<types.Node | null | undefined>, internal: Internal, checkForBreakpoints?: boolean): ReactiveType | false;
|
|
37
39
|
export type ReactiveType = "readable" | "writable" | "any";
|
|
38
40
|
export declare function isReactiveName(name: string, internal: Internal): boolean;
|
|
39
41
|
export declare function forceReactiveName(name: string, type: ReactiveType, path: NodePath<unknown>, internal: Internal): boolean;
|
|
42
|
+
export declare function forcePathIsWritable(path: NodePath<types.SpreadElement | types.ArgumentPlaceholder | types.Expression | null>, internal: Internal, accepts?: "undefined" | "any"): true | undefined;
|
|
40
43
|
export declare function leftIsThisInConstructor(left: NodePath<unknown>): boolean;
|
|
44
|
+
export type ReactivityMarks = "" | "wr_" | "r_" | "$";
|
|
45
|
+
export declare function replaceReactivityMark(name: string, with_: ReactivityMarks, v4?: boolean): string;
|
|
46
|
+
export declare function extractReactivityMark(name: string, v4?: boolean): ReactivityMarks;
|
|
@@ -2,7 +2,7 @@ import * as t from "@babel/types";
|
|
|
2
2
|
import { checkNode, exprIsSure } from "./expression.js";
|
|
3
3
|
import { ctx } from "./internal.js";
|
|
4
4
|
import { bindFunctions, calledFn, calls, hintFunctions, safeFunctions } from "./call.js";
|
|
5
|
-
import { meshAllUnknown } from "./mesh.js";
|
|
5
|
+
import { meshAllUnknown, meshExpression } from "./mesh.js";
|
|
6
6
|
import { nodeToStaticPosition } from "./transformer.js";
|
|
7
7
|
import { hasBreakPoint } from "./field-reference.js";
|
|
8
8
|
export var Errors;
|
|
@@ -137,20 +137,29 @@ export function ref(expr, internal, area, name, safe) {
|
|
|
137
137
|
return internal.ref(t.isExpression(expr) ? expr : null, area, name, safe);
|
|
138
138
|
}
|
|
139
139
|
export function arrayModel(args, usage, internal, name) {
|
|
140
|
-
return internal.arrayModel(args[0], usage, name);
|
|
140
|
+
return internal.arrayModel(args[0], args[1], usage, name);
|
|
141
141
|
}
|
|
142
142
|
export function setModel(args, usage, internal, name) {
|
|
143
|
-
return internal.setModel(args[0], usage, name);
|
|
143
|
+
return internal.setModel(args[0], args[1], usage, name);
|
|
144
144
|
}
|
|
145
145
|
export function mapModel(args, usage, internal, name) {
|
|
146
|
-
return internal.mapModel(args[0], usage, name);
|
|
146
|
+
return internal.mapModel(args[0], args[1], usage, name);
|
|
147
|
+
}
|
|
148
|
+
export function checkBuildInModelArgs(path, internal) {
|
|
149
|
+
const args = path.get("arguments");
|
|
150
|
+
if (args.length > 0) {
|
|
151
|
+
forcePathIsWritable(args[0], internal, "any");
|
|
152
|
+
if (args.length > 1) {
|
|
153
|
+
forcePathIsWritable(args[1], internal, "undefined");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return path.node.arguments;
|
|
147
157
|
}
|
|
148
158
|
export function processModelCall(path, usage, type, isConst, internal, name) {
|
|
149
|
-
const args = path
|
|
159
|
+
const args = checkBuildInModelArgs(path, internal);
|
|
150
160
|
if (!isConst) {
|
|
151
161
|
err(Errors.RulesOfVasille, path, `${type} models must be declared as constants`, internal);
|
|
152
162
|
}
|
|
153
|
-
meshAllUnknown(path.get("arguments"), internal, true);
|
|
154
163
|
path.replaceWith(type === "Map"
|
|
155
164
|
? mapModel(args, usage, internal, name)
|
|
156
165
|
: type === "Set"
|
|
@@ -181,7 +190,7 @@ export function toKebabCase(name) {
|
|
|
181
190
|
return fixed;
|
|
182
191
|
}
|
|
183
192
|
export function pathIsReactiveValue(path, _type, internal, checkForBreakpoints = true) {
|
|
184
|
-
return
|
|
193
|
+
return reactivityTypeOfNodePath(path, internal, checkForBreakpoints) !== false;
|
|
185
194
|
}
|
|
186
195
|
export function removeExtension(name) {
|
|
187
196
|
if (name.endsWith(".ts") || name.endsWith(".js")) {
|
|
@@ -207,14 +216,16 @@ export function reactivityTypeByName(name, internal) {
|
|
|
207
216
|
? "readable"
|
|
208
217
|
: false;
|
|
209
218
|
}
|
|
210
|
-
export function reactivityTypeOfNode(node, internal
|
|
211
|
-
return ((
|
|
212
|
-
((
|
|
213
|
-
((!node.node.
|
|
214
|
-
t.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
219
|
+
export function reactivityTypeOfNode(node, internal) {
|
|
220
|
+
return ((t.isIdentifier(node) && reactivityTypeByName(node.name, internal)) ||
|
|
221
|
+
((t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) &&
|
|
222
|
+
((!node.computed && t.isIdentifier(node.property) && reactivityTypeByName(node.property.name, internal)) ||
|
|
223
|
+
(t.isStringLiteral(node.property) && reactivityTypeByName(node.property.value, internal)))));
|
|
224
|
+
}
|
|
225
|
+
export function reactivityTypeOfNodePath(path, internal, checkForBreakpoints = true) {
|
|
226
|
+
const node = path.node;
|
|
227
|
+
return ((node && reactivityTypeOfNode(node, internal)) ||
|
|
228
|
+
(checkForBreakpoints && path.isExpression() && hasBreakPoint(path, internal) && "readable"));
|
|
218
229
|
}
|
|
219
230
|
export function isReactiveName(name, internal) {
|
|
220
231
|
return isReadableName(name, internal) || isWritableName(name, internal);
|
|
@@ -231,6 +242,40 @@ export function forceReactiveName(name, type, path, internal) {
|
|
|
231
242
|
isReadableName(name, internal) &&
|
|
232
243
|
err(Errors.RulesOfVasille, path, `Expected "writable" reactivity mark, the name "${name}" has "readonly" mark`, internal, true)))));
|
|
233
244
|
}
|
|
245
|
+
export function forcePathIsWritable(path, internal, accepts) {
|
|
246
|
+
if (path.isIdentifier() && isWritableName(path.node.name, internal)) {
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
if (path.isMemberExpression() &&
|
|
250
|
+
!path.node.computed &&
|
|
251
|
+
t.isIdentifier(path.node.property) &&
|
|
252
|
+
isWritableName(path.node.property.name, internal)) {
|
|
253
|
+
meshExpression(path.get("object"), internal, false);
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
/* istanbul ignore else */
|
|
257
|
+
if (accepts === "undefined" || accepts === "any") {
|
|
258
|
+
if (path.isOptionalMemberExpression() &&
|
|
259
|
+
!path.node.computed &&
|
|
260
|
+
t.isIdentifier(path.node.property) &&
|
|
261
|
+
isWritableName(path.node.property.name, internal)) {
|
|
262
|
+
meshExpression(path.get("object"), internal, false);
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
if (path.isReferencedIdentifier() && path.node.name === "undefined") {
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (path.isExpression() && exprCall(path, path.node, internal, {}, path.node, false)) {
|
|
270
|
+
err(Errors.RulesOfVasille, path, "Unexpected readonly reactive value. Expected a writable one." +
|
|
271
|
+
(accepts === "any" ? " Use `unwrap` to take the current value of reactive value in runtime." : ""), internal);
|
|
272
|
+
}
|
|
273
|
+
if (accepts === "any") {
|
|
274
|
+
meshAllUnknown([path], internal, false);
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
err(Errors.RulesOfVasille, path, "Expected writable reactive value here.", internal);
|
|
278
|
+
}
|
|
234
279
|
export function leftIsThisInConstructor(left) {
|
|
235
280
|
if (left.isMemberExpression()) {
|
|
236
281
|
let iterator = left;
|
|
@@ -247,3 +292,12 @@ export function leftIsThisInConstructor(left) {
|
|
|
247
292
|
}
|
|
248
293
|
return false;
|
|
249
294
|
}
|
|
295
|
+
const newReactivityMarks = ["wr_", "r_"];
|
|
296
|
+
const allReactivityMarks = [...newReactivityMarks, "$"];
|
|
297
|
+
export function replaceReactivityMark(name, with_, v4) {
|
|
298
|
+
const start = (v4 ? allReactivityMarks : newReactivityMarks).find(s => name.startsWith(s));
|
|
299
|
+
return with_ + name.substring(start ? start.length : 0);
|
|
300
|
+
}
|
|
301
|
+
export function extractReactivityMark(name, v4) {
|
|
302
|
+
return (v4 ? allReactivityMarks : newReactivityMarks).find(s => name.startsWith(s)) ?? "";
|
|
303
|
+
}
|
|
@@ -3,7 +3,7 @@ import { asyncFunctions, bindFunctions, calledFn, calls, composeFunctions, dynam
|
|
|
3
3
|
import { exprIsSure, idIsIValue, memberIsIValue, nodeIsMeshed } from "./expression.js";
|
|
4
4
|
import { ctx, V, VariablesStatus } from "./internal.js";
|
|
5
5
|
import { processConditions, transformJsx } from "./jsx.js";
|
|
6
|
-
import { checkNonReactiveName, checkReactiveName, err, Errors, exprCall, forceReactiveName, isReactiveName, isReadableName, isWritableName, leftIsThisInConstructor, parseCalculateCall, pathIsReactiveValue, processModelCall, reactivityTypeByName,
|
|
6
|
+
import { checkBuildInModelArgs, checkNonReactiveName, checkReactiveName, err, Errors, exprCall, extractReactivityMark, forceReactiveName, isReactiveName, isReadableName, isWritableName, leftIsThisInConstructor, parseCalculateCall, pathIsReactiveValue, processModelCall, reactivityTypeByName, reactivityTypeOfNodePath, ref, removeExtension, replaceReactivityMark, toKebabCase, } from "./lib.js";
|
|
7
7
|
import { checkOrder } from "./order-check.js";
|
|
8
8
|
import { routerReplace } from "./router.js";
|
|
9
9
|
import { stringify } from "./utils.js";
|
|
@@ -252,22 +252,19 @@ export function meshExpression(nodePath, internal, canHasRef) {
|
|
|
252
252
|
}
|
|
253
253
|
// arrayModel/setModel/mapModel call
|
|
254
254
|
else if (!internal.isComposing && calls(path, modelFunctions, internal)) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
meshAllUnknown([argPath], internal, true);
|
|
258
|
-
}
|
|
255
|
+
const [source, size] = checkBuildInModelArgs(path, internal);
|
|
256
|
+
const called = calledFn(path, modelFunctions, internal);
|
|
259
257
|
const loc = path.node.loc;
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
258
|
+
switch (called) {
|
|
259
|
+
case "arrayModel":
|
|
260
|
+
path.replaceWith(internal.arrayModel(source, size, path.node, undefined));
|
|
261
|
+
break;
|
|
262
|
+
case "mapModel":
|
|
263
|
+
path.replaceWith(internal.mapModel(source, size, path.node, undefined));
|
|
264
|
+
break;
|
|
265
|
+
case "setModel":
|
|
266
|
+
path.replaceWith(internal.setModel(source, size, path.node, undefined));
|
|
267
|
+
break;
|
|
271
268
|
}
|
|
272
269
|
path.node.loc = loc;
|
|
273
270
|
}
|
|
@@ -331,8 +328,8 @@ export function meshExpression(nodePath, internal, canHasRef) {
|
|
|
331
328
|
const path = nodePath;
|
|
332
329
|
const left = path.get("left");
|
|
333
330
|
const right = path.get("right");
|
|
334
|
-
const leftReactivity =
|
|
335
|
-
const rightReactivity =
|
|
331
|
+
const leftReactivity = reactivityTypeOfNodePath(left, internal);
|
|
332
|
+
const rightReactivity = reactivityTypeOfNodePath(right, internal);
|
|
336
333
|
let bypassMesh = false;
|
|
337
334
|
if (left.isMemberExpression() && hasBreakPoint(left, internal) && !memberIsIValue(left, "any", internal)) {
|
|
338
335
|
err(Errors.RulesOfVasille, left, "This assignment breaks the reactivity", internal);
|
|
@@ -562,8 +559,7 @@ function ignoreObjectPattern(pattern, internal) {
|
|
|
562
559
|
if (originName &&
|
|
563
560
|
newName &&
|
|
564
561
|
reactivityTypeByName(originName, internal) !== reactivityTypeByName(newName, internal)) {
|
|
565
|
-
const correctName =
|
|
566
|
-
newName.substring(newName.search(/[_$]/) + 1);
|
|
562
|
+
const correctName = replaceReactivityMark(newName, extractReactivityMark(originName, internal.v4Naming), internal.v4Naming);
|
|
567
563
|
err(Errors.RulesOfVasille, path.get("value"), `Property "${originName}" can not be renamed to "${newName}": rename it to "${correctName}"`, internal);
|
|
568
564
|
}
|
|
569
565
|
const valuePath = path.get("value");
|
|
@@ -203,6 +203,7 @@ export function transformProgram(path, filename, opts) {
|
|
|
203
203
|
return expression;
|
|
204
204
|
}
|
|
205
205
|
const reports = [];
|
|
206
|
+
const errors = [];
|
|
206
207
|
const relativePath = filename.substring(process.cwd().length);
|
|
207
208
|
const internal = {
|
|
208
209
|
appData: opts.appData,
|
|
@@ -265,23 +266,38 @@ export function transformProgram(path, filename, opts) {
|
|
|
265
266
|
}
|
|
266
267
|
return call("toDeepFieldRef", [getCtx(), obj, t.arrayExpression(fields)]);
|
|
267
268
|
},
|
|
268
|
-
setModel(arg, usage, name) {
|
|
269
|
+
setModel(arg, size, usage, name) {
|
|
269
270
|
if (opts.devLayer) {
|
|
270
|
-
return named(call("setModel", [
|
|
271
|
+
return named(call("setModel", [
|
|
272
|
+
nodeToStaticPosition(usage),
|
|
273
|
+
getCtx(),
|
|
274
|
+
arg ?? t.buildUndefinedNode(),
|
|
275
|
+
size ?? t.buildUndefinedNode(),
|
|
276
|
+
]), name);
|
|
271
277
|
}
|
|
272
|
-
return call("setModel", arg ? [
|
|
278
|
+
return call("setModel", [getCtx(), ...(arg ? [arg] : []), ...(arg && size ? [size] : [])]);
|
|
273
279
|
},
|
|
274
|
-
mapModel(arg, usage, name) {
|
|
280
|
+
mapModel(arg, size, usage, name) {
|
|
275
281
|
if (opts.devLayer) {
|
|
276
|
-
return named(call("mapModel", [
|
|
282
|
+
return named(call("mapModel", [
|
|
283
|
+
nodeToStaticPosition(usage),
|
|
284
|
+
getCtx(),
|
|
285
|
+
arg ?? t.buildUndefinedNode(),
|
|
286
|
+
size ?? t.buildUndefinedNode(),
|
|
287
|
+
]), name);
|
|
277
288
|
}
|
|
278
|
-
return call("mapModel", arg ? [
|
|
289
|
+
return call("mapModel", [getCtx(), ...(arg ? [arg] : []), ...(arg && size ? [size] : [])]);
|
|
279
290
|
},
|
|
280
|
-
arrayModel(arg, usage, name) {
|
|
291
|
+
arrayModel(arg, length, usage, name) {
|
|
281
292
|
if (opts.devLayer) {
|
|
282
|
-
return named(call("arrayModel", [
|
|
293
|
+
return named(call("arrayModel", [
|
|
294
|
+
nodeToStaticPosition(usage),
|
|
295
|
+
getCtx(),
|
|
296
|
+
arg ?? t.buildUndefinedNode(),
|
|
297
|
+
length ?? t.buildUndefinedNode(),
|
|
298
|
+
]), name);
|
|
283
299
|
}
|
|
284
|
-
return call("arrayModel", arg ? [
|
|
300
|
+
return call("arrayModel", [getCtx(), ...(arg ? [arg] : []), ...(arg && length ? [length] : [])]);
|
|
285
301
|
},
|
|
286
302
|
ensure(arg, area) {
|
|
287
303
|
const object = arg.object;
|
|
@@ -362,9 +378,7 @@ export function transformProgram(path, filename, opts) {
|
|
|
362
378
|
if (opts.throwAtFirstError) {
|
|
363
379
|
throw e;
|
|
364
380
|
}
|
|
365
|
-
|
|
366
|
-
process.stderr.write(e.message);
|
|
367
|
-
process.stderr.write(`\n\n`);
|
|
381
|
+
errors.push(`\nin file://${filename}:${pos?.start.line}:${pos?.start.column}\n${e.message}\n`);
|
|
368
382
|
}
|
|
369
383
|
else {
|
|
370
384
|
console.warn(message);
|
|
@@ -418,7 +432,8 @@ export function transformProgram(path, filename, opts) {
|
|
|
418
432
|
reports: reports,
|
|
419
433
|
});
|
|
420
434
|
if (reports.some(item => item.class === "error")) {
|
|
421
|
-
|
|
435
|
+
Error.stackTraceLimit = 1;
|
|
436
|
+
throw new Error(errors.join(""));
|
|
422
437
|
}
|
|
423
438
|
if (opts.devLayer) {
|
|
424
439
|
path.node.body.unshift(t.variableDeclaration("const", [t.variableDeclarator(filePathId, t.stringLiteral(internal.steelFilePath))]));
|
|
@@ -2,8 +2,10 @@ import { cp, mkdir, opendir, readFile, rm, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { statSync } from "node:fs";
|
|
3
3
|
import path, { dirname } from "node:path";
|
|
4
4
|
import { transformAsync } from "@babel/core";
|
|
5
|
+
// @ts-expect-error
|
|
5
6
|
import pluginJsxSyntax from "@babel/plugin-syntax-jsx";
|
|
6
7
|
import vasillePlugin from "../../babel-plugin/index.js";
|
|
8
|
+
// @ts-expect-error
|
|
7
9
|
import typeScriptPlugin from "@babel/plugin-transform-typescript";
|
|
8
10
|
import { watchFolder } from "./watch-folder.js";
|
|
9
11
|
export async function compileComponentsLib(srcDir, outputDir) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
// @ts-expect-error
|
|
1
2
|
import pluginJsxSyntax from "@babel/plugin-syntax-jsx";
|
|
2
3
|
import pluginVasille from "../../babel-plugin/index.js";
|
|
4
|
+
// @ts-expect-error
|
|
3
5
|
import pluginTypescript from "@babel/plugin-transform-typescript";
|
|
4
6
|
import babel from "vite-plugin-babel";
|
|
5
7
|
export function getVitePlugins(target, options) {
|
package/build/export/index.d.ts
CHANGED
|
@@ -101,11 +101,11 @@ export declare function effect(f: () => void): void;
|
|
|
101
101
|
* */
|
|
102
102
|
export declare function bypassWriteRestriction<T>(reactive: T, value: T): T;
|
|
103
103
|
/** Returns an array model of the array */
|
|
104
|
-
export declare function arrayModel<T>(v?: T[]): ArrayModel<T>;
|
|
104
|
+
export declare function arrayModel<T>(v?: readonly T[], length?: number): ArrayModel<T>;
|
|
105
105
|
/** Returns a set model of array values */
|
|
106
|
-
export declare function setModel<T>(v?: T[]): SetModel<T>;
|
|
106
|
+
export declare function setModel<T>(v?: readonly T[] | ReadonlySet<T>, size?: number): SetModel<T>;
|
|
107
107
|
/** Returns a map model of map data */
|
|
108
|
-
export declare function mapModel<K, T>(v?: [K, T][]): MapModel<K, T>;
|
|
108
|
+
export declare function mapModel<K, T>(v?: readonly (readonly [K, T])[] | ReadonlyMap<K, T>, size?: number): MapModel<K, T>;
|
|
109
109
|
/** Awaits async data in a sync component */
|
|
110
110
|
export declare function awaited<T>(target: (signal?: AbortSignal) => Promise<T>): [unknown, T | undefined];
|
|
111
111
|
/** Returns an abort signal to cancel requests/timers when context is destroyed */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "steel-frame",
|
|
3
|
-
"version": "7.2.
|
|
3
|
+
"version": "7.2.2",
|
|
4
4
|
"description": "SteelFrame: Build Fault-Tolerant Web Applications Effortlessly.",
|
|
5
5
|
"main": "build/cli/run.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"prepack": "cp -f ../README.md ./README.md",
|
|
32
|
-
"prettier": "prettier src --write",
|
|
32
|
+
"prettier": "prettier src test --write",
|
|
33
33
|
"prebuild": "rm -rf build",
|
|
34
34
|
"build": "tsc --build tsconfig.json",
|
|
35
35
|
"tsc-tests": "tsc --build test/tsconfig.json",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"@inquirer/select": "^5.2.6",
|
|
61
61
|
"csstype": "^3.1.3",
|
|
62
62
|
"esbuild": "^0.28.2",
|
|
63
|
-
"vasille-web": "7.2.
|
|
63
|
+
"vasille-web": "7.2.2",
|
|
64
64
|
"vite": "^8.3.4",
|
|
65
65
|
"vite-plugin-babel": "^1.7.3",
|
|
66
66
|
"vite-plugin-inspect": "^12.1.0",
|
|
@@ -75,6 +75,6 @@
|
|
|
75
75
|
"prettier": "^3.6.2",
|
|
76
76
|
"steel-frame": "file:.",
|
|
77
77
|
"ts-jest": "^29.4.14",
|
|
78
|
-
"typescript": "^
|
|
78
|
+
"typescript": "^6.0.3"
|
|
79
79
|
}
|
|
80
80
|
}
|
package/build/cli/sf.d.ts
DELETED
package/build/cli/sf.js
DELETED