release: v1.0.14 By: AICoder
This commit is contained in:
parent
b04be8d437
commit
a777f315b4
@ -1,5 +1,11 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v1.0.14 (2026-06-05)
|
||||
|
||||
### 修复
|
||||
- **微任务扫描死循环**: 引入 `_stScanned` 标记对新挂载节点进行幂等拦截,防止在复杂嵌套(如 `$if` / `$each`)及大数据量场景下,新老节点重组重排循环触发 MutationObserver 造成浏览器卡死的微任务无限扫描死循环。
|
||||
- **状态更新防御**: 在 `_updateBinding` 逻辑中加入同值校验,避免当目标值与原值相等时重复赋值,杜绝不必要的 Observer 触发与重绘。
|
||||
|
||||
## v1.0.13 (2026-05-26)
|
||||
|
||||
### 新特性
|
||||
|
||||
10
dist/state.js
vendored
10
dist/state.js
vendored
@ -244,7 +244,9 @@
|
||||
if (typeof result === "object" && result != null && !Array.isArray(result) && o[lk] == null) o[lk] = {};
|
||||
const lo = o[lk];
|
||||
if (typeof lo === "object" && lo != null && lo.__watch) Object.assign(lo, result);
|
||||
else o[lk] = result;
|
||||
else {
|
||||
if (o[lk] !== result) o[lk] = result;
|
||||
}
|
||||
} else if (typeof result === "object" && result != null && !Array.isArray(result)) {
|
||||
Object.assign(o, result);
|
||||
}
|
||||
@ -475,6 +477,7 @@
|
||||
return;
|
||||
}
|
||||
if (node.nodeType !== 1) return;
|
||||
node._stScanned = true;
|
||||
if (!node._stTranslated) {
|
||||
Array.from(node.attributes).forEach((attr) => {
|
||||
if (!attr.name.startsWith("$") && !attr.name.startsWith("st-") && !attr.name.startsWith(".")) {
|
||||
@ -693,7 +696,10 @@
|
||||
new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
mutation.addedNodes.forEach((newNode) => {
|
||||
if (newNode.isConnected) _scanTree(newNode);
|
||||
if (newNode.isConnected && newNode.nodeType === 1 && !newNode._stScanned) {
|
||||
newNode._stScanned = true;
|
||||
_scanTree(newNode);
|
||||
}
|
||||
});
|
||||
mutation.removedNodes.forEach((oldNode) => _unbindTree(oldNode));
|
||||
});
|
||||
|
||||
2
dist/state.min.js
vendored
2
dist/state.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/state.min.mjs
vendored
2
dist/state.min.mjs
vendored
File diff suppressed because one or more lines are too long
10
dist/state.mjs
vendored
10
dist/state.mjs
vendored
@ -240,7 +240,9 @@ function _updateBinding(binding) {
|
||||
if (typeof result === "object" && result != null && !Array.isArray(result) && o[lk] == null) o[lk] = {};
|
||||
const lo = o[lk];
|
||||
if (typeof lo === "object" && lo != null && lo.__watch) Object.assign(lo, result);
|
||||
else o[lk] = result;
|
||||
else {
|
||||
if (o[lk] !== result) o[lk] = result;
|
||||
}
|
||||
} else if (typeof result === "object" && result != null && !Array.isArray(result)) {
|
||||
Object.assign(o, result);
|
||||
}
|
||||
@ -471,6 +473,7 @@ const _scanTree = (node, scanObj = {}) => {
|
||||
return;
|
||||
}
|
||||
if (node.nodeType !== 1) return;
|
||||
node._stScanned = true;
|
||||
if (!node._stTranslated) {
|
||||
Array.from(node.attributes).forEach((attr) => {
|
||||
if (!attr.name.startsWith("$") && !attr.name.startsWith("st-") && !attr.name.startsWith(".")) {
|
||||
@ -689,7 +692,10 @@ if (typeof document !== "undefined") {
|
||||
new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
mutation.addedNodes.forEach((newNode) => {
|
||||
if (newNode.isConnected) _scanTree(newNode);
|
||||
if (newNode.isConnected && newNode.nodeType === 1 && !newNode._stScanned) {
|
||||
newNode._stScanned = true;
|
||||
_scanTree(newNode);
|
||||
}
|
||||
});
|
||||
mutation.removedNodes.forEach((oldNode) => _unbindTree(oldNode));
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@apigo.cc/state",
|
||||
"version": "1.0.13",
|
||||
"version": "1.0.14",
|
||||
"type": "module",
|
||||
"main": "dist/state.js",
|
||||
"module": "dist/state.js",
|
||||
|
||||
@ -76,7 +76,7 @@ export function _updateBinding(binding) {
|
||||
if (typeof result === 'object' && result != null && !Array.isArray(result) && o[lk] == null) o[lk] = {};
|
||||
const lo = o[lk];
|
||||
if (typeof lo === 'object' && lo != null && lo.__watch) Object.assign(lo, result);
|
||||
else o[lk] = result;
|
||||
else { if (o[lk] !== result) o[lk] = result; }
|
||||
} else if (typeof result === 'object' && result != null && !Array.isArray(result)) {
|
||||
Object.assign(o, result);
|
||||
}
|
||||
@ -308,6 +308,7 @@ export const _scanTree = (node, scanObj = {}) => {
|
||||
node._stTranslated = true; return;
|
||||
}
|
||||
if (node.nodeType !== 1) return;
|
||||
node._stScanned = true;
|
||||
|
||||
if (!node._stTranslated) {
|
||||
Array.from(node.attributes).forEach(attr => {
|
||||
|
||||
@ -28,7 +28,10 @@ if (typeof document !== 'undefined') {
|
||||
new MutationObserver(mutations => {
|
||||
mutations.forEach(mutation => {
|
||||
mutation.addedNodes.forEach(newNode => {
|
||||
if (newNode.isConnected) _scanTree(newNode);
|
||||
if (newNode.isConnected && newNode.nodeType === 1 && !newNode._stScanned) {
|
||||
newNode._stScanned = true;
|
||||
_scanTree(newNode);
|
||||
}
|
||||
});
|
||||
mutation.removedNodes.forEach(oldNode => _unbindTree(oldNode));
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user