Skip to content

Commit

Permalink
Merge pull request #198 from lightning-js/dev
Browse files Browse the repository at this point in the history
Release 1.8.1
  • Loading branch information
michielvandergeest authored Oct 29, 2024
2 parents dbfad51 + f5bdb4a commit 3f3143a
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 24 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## v1.8.1

_29 oct 2024_

- Fixed issue with array based props not triggering reactivity
- Upgraded renderer to 2.5.1


## v1.8.0

_22 oct 2024_
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lightningjs/blits",
"version": "1.8.0",
"version": "1.8.1",
"description": "Blits: The Lightning 3 App Development Framework",
"bin": "bin/index.js",
"exports": {
Expand All @@ -13,7 +13,7 @@
},
"scripts": {
"test": "c8 npm run test:run",
"test:run": "node -r global-jsdom/register ./node_modules/.bin/tape '{,!(node_modules)/**/}*.test.js' | tap-diff",
"test:run": "node -r global-jsdom/register ./node_modules/.bin/tape '{,!(node_modules|packages)/**/}*.test.js' | tap-diff",
"lint": "eslint '**/*.js'",
"lint:fix": "eslint '**/*.js' --fix",
"prepublishOnly": "node scripts/prepublishOnly.js",
Expand Down Expand Up @@ -49,7 +49,7 @@
},
"dependencies": {
"@lightningjs/msdf-generator": "^1.1.0",
"@lightningjs/renderer": "^2.4.0"
"@lightningjs/renderer": "^2.5.1"
},
"repository": {
"type": "git",
Expand Down
3 changes: 2 additions & 1 deletion packages/create-blits/boilerplate/ts/default/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"allowJs": true,
"checkJs": true,
"noEmit": true,
"strict": true
"strict": true,
"noImplicitThis": true
}
}
50 changes: 50 additions & 0 deletions src/helpers/deepEqualArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2024 Comcast Cable Communications Management, LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

const deepEqualArray = (array1, array2) => {
if (array1 === array2) return true
if (array1.length !== array2.length) return false

let l = array1.length

while (l--) {
const value1 = array1[l]
const value2 = array2[l]

// values are arrays, deepEqual nested arrays
if (Array.isArray(value1) && Array.isArray(value2)) {
if (deepEqualArray(value1, value2) === false) return false
}
// values are objects, deepEqual nested objects
else if (
typeof value1 === 'object' &&
value1 !== null &&
typeof value2 === 'object' &&
value2 !== null
) {
if (deepEqualArray(Object.entries(value1), Object.entries(value2)) === false) return false
}
// other type, do strict equal check
else if (value1 !== value2) {
return false
}
}

return true
}

export default deepEqualArray
127 changes: 127 additions & 0 deletions src/helpers/deepEqualArray.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright 2024 Comcast Cable Communications Management, LLC
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

import test from 'tape'
import deepEqual from './deepEqualArray.js'

test('Type', (assert) => {
const expected = 'function'
const actual = typeof deepEqual

assert.equal(actual, expected, 'deepEqual should be a function')
assert.end()
})

test('The same arrays', (assert) => {
const val1 = ['hello', 'world']

assert.true(
deepEqual(val1, val1),
'deepEqual should return true if the values are the same reference'
)
assert.end()
})

test('Equal simple arrays', (assert) => {
const val1 = ['hello', 'world']
const val2 = ['hello', 'world']

assert.true(deepEqual(val1, val2), 'deepEqual should return true if simple arrays are equal')
assert.end()
})

test('Not equal simple arrays', (assert) => {
const val1 = ['hello', 'world']
const val2 = ['world', 'hello']

assert.false(
deepEqual(val1, val2),
'deepEqual should return false if simple arrays are not equal'
)
assert.end()
})

test('Not Equal simple arrays (different length)', (assert) => {
const val1 = ['hello', 'world']
const val2 = ['hello', 'world', '!']

assert.false(deepEqual(val1, val2), 'deepEqual should return false if simple arrays are equal')
assert.end()
})

test('Equal nested arrays', (assert) => {
const val1 = ['hello', ['world', '!']]
const val2 = ['hello', ['world', '!']]

assert.true(deepEqual(val1, val2), 'deepEqual should return true if nested arrays are equal')
assert.end()
})

test('Not equal nested arrays', (assert) => {
const val1 = ['hello', ['world', '!']]
const val2 = ['hello', ['world', '!', '?']]

assert.false(
deepEqual(val1, val2),
'deepEqual should return false if nested arrays are not equal'
)
assert.end()
})

test('Equal arrays with objects', (assert) => {
const val1 = [{ foo: 'bar', bar: 'foo' }, { hello: 'world' }]
const val2 = [{ foo: 'bar', bar: 'foo' }, { hello: 'world' }]

assert.true(
deepEqual(val1, val2),
'deepEqual should return true if arrays with objects are equal'
)
assert.end()
})

