@lightningjs/blits 1.8.0 → 1.8.1

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.8.1
4
+
5
+ _29 oct 2024_
6
+
7
+ - Fixed issue with array based props not triggering reactivity
8
+ - Upgraded renderer to 2.5.1
9
+
10
+
3
11
  ## v1.8.0
4
12
 
5
13
  _22 oct 2024_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightningjs/blits",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Blits: The Lightning 3 App Development Framework",
5
5
  "bin": "bin/index.js",
6
6
  "exports": {
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "scripts": {
15
15
  "test": "c8 npm run test:run",
16
- "test:run": "node -r global-jsdom/register ./node_modules/.bin/tape '{,!(node_modules)/**/}*.test.js' | tap-diff",
16
+ "test:run": "node -r global-jsdom/register ./node_modules/.bin/tape '{,!(node_modules|packages)/**/}*.test.js' | tap-diff",
17
17
  "lint": "eslint '**/*.js'",
18
18
  "lint:fix": "eslint '**/*.js' --fix",
19
19
  "prepublishOnly": "node scripts/prepublishOnly.js",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@lightningjs/msdf-generator": "^1.1.0",
52
- "@lightningjs/renderer": "^2.4.0"
52
+ "@lightningjs/renderer": "^2.5.1"
53
53
  },
54
54
  "repository": {
55
55
  "type": "git",
@@ -141,6 +141,7 @@ export default () =>
141
141
  props7['h'] = 20
142
142
  props7['w'] = 20
143
143
  props7['map'] = component.sprite
144
+
144
145
  props7['frame'] = component.fps[0]
145
146
 
146
147
  componentType = props7['is'] || 'Sprite'
@@ -198,6 +199,7 @@ export default () =>
198
199
  props9['h'] = 20
199
200
  props9['w'] = 20
200
201
  props9['map'] = component.sprite
202
+
201
203
  props9['frame'] = component.fps[1]
202
204
 
203
205
  componentType = props9['is'] || 'Sprite'
@@ -255,6 +257,7 @@ export default () =>
255
257
  props11['h'] = 20
256
258
  props11['w'] = 20
257
259
  props11['map'] = component.sprite
260
+
258
261
  props11['frame'] = component.fps[2]
259
262
 
260
263
  componentType = props11['is'] || 'Sprite'
@@ -386,6 +389,7 @@ export default () =>
386
389
  props17['h'] = 20
387
390
  props17['w'] = 20
388
391
  props17['map'] = component.sprite
392
+
389
393
  props17['frame'] = component.avgFps[0]
390
394
 
391
395
  componentType = props17['is'] || 'Sprite'
@@ -443,6 +447,7 @@ export default () =>
443
447
  props19['h'] = 20
444
448
  props19['w'] = 20
445
449
  props19['map'] = component.sprite
450
+
446
451
  props19['frame'] = component.avgFps[1]
447
452
 
448
453
  componentType = props19['is'] || 'Sprite'
@@ -500,6 +505,7 @@ export default () =>
500
505
  props21['h'] = 20
501
506
  props21['w'] = 20
502
507
  props21['map'] = component.sprite
508
+
503
509
  props21['frame'] = component.avgFps[2]
504
510
 
505
511
  componentType = props21['is'] || 'Sprite'
@@ -632,6 +638,7 @@ export default () =>
632
638
  props27['h'] = 20
633
639
  props27['w'] = 20
634
640
  props27['map'] = component.sprite
641
+
635
642
  props27['frame'] = component.minFps[0]
636
643
 
637
644
  componentType = props27['is'] || 'Sprite'
@@ -689,6 +696,7 @@ export default () =>
689
696
  props29['h'] = 20
690
697
  props29['w'] = 20
691
698
  props29['map'] = component.sprite
699
+
692
700
  props29['frame'] = component.minFps[1]
693
701
 
694
702
  componentType = props29['is'] || 'Sprite'
@@ -746,6 +754,7 @@ export default () =>
746
754
  props31['h'] = 20
747
755
  props31['w'] = 20
748
756
  props31['map'] = component.sprite
757
+
749
758
  props31['frame'] = component.minFps[2]
750
759
 
751
760
  componentType = props31['is'] || 'Sprite'
@@ -876,6 +885,7 @@ export default () =>
876
885
  props37['h'] = 20
877
886
  props37['w'] = 20
878
887
  props37['map'] = component.sprite
888
+
879
889
  props37['frame'] = component.maxFps[0]
880
890
 
881
891
  componentType = props37['is'] || 'Sprite'
@@ -933,6 +943,7 @@ export default () =>
933
943
  props39['h'] = 20
934
944
  props39['w'] = 20
935
945
  props39['map'] = component.sprite
946
+
936
947
  props39['frame'] = component.maxFps[1]
937
948
 
938
949
  componentType = props39['is'] || 'Sprite'
@@ -990,6 +1001,7 @@ export default () =>
990
1001
  props41['h'] = 20
991
1002
  props41['w'] = 20
992
1003
  props41['map'] = component.sprite
1004
+
993
1005
  props41['frame'] = component.maxFps[2]
994
1006
 
995
1007
  componentType = props41['is'] || 'Sprite'
@@ -0,0 +1,50 @@
1
+ /*
2
+ * Copyright 2024 Comcast Cable Communications Management, LLC
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ *
15
+ * SPDX-License-Identifier: Apache-2.0
16
+ */
17
+
18
+ const deepEqualArray = (array1, array2) => {
19
+ if (array1 === array2) return true
20
+ if (array1.length !== array2.length) return false
21
+
22
+ let l = array1.length
23
+
24
+ while (l--) {
25
+ const value1 = array1[l]
26
+ const value2 = array2[l]
27
+
28
+ // values are arrays, deepEqual nested arrays
29
+ if (Array.isArray(value1) && Array.isArray(value2)) {
30
+ if (deepEqualArray(value1, value2) === false) return false
31
+ }
32
+ // values are objects, deepEqual nested objects
33
+ else if (
34
+ typeof value1 === 'object' &&
35
+ value1 !== null &&
36
+ typeof value2 === 'object' &&
37
+ value2 !== null
38
+ ) {
39
+ if (deepEqualArray(Object.entries(value1), Object.entries(value2)) === false) return false
40
+ }
41
+ // other type, do strict equal check
42
+ else if (value1 !== value2) {
43
+ return false
44
+ }
45
+ }
46
+
47
+ return true
48
+ }
49
+
50
+ export default deepEqualArray
@@ -0,0 +1,127 @@
1
+ /*
2
+ * Copyright 2024 Comcast Cable Communications Management, LLC
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ *
15
+ * SPDX-License-Identifier: Apache-2.0
16
+ */
17
+
18
+ import test from 'tape'
19
+ import deepEqual from './deepEqualArray.js'
20
+
21
+ test('Type', (assert) => {
22
+ const expected = 'function'
23
+ const actual = typeof deepEqual
24
+
25
+ assert.equal(actual, expected, 'deepEqual should be a function')
26
+ assert.end()
27
+ })
28
+
29
+ test('The same arrays', (assert) => {
30
+ const val1 = ['hello', 'world']
31
+
32
+ assert.true(
33
+ deepEqual(val1, val1),
34
+ 'deepEqual should return true if the values are the same reference'
35
+ )
36
+ assert.end()
37
+ })
38
+
39
+ test('Equal simple arrays', (assert) => {
40
+ const val1 = ['hello', 'world']
41
+ const val2 = ['hello', 'world']
42
+
43
+ assert.true(deepEqual(val1, val2), 'deepEqual should return true if simple arrays are equal')
44
+ assert.end()
45
+ })
46
+
47
+ test('Not equal simple arrays', (assert) => {
48
+ const val1 = ['hello', 'world']
49
+ const val2 = ['world', 'hello']
50
+
51
+ assert.false(
52
+ deepEqual(val1, val2),
53
+ 'deepEqual should return false if simple arrays are not equal'
54
+ )
55
+ assert.end()
56
+ })
57
+
58
+ test('Not Equal simple arrays (different length)', (assert) => {
59
+ const val1 = ['hello', 'world']
60
+ const val2 = ['hello', 'world', '!']
61
+
62
+ assert.false(deepEqual(val1, val2), 'deepEqual should return false if simple arrays are equal')
63
+ assert.end()
64
+ })
65
+
66
+ test('Equal nested arrays', (assert) => {
67
+ const val1 = ['hello', ['world', '!']]
68
+ const val2 = ['hello', ['world', '!']]
69
+
70
+ assert.true(deepEqual(val1, val2), 'deepEqual should return true if nested arrays are equal')
71
+ assert.end()
72
+ })
73
+
74
+ test('Not equal nested arrays', (assert) => {
75
+ const val1 = ['hello', ['world', '!']]
76
+ const val2 = ['hello', ['world', '!', '?']]
77
+
78
+ assert.false(
79
+ deepEqual(val1, val2),
80
+ 'deepEqual should return false if nested arrays are not equal'
81
+ )
82
+ assert.end()
83
+ })
84
+
85
+ test('Equal arrays with objects', (assert) => {
86
+ const val1 = [{ foo: 'bar', bar: 'foo' }, { hello: 'world' }]
87
+ const val2 = [{ foo: 'bar', bar: 'foo' }, { hello: 'world' }]
88
+
89
+ assert.true(
90
+ deepEqual(val1, val2),
91
+ 'deepEqual should return true if arrays with objects are equal'
92
+ )
93
+ assert.end()
94
+ })
95
+
96
+ test('Not equal arrays with objects (keys', (assert) => {
97
+ const val1 = [{ foo: 'bar', bar: 'foo' }, { test: 'bla' }]
98
+ const val2 = [{ foo2: 'bar', bar2: 'foo' }, { test: 'bla' }]
99
+
100
+ assert.false(
101
+ deepEqual(val1, val2),
102
+ 'deepEqual should return false if arrays with objects are not equal'
103
+ )
104
+ assert.end()
105
+ })
106
+
107
+ test('Equal arrays with mixed values', (assert) => {
108
+ const val1 = ['foo', { foo: 'bar', bar: 'foo' }, ['hello', 'world', ['this', 'is', { level: 2 }]]]
109
+ const val2 = ['foo', { foo: 'bar', bar: 'foo' }, ['hello', 'world', ['this', 'is', { level: 2 }]]]
110
+
111
+ assert.true(
112
+ deepEqual(val1, val2),
113
+ 'deepEqual should return true if arrays with mixed values are equal'
114
+ )
115
+ assert.end()
116
+ })
117
+
118
+ test('Not Equal arrays with mixed values', (assert) => {
119
+ const val1 = ['foo', { foo: 'bar', bar: 'foo' }, ['hello', 'world', ['this', 'is', { level: 2 }]]]
120
+ const val2 = ['foo', { foo: 'bar', bar: 'foo' }, ['hello', 'world', ['this', 'is', { level: 3 }]]]
121
+
122
+ assert.false(
123
+ deepEqual(val1, val2),
124
+ 'deepEqual should return true if arrays with mixed values are not equal'
125
+ )
126
+ assert.end()
127
+ })
@@ -212,12 +212,11 @@ const generateComponentCode = function (
212
212
  templateObject[key],
213
213
  options.component
214
214
  )}`)
215
- renderCode.push(
216
- `props${counter}['${key.substring(1)}'] = ${interpolate(
217
- templateObject[key],
218
- options.component
219
- )}`
220
- )
215
+ renderCode.push(`
216
+ props${counter}['${key.substring(1)}']= ${interpolate(
217
+ templateObject[key],
218
+ options.component
219
+ )}`)
221
220
  } else {
222
221
  renderCode.push(
223
222
  `props${counter}['${key}'] = ${cast(templateObject[key], key, options.component)}`
@@ -18,6 +18,7 @@
18
18
  import { ImageTexture } from '@lightningjs/renderer'
19
19
  import { track, trigger, pauseTracking, resumeTracking } from './effect.js'
20
20
  import symbols from '../symbols.js'
21
+ import deepEqualArray from '../../helpers/deepEqualArray.js'
21
22
 
22
23
  const arrayPatchMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort']
23
24
 
@@ -38,7 +39,7 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
38
39
 
39
40
  // if original object is already a proxy, don't create a new one but return the existing one instead
40
41
  const existingProxy = proxyMap.get(original)
41
- if (existingProxy) {
42
+ if (existingProxy !== undefined) {
42
43
  return existingProxy
43
44
  }
44
45
 
@@ -50,9 +51,9 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
50
51
  }
51
52
 
52
53
  // handling arrays
53
- if (Array.isArray(target)) {
54
+ if (Array.isArray(target) === true) {
54
55
  if (typeof target[key] === 'object' && target[key] !== null) {
55
- if (Array.isArray(target[key])) {
56
+ if (Array.isArray(target[key]) === true) {
56
57
  track(target, key, global)
57
58
  }
58
59
  // create a new reactive proxy
@@ -80,7 +81,7 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
80
81
 
81
82
  // handling objects (but not null values, which have object type in JS)
82
83
  if (typeof target[key] === 'object' && target[key] !== null) {
83
- if (Array.isArray(target[key])) {
84
+ if (Array.isArray(target[key]) === true) {
84
85
  track(target, key, global)
85
86
  }
86
87
  // create a new reactive proxy
@@ -99,13 +100,19 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
99
100
  const rawValue = getRaw(value)
100
101
 
101
102
  let result = true
102
- if (oldRawValue !== rawValue) {
103
+ const isEqual =
104
+ Array.isArray(rawValue) === true
105
+ ? deepEqualArray(oldRawValue, rawValue)
106
+ : oldRawValue === rawValue
107
+
108
+ if (isEqual === false) {
109
+ if (Array.isArray(value) === true) value = getRaw(value).slice(0)
103
110
  result = Reflect.set(target, key, value, receiver)
104
111
  }
105
112
 
106
- if (result && oldRawValue !== rawValue) {
113
+ if (result === true && isEqual === false) {
107
114
  // if we're assigning an array key directly trigger reactivity on the parent key as well
108
- if (Array.isArray(target) && key in target) {
115
+ if (Array.isArray(target) === true && key in target === true) {
109
116
  trigger(_parent, _key, true)
110
117
  }
111
118
  trigger(target, key, true)
@@ -126,7 +133,7 @@ const reactiveDefineProperty = (target, global) => {
126
133
  if (target[key] !== null && typeof target[key] === 'object') {
127
134
  if (Object.getPrototypeOf(target[key]) === Object.prototype) {
128
135
  return reactiveDefineProperty(target[key])
129
- } else if (Array.isArray(target[key])) {
136
+ } else if (Array.isArray(target[key]) === true) {
130
137
  for (let i = 0; i < arrayPatchMethods.length - 1; i++) {
131
138
  target[key][arrayPatchMethods[i]] = function (v) {
132
139
  Array.prototype[arrayPatchMethods[i]].call(this, v)