@fluffjs/fluff 0.4.0 → 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.
- package/package.json +1 -1
- package/runtime/FluffBase.d.ts +5 -1
- package/runtime/FluffBase.js +94 -0
- package/runtime/FluffElementImpl.d.ts +1 -1
- package/runtime/FluffElementImpl.js +2 -1
- package/runtime/MarkerManager.d.ts +3 -0
- package/runtime/MarkerManager.js +36 -2
- package/runtime/MarkerManagerInterface.d.ts +2 -1
- package/utils/Property.js +3 -3
package/package.json
CHANGED
package/runtime/FluffBase.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export type CompactBinding = [
|
|
|
51
51
|
p?: [number, number[]][];
|
|
52
52
|
}?
|
|
53
53
|
];
|
|
54
|
+
export type CompactMarkerConfig = [0, ([number | null, CompactDep[] | null] | [])[]] | [1, number, number, boolean, CompactDep[] | null, number | null] | [2, number, CompactDep[] | null, [number, number[]][] | null] | [3, number, CompactDep[] | null, [boolean, boolean, number | null][]] | [4];
|
|
54
55
|
export declare abstract class FluffBase extends HTMLElement {
|
|
55
56
|
static __e: ExpressionFn[];
|
|
56
57
|
static __h: HandlerFn[];
|
|
@@ -59,7 +60,10 @@ export declare abstract class FluffBase extends HTMLElement {
|
|
|
59
60
|
private static __expressionsReady;
|
|
60
61
|
private static readonly __pendingInitCallbacks;
|
|
61
62
|
static __setExpressionTable(expressions: ExpressionFn[], handlers: HandlerFn[], strings?: string[]): void;
|
|
62
|
-
|
|
63
|
+
static __decodeString(idx: number): string;
|
|
64
|
+
static __decodeDep(dep: number | number[]): string | string[];
|
|
65
|
+
static __decodeDeps(deps: (number | number[])[] | null): (string | string[])[] | undefined;
|
|
66
|
+
static __decodeMarkerConfig(compact: CompactMarkerConfig): unknown;
|
|
63
67
|
private static __decodeBinding;
|
|
64
68
|
static __areExpressionsReady(): boolean;
|
|
65
69
|
static __addPendingInit(callback: () => void): void;
|
package/runtime/FluffBase.js
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { Property } from '../utils/Property.js';
|
|
2
2
|
import { Publisher } from '../utils/Publisher.js';
|
|
3
3
|
const BINDING_TYPES = ['property', 'event', 'two-way', 'class', 'style', 'ref'];
|
|
4
|
+
/**
|
|
5
|
+
* Compact Marker Config Format (Decoder)
|
|
6
|
+
*
|
|
7
|
+
* Marker configs use the same string table as bindings. Type is numeric:
|
|
8
|
+
* 0=if, 1=for, 2=text, 3=switch, 4=break
|
|
9
|
+
*
|
|
10
|
+
* Format varies by type:
|
|
11
|
+
* - if: [0, branches[]] where branch = [exprId?, deps?]
|
|
12
|
+
* - for: [1, iteratorIdx, iterableExprId, hasEmpty, deps?, trackByIdx?]
|
|
13
|
+
* - text: [2, exprId, deps?, pipes?]
|
|
14
|
+
* - switch: [3, expressionExprId, deps?, cases[]]
|
|
15
|
+
* - break: [4]
|
|
16
|
+
*
|
|
17
|
+
* deps are interned as CompactDep[] (same as bindings)
|
|
18
|
+
* pipes are [pipeNameIdx, argExprIds[]][]
|
|
19
|
+
*/
|
|
20
|
+
const MARKER_TYPES = ['if', 'for', 'text', 'switch', 'break'];
|
|
4
21
|
export class FluffBase extends HTMLElement {
|
|
5
22
|
static __e = [];
|
|
6
23
|
static __h = [];
|
|
@@ -20,12 +37,89 @@ export class FluffBase extends HTMLElement {
|
|
|
20
37
|
callback();
|
|
21
38
|
}
|
|
22
39
|
}
|
|
40
|
+
static __decodeString(idx) {
|
|
41
|
+
return FluffBase.__s[idx];
|
|
42
|
+
}
|
|
23
43
|
static __decodeDep(dep) {
|
|
24
44
|
if (Array.isArray(dep)) {
|
|
25
45
|
return dep.map(idx => FluffBase.__s[idx]);
|
|
26
46
|
}
|
|
27
47
|
return FluffBase.__s[dep];
|
|
28
48
|
}
|
|
49
|
+
static __decodeDeps(deps) {
|
|
50
|
+
if (!deps)
|
|
51
|
+
return undefined;
|
|
52
|
+
return deps.map(d => FluffBase.__decodeDep(d));
|
|
53
|
+
}
|
|
54
|
+
static __decodeMarkerConfig(compact) {
|
|
55
|
+
const [typeNum] = compact;
|
|
56
|
+
const type = MARKER_TYPES[typeNum];
|
|
57
|
+
switch (typeNum) {
|
|
58
|
+
case 0: // if
|
|
59
|
+
{
|
|
60
|
+
const [, rawBranches] = compact;
|
|
61
|
+
const branches = rawBranches.map(b => {
|
|
62
|
+
if (b.length === 0)
|
|
63
|
+
return {};
|
|
64
|
+
const [branchExprId, branchDeps] = b;
|
|
65
|
+
const result = {};
|
|
66
|
+
if (branchExprId !== null)
|
|
67
|
+
result.exprId = branchExprId;
|
|
68
|
+
if (branchDeps)
|
|
69
|
+
result.deps = FluffBase.__decodeDeps(branchDeps);
|
|
70
|
+
return result;
|
|
71
|
+
});
|
|
72
|
+
return { type, branches };
|
|
73
|
+
}
|
|
74
|
+
case 1: // for
|
|
75
|
+
{
|
|
76
|
+
const [, iteratorIdx, iterableExprId, hasEmpty, deps, trackByIdx] = compact;
|
|
77
|
+
const result = {
|
|
78
|
+
type,
|
|
79
|
+
iterator: FluffBase.__s[iteratorIdx],
|
|
80
|
+
iterableExprId,
|
|
81
|
+
hasEmpty
|
|
82
|
+
};
|
|
83
|
+
if (deps)
|
|
84
|
+
result.deps = FluffBase.__decodeDeps(deps);
|
|
85
|
+
if (trackByIdx !== null)
|
|
86
|
+
result.trackBy = FluffBase.__s[trackByIdx];
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
case 2: // text
|
|
90
|
+
{
|
|
91
|
+
const [, exprId, deps, pipes] = compact;
|
|
92
|
+
const result = { type, exprId };
|
|
93
|
+
if (deps)
|
|
94
|
+
result.deps = FluffBase.__decodeDeps(deps);
|
|
95
|
+
if (pipes) {
|
|
96
|
+
result.pipes = pipes.map(([nameIdx, argExprIds]) => ({
|
|
97
|
+
name: FluffBase.__s[nameIdx],
|
|
98
|
+
argExprIds
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
case 3: // switch
|
|
104
|
+
{
|
|
105
|
+
const [, expressionExprId, deps, cases] = compact;
|
|
106
|
+
const result = { type, expressionExprId };
|
|
107
|
+
if (deps)
|
|
108
|
+
result.deps = FluffBase.__decodeDeps(deps);
|
|
109
|
+
result.cases = cases.map(([isDefault, fallthrough, valueExprId]) => {
|
|
110
|
+
const c = { isDefault, fallthrough };
|
|
111
|
+
if (valueExprId !== null)
|
|
112
|
+
c.valueExprId = valueExprId;
|
|
113
|
+
return c;
|
|
114
|
+
});
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
case 4: // break
|
|
118
|
+
return { type };
|
|
119
|
+
default:
|
|
120
|
+
return { type: 'unknown' };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
29
123
|
static __decodeBinding(compact) {
|
|
30
124
|
const [nameIdx, bType, deps, id, extras] = compact;
|
|
31
125
|
const n = FluffBase.__s[nameIdx];
|
|
@@ -22,7 +22,7 @@ export declare abstract class FluffElement extends FluffBase {
|
|
|
22
22
|
protected __pipe(name: string, value: unknown, ...args: unknown[]): unknown;
|
|
23
23
|
protected __getPipeFn(name: string): ((value: unknown, ...args: unknown[]) => unknown) | undefined;
|
|
24
24
|
protected __getShadowRoot(): ShadowRoot;
|
|
25
|
-
protected __createProp<T>(
|
|
25
|
+
protected __createProp<T>(nameOrIdx: string | number, options: T | {
|
|
26
26
|
initialValue: T;
|
|
27
27
|
[key: string]: unknown;
|
|
28
28
|
}): Property<T>;
|
|
@@ -101,7 +101,8 @@ export class FluffElement extends FluffBase {
|
|
|
101
101
|
__getShadowRoot() {
|
|
102
102
|
return this._shadowRoot;
|
|
103
103
|
}
|
|
104
|
-
__createProp(
|
|
104
|
+
__createProp(nameOrIdx, options) {
|
|
105
|
+
const name = typeof nameOrIdx === 'number' ? FluffBase.__decodeString(nameOrIdx) : nameOrIdx;
|
|
105
106
|
const prop = new Property(options);
|
|
106
107
|
Object.defineProperty(this, name, {
|
|
107
108
|
get() {
|
|
@@ -6,6 +6,9 @@ export declare class MarkerManager {
|
|
|
6
6
|
private readonly host;
|
|
7
7
|
private readonly shadowRoot;
|
|
8
8
|
constructor(host: HTMLElement, shadowRoot: ShadowRoot);
|
|
9
|
+
private decodeConfig;
|
|
10
|
+
private isMarkerConfig;
|
|
11
|
+
private isCompactMarkerConfig;
|
|
9
12
|
initializeFromConfig(entries: MarkerConfigEntries): void;
|
|
10
13
|
ensureController(id: number, type: string, startMarker: Comment, endMarker: Comment | null): MarkerController | undefined;
|
|
11
14
|
getController(id: number, startMarker: Comment): MarkerController | undefined;
|
package/runtime/MarkerManager.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BreakController } from './BreakController.js';
|
|
2
|
+
import { FluffBase } from './FluffBase.js';
|
|
2
3
|
import { ForController } from './ForController.js';
|
|
3
4
|
import { IfController } from './IfController.js';
|
|
4
5
|
import { MarkerConfigGuards } from './MarkerConfigGuards.js';
|
|
@@ -13,12 +14,45 @@ export class MarkerManager {
|
|
|
13
14
|
this.host = host;
|
|
14
15
|
this.shadowRoot = shadowRoot;
|
|
15
16
|
}
|
|
17
|
+
decodeConfig(config) {
|
|
18
|
+
if (this.isCompactMarkerConfig(config)) {
|
|
19
|
+
const decoded = FluffBase.__decodeMarkerConfig(config);
|
|
20
|
+
if (this.isMarkerConfig(decoded)) {
|
|
21
|
+
return decoded;
|
|
22
|
+
}
|
|
23
|
+
throw new Error('Decoded marker config is invalid');
|
|
24
|
+
}
|
|
25
|
+
if (!Array.isArray(config)) {
|
|
26
|
+
return config;
|
|
27
|
+
}
|
|
28
|
+
throw new Error('Invalid marker config format');
|
|
29
|
+
}
|
|
30
|
+
isMarkerConfig(value) {
|
|
31
|
+
if (typeof value !== 'object' || value === null)
|
|
32
|
+
return false;
|
|
33
|
+
if (!('type' in value))
|
|
34
|
+
return false;
|
|
35
|
+
const typeVal = value.type;
|
|
36
|
+
return typeof typeVal === 'string' && ['if', 'for', 'text', 'switch', 'break'].includes(typeVal);
|
|
37
|
+
}
|
|
38
|
+
isCompactMarkerConfig(config) {
|
|
39
|
+
if (!Array.isArray(config))
|
|
40
|
+
return false;
|
|
41
|
+
if (config.length === 0)
|
|
42
|
+
return false;
|
|
43
|
+
const firstElement = config[0];
|
|
44
|
+
return typeof firstElement === 'number' && firstElement >= 0 && firstElement <= 4;
|
|
45
|
+
}
|
|
16
46
|
initializeFromConfig(entries) {
|
|
17
47
|
this.configs.clear();
|
|
18
|
-
for (const [id,
|
|
48
|
+
for (const [id, rawConfig] of entries) {
|
|
49
|
+
const config = this.decodeConfig(rawConfig);
|
|
19
50
|
this.configs.set(id, config);
|
|
20
51
|
}
|
|
21
|
-
for (const [id
|
|
52
|
+
for (const [id] of entries) {
|
|
53
|
+
const config = this.configs.get(id);
|
|
54
|
+
if (!config)
|
|
55
|
+
continue;
|
|
22
56
|
const { startMarker, endMarker } = this.findMarkers(id, config.type);
|
|
23
57
|
if (!startMarker) {
|
|
24
58
|
continue;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MarkerConfig } from '../interfaces/MarkerConfig.js';
|
|
2
|
-
|
|
2
|
+
import type { CompactMarkerConfig } from './FluffBase.js';
|
|
3
|
+
export type MarkerConfigEntries = [number, MarkerConfig | CompactMarkerConfig][];
|
|
3
4
|
export interface MarkerManagerInterface {
|
|
4
5
|
initializeFromConfig: (entries: MarkerConfigEntries) => void;
|
|
5
6
|
cleanup: () => void;
|
package/utils/Property.js
CHANGED
|
@@ -174,11 +174,11 @@ export class Property {
|
|
|
174
174
|
if (this.value === undefined)
|
|
175
175
|
return;
|
|
176
176
|
this.onChange.emit(this.value);
|
|
177
|
-
if (direction
|
|
177
|
+
if (direction === Direction.Outbound) {
|
|
178
178
|
this.onOutboundChange.emit(this.value);
|
|
179
179
|
}
|
|
180
|
-
if (direction
|
|
181
|
-
this.
|
|
180
|
+
if (direction === Direction.Inbound) {
|
|
181
|
+
this.onInboundChange.emit(this.value);
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
subscribe(direction, cb) {
|