test('Not equal arrays with objects (keys', (assert) => {
const val1 = [{ foo: 'bar', bar: 'foo' }, { test: 'bla' }]
const val2 = [{ foo2: 'bar', bar2: 'foo' }, { test: 'bla' }]

assert.false(
deepEqual(val1, val2),
'deepEqual should return false if arrays with objects are not equal'
)
assert.end()
})

test('Equal arrays with mixed values', (assert) => {
const val1 = ['foo', { foo: 'bar', bar: 'foo' }, ['hello', 'world', ['this', 'is', { level: 2 }]]]
const val2 = ['foo', { foo: 'bar', bar: 'foo' }, ['hello', 'world', ['this', 'is', { level: 2 }]]]

assert.true(
deepEqual(val1, val2),
'deepEqual should return true if arrays with mixed values are equal'
)
assert.end()
})

test('Not Equal arrays with mixed values', (assert) => {
const val1 = ['foo', { foo: 'bar', bar: 'foo' }, ['hello', 'world', ['this', 'is', { level: 2 }]]]
const val2 = ['foo', { foo: 'bar', bar: 'foo' }, ['hello', 'world', ['this', 'is', { level: 3 }]]]

assert.false(
deepEqual(val1, val2),
'deepEqual should return true if arrays with mixed values are not equal'
)
assert.end()
})
11 changes: 5 additions & 6 deletions src/lib/codegenerator/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,11 @@ const generateComponentCode = function (
templateObject[key],
options.component
)}`)
renderCode.push(
`props${counter}['${key.substring(1)}'] = ${interpolate(
templateObject[key],
options.component
)}`
)
renderCode.push(`
props${counter}['${key.substring(1)}']= ${interpolate(
templateObject[key],
options.component
)}`)
} else {
renderCode.push(
`props${counter}['${key}'] = ${cast(templateObject[key], key, options.component)}`
Expand Down
23 changes: 15 additions & 8 deletions src/lib/reactivity/reactive.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import { ImageTexture } from '@lightningjs/renderer'
import { track, trigger, pauseTracking, resumeTracking } from './effect.js'
import symbols from '../symbols.js'
import deepEqualArray from '../../helpers/deepEqualArray.js'

const arrayPatchMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort']

Expand All @@ -38,7 +39,7 @@ const reactiveProxy = (original, _parent = null, _key, global) => {

// if original object is already a proxy, don't create a new one but return the existing one instead
const existingProxy = proxyMap.get(original)
if (existingProxy) {
if (existingProxy !== undefined) {
return existingProxy
}

Expand All @@ -50,9 +51,9 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
}

// handling arrays
if (Array.isArray(target)) {
if (Array.isArray(target) === true) {
if (typeof target[key] === 'object' && target[key] !== null) {
if (Array.isArray(target[key])) {
if (Array.isArray(target[key]) === true) {
track(target, key, global)
}
// create a new reactive proxy
Expand Down Expand Up @@ -80,7 +81,7 @@ const reactiveProxy = (original, _parent = null, _key, global) => {

// handling objects (but not null values, which have object type in JS)
if (typeof target[key] === 'object' && target[key] !== null) {
if (Array.isArray(target[key])) {
if (Array.isArray(target[key]) === true) {
track(target, key, global)
}
// create a new reactive proxy
Expand All @@ -99,13 +100,19 @@ const reactiveProxy = (original, _parent = null, _key, global) => {
const rawValue = getRaw(value)

let result = true
if (oldRawValue !== rawValue) {
const isEqual =
Array.isArray(rawValue) === true
? deepEqualArray(oldRawValue, rawValue)
: oldRawValue === rawValue

if (isEqual === false) {
if (Array.isArray(value) === true) value = getRaw(value).slice(0)
result = Reflect.set(target, key, value, receiver)
}

if (result && oldRawValue !== rawValue) {
if (result === true && isEqual === false) {
// if we're assigning an array key directly trigger reactivity on the parent key as well
if (Array.isArray(target) && key in target) {
if (Array.isArray(target) === true && key in target === true) {
trigger(_parent, _key, true)
}
trigger(target, key, true)
Expand All @@ -126,7 +133,7 @@ const reactiveDefineProperty = (target, global) => {
if (target[key] !== null && typeof target[key] === 'object') {
if (Object.getPrototypeOf(target[key]) === Object.prototype) {
return reactiveDefineProperty(target[key])
} else if (Array.isArray(target[key])) {
} else if (Array.isArray(target[key]) === true) {
for (let i = 0; i < arrayPatchMethods.length - 1; i++) {
target[key][arrayPatchMethods[i]] = function (v) {
Array.prototype[arrayPatchMethods[i]].call(this, v)
Expand Down

0 comments on commit 3f3143a

Please sign in to comment.