@lightningjs/blits 1.40.0 → 1.41.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/CHANGELOG.md +16 -0
- package/package.json +3 -3
- package/src/component/base/timeouts_intervals.js +1 -1
- package/src/engines/L3/element.js +18 -3
- package/src/lib/codegenerator/generator.js +3 -0
- package/src/lib/reactivity/reactive.js +3 -3
- package/src/lib/reactivityguard/computedprops.js +51 -22
- package/src/plugin.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.41.0
|
|
4
|
+
|
|
5
|
+
_16 Oct 2025_
|
|
6
|
+
|
|
7
|
+
- Improved overall test coverage to 86%
|
|
8
|
+
- Filtered out inspector-data entirely in production
|
|
9
|
+
- Improved vite plugin that handles computed props to be more robust
|
|
10
|
+
- Fixed issue with global reactive object that are deeply nested
|
|
11
|
+
- Bumped MSDF generator dependency to address security issues in dependencies
|
|
12
|
+
|
|
13
|
+
## v1.40.1
|
|
14
|
+
|
|
15
|
+
_10 Oct 2025_
|
|
16
|
+
|
|
17
|
+
- Downgraded renderer to 2.18.2
|
|
18
|
+
|
|
3
19
|
## v1.40.0
|
|
4
20
|
|
|
5
21
|
_10 Oct 2025_
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightningjs/blits",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.0",
|
|
4
4
|
"description": "Blits: The Lightning 3 App Development Framework",
|
|
5
5
|
"bin": "bin/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"tape": "^5.5.0"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@lightningjs/msdf-generator": "^1.
|
|
58
|
-
"@lightningjs/renderer": "^2.18.
|
|
57
|
+
"@lightningjs/msdf-generator": "^1.2.0",
|
|
58
|
+
"@lightningjs/renderer": "^2.18.2"
|
|
59
59
|
},
|
|
60
60
|
"repository": {
|
|
61
61
|
"type": "git",
|
|
@@ -222,6 +222,12 @@ const colorMap = {
|
|
|
222
222
|
*/
|
|
223
223
|
let textDefaults = null
|
|
224
224
|
|
|
225
|
+
/**
|
|
226
|
+
* Inspector enabled flag (initialized on first use).
|
|
227
|
+
* @type {boolean|null}
|
|
228
|
+
*/
|
|
229
|
+
let inspectorEnabled = null
|
|
230
|
+
|
|
225
231
|
/**
|
|
226
232
|
* @typedef {import('../../component.js').BlitsElement} BlitsElement
|
|
227
233
|
*
|
|
@@ -465,6 +471,11 @@ const propsTransformer = {
|
|
|
465
471
|
}
|
|
466
472
|
},
|
|
467
473
|
set 'inspector-data'(v) {
|
|
474
|
+
// Skip processing if inspector is not enabled for performance optimization
|
|
475
|
+
if (inspectorEnabled === false) {
|
|
476
|
+
return
|
|
477
|
+
}
|
|
478
|
+
|
|
468
479
|
if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
|
|
469
480
|
this.props['data'] = v
|
|
470
481
|
}
|
|
@@ -567,10 +578,11 @@ const Element = {
|
|
|
567
578
|
for (let i = 0; i < propsKeys.length; i++) {
|
|
568
579
|
// todo: fix code duplication
|
|
569
580
|
if (isTransition(value) === true) {
|
|
570
|
-
|
|
581
|
+
this.animate(propsKeys[i], this.props.props[propsKeys[i]], value.transition)
|
|
582
|
+
} else {
|
|
583
|
+
// set the prop to the value on the node
|
|
584
|
+
this.node[propsKeys[i]] = this.props.props[propsKeys[i]]
|
|
571
585
|
}
|
|
572
|
-
// set the prop to the value on the node
|
|
573
|
-
this.node[propsKeys[i]] = this.props.props[propsKeys[i]]
|
|
574
586
|
}
|
|
575
587
|
}
|
|
576
588
|
|
|
@@ -740,6 +752,9 @@ export default (config, component) => {
|
|
|
740
752
|
fontFamily: Settings.get('defaultFont', 'sans-serif'),
|
|
741
753
|
}
|
|
742
754
|
}
|
|
755
|
+
if (inspectorEnabled === null) {
|
|
756
|
+
inspectorEnabled = Settings.get('inspector', false)
|
|
757
|
+
}
|
|
743
758
|
return Object.assign(Object.create(Element), {
|
|
744
759
|
props: Object.assign(Object.create(propsTransformer), { props: {} }),
|
|
745
760
|
scheduledTransitions: {},
|
|
@@ -179,6 +179,9 @@ const generateElementCode = function (
|
|
|
179
179
|
|
|
180
180
|
if (key === 'key') return
|
|
181
181
|
|
|
182
|
+
// Skip inspector-data in production builds for performance optimization
|
|
183
|
+
if (key === 'inspector-data' && !isDev) return
|
|
184
|
+
|
|
182
185
|
const value = templateObject[key]
|
|
183
186
|
|
|
184
187
|
if (isReactiveKey(key)) {
|
|
@@ -46,7 +46,7 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
|
|
|
46
46
|
|
|
47
47
|
const handler = {
|
|
48
48
|
get(target, key, receiver) {
|
|
49
|
-
//
|
|
49
|
+
// indicate that this is a proxy object
|
|
50
50
|
if (key === symbols.isProxy) {
|
|
51
51
|
return true
|
|
52
52
|
}
|
|
@@ -62,7 +62,7 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
|
|
|
62
62
|
track(target, key, global)
|
|
63
63
|
}
|
|
64
64
|
// create a new reactive proxy
|
|
65
|
-
return reactiveProxy(getRaw(target[key]), target, key)
|
|
65
|
+
return reactiveProxy(getRaw(target[key]), target, key, global)
|
|
66
66
|
}
|
|
67
67
|
// augment array path methods (that change the length of the array)
|
|
68
68
|
if (arrayPatchMethods.indexOf(key) !== -1) {
|
|
@@ -90,7 +90,7 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
|
|
|
90
90
|
track(target, key, global)
|
|
91
91
|
}
|
|
92
92
|
// create a new reactive proxy
|
|
93
|
-
return reactiveProxy(getRaw(target[key]), target, key)
|
|
93
|
+
return reactiveProxy(getRaw(target[key]), target, key, global)
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
// handling all other types
|
|
@@ -15,6 +15,51 @@
|
|
|
15
15
|
* SPDX-License-Identifier: Apache-2.0
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
+
// Utility function: Character-wise brace matcher that handles strings and comments
|
|
19
|
+
const findMatchingBrace = (text, startPos) => {
|
|
20
|
+
let braceLevel = 1
|
|
21
|
+
let position = startPos + 1
|
|
22
|
+
let inString = false
|
|
23
|
+
let stringChar = ''
|
|
24
|
+
|
|
25
|
+
for (; position < text.length && braceLevel > 0; position++) {
|
|
26
|
+
const char = text[position]
|
|
27
|
+
|
|
28
|
+
// Handle string boundaries (ignore escaped quotes)
|
|
29
|
+
if (!inString && (char === '"' || char === "'" || char === '`')) {
|
|
30
|
+
inString = true
|
|
31
|
+
stringChar = char
|
|
32
|
+
} else if (inString && char === stringChar && text[position - 1] !== '\\') {
|
|
33
|
+
inString = false
|
|
34
|
+
}
|
|
35
|
+
// Skip comments when not in strings
|
|
36
|
+
else if (!inString && char === '/' && text[position + 1] === '/') {
|
|
37
|
+
// Skip line comment
|
|
38
|
+
position = text.indexOf('\n', position) || text.length - 1
|
|
39
|
+
} else if (!inString && char === '/' && text[position + 1] === '*') {
|
|
40
|
+
// Skip block comment
|
|
41
|
+
position = text.indexOf('*/', position + 2) || text.length - 1
|
|
42
|
+
}
|
|
43
|
+
// Count braces only outside strings and comments
|
|
44
|
+
else if (!inString) {
|
|
45
|
+
if (char === '{') braceLevel++
|
|
46
|
+
else if (char === '}') braceLevel--
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return braceLevel === 0 ? position : -1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Find computed object boundaries in component config
|
|
54
|
+
const findComputedObjectEnd = (configObject, computedStart) => {
|
|
55
|
+
return findMatchingBrace(configObject, computedStart)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Find individual computed function boundaries
|
|
59
|
+
const findComputedFunctionEnd = (computedObj, openingBracePos) => {
|
|
60
|
+
return findMatchingBrace(computedObj, openingBracePos)
|
|
61
|
+
}
|
|
62
|
+
|
|
18
63
|
export default (code) => {
|
|
19
64
|
// Find component declarations
|
|
20
65
|
const componentRegex =
|
|
@@ -33,18 +78,10 @@ export default (code) => {
|
|
|
33
78
|
// Find start position of the computed block
|
|
34
79
|
const computedStart = computedKeywordMatch.index + computedKeywordMatch[0].length - 1 // Position of the opening brace
|
|
35
80
|
|
|
36
|
-
// Find the matching closing brace
|
|
37
|
-
|
|
38
|
-
let pos = computedStart + 1
|
|
81
|
+
// Find the matching closing brace for computed object in config
|
|
82
|
+
const computedEnd = findComputedObjectEnd(configObject, computedStart)
|
|
39
83
|
|
|
40
|
-
|
|
41
|
-
if (configObject[pos] === '{') braceLevel++
|
|
42
|
-
else if (configObject[pos] === '}') braceLevel--
|
|
43
|
-
pos++
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (braceLevel === 0) {
|
|
47
|
-
const computedEnd = pos
|
|
84
|
+
if (computedEnd !== -1) {
|
|
48
85
|
const computedObj = configObject.substring(computedStart, computedEnd)
|
|
49
86
|
|
|
50
87
|
// Process each computed property
|
|
@@ -67,18 +104,10 @@ export default (code) => {
|
|
|
67
104
|
const openingBracePos = computedObj.indexOf('{', funcNamePos)
|
|
68
105
|
if (openingBracePos === -1) break
|
|
69
106
|
|
|
70
|
-
// Find closing brace
|
|
71
|
-
|
|
72
|
-
let closingBracePos = openingBracePos + 1
|
|
73
|
-
|
|
74
|
-
while (braceLevel > 0 && closingBracePos < computedObj.length) {
|
|
75
|
-
if (computedObj[closingBracePos] === '{') braceLevel++
|
|
76
|
-
else if (computedObj[closingBracePos] === '}') braceLevel--
|
|
77
|
-
closingBracePos++
|
|
78
|
-
}
|
|
107
|
+
// Find closing brace for individual computed function
|
|
108
|
+
const closingBracePos = findComputedFunctionEnd(computedObj, openingBracePos)
|
|
79
109
|
|
|
80
|
-
if (
|
|
81
|
-
// Could not find matching brace
|
|
110
|
+
if (closingBracePos === -1) {
|
|
82
111
|
break
|
|
83
112
|
}
|
|
84
113
|
|
package/src/plugin.js
CHANGED
|
@@ -15,7 +15,7 @@ const registerPlugin = (plugin, nameOrOptions = '', options = {}) => {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
if (typeof plugin === 'function') {
|
|
18
|
-
if (name === undefined) {
|
|
18
|
+
if (name === undefined || name === '') {
|
|
19
19
|
throw Error('Error registering plugin: name is required for plugin')
|
|
20
20
|
}
|
|
21
21
|
plugins[name] = { plugin, options }
|