bobe 0.0.59 → 0.0.61
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/dist/bobe.cjs.js +142 -27
- package/dist/bobe.cjs.js.map +1 -1
- package/dist/bobe.compiler.cjs.js +142 -27
- package/dist/bobe.compiler.cjs.js.map +1 -1
- package/dist/bobe.compiler.esm.js +142 -27
- package/dist/bobe.compiler.esm.js.map +1 -1
- package/dist/bobe.esm.js +142 -27
- package/dist/bobe.esm.js.map +1 -1
- package/dist/index.d.ts +18 -5
- package/dist/index.umd.js +142 -27
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
|
@@ -33,15 +33,15 @@ let FakeType = function (FakeType) {
|
|
|
33
33
|
FakeType[FakeType["ForItem"] = 64] = "ForItem";
|
|
34
34
|
FakeType[FakeType["Context"] = 128] = "Context";
|
|
35
35
|
FakeType[FakeType["DynamicText"] = 256] = "DynamicText";
|
|
36
|
+
FakeType[FakeType["Tp"] = 512] = "Tp";
|
|
36
37
|
return FakeType;
|
|
37
38
|
}({});
|
|
38
39
|
const CondBit = FakeType.If | FakeType.Fail | FakeType.Else;
|
|
39
|
-
const LogicalBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.For | FakeType.ForItem;
|
|
40
40
|
const CtxProviderBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.For | FakeType.ForItem | FakeType.Component | FakeType.Fragment | FakeType.DynamicText;
|
|
41
|
-
const ContextBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.ForItem | FakeType.Context;
|
|
41
|
+
const ContextBit = FakeType.If | FakeType.Fail | FakeType.Else | FakeType.ForItem | FakeType.Context | FakeType.Tp;
|
|
42
42
|
const TokenizerSwitcherBit = FakeType.Component | FakeType.Fragment;
|
|
43
43
|
let NodeSort = function (NodeSort) {
|
|
44
|
-
NodeSort[NodeSort["
|
|
44
|
+
NodeSort[NodeSort["EffectNode"] = 1] = "EffectNode";
|
|
45
45
|
NodeSort[NodeSort["Real"] = 2] = "Real";
|
|
46
46
|
NodeSort[NodeSort["Component"] = 4] = "Component";
|
|
47
47
|
NodeSort[NodeSort["CtxProvider"] = 8] = "CtxProvider";
|
|
@@ -54,6 +54,7 @@ let NodeSort = function (NodeSort) {
|
|
|
54
54
|
TerpEvt["HandledComponentNode"] = "handled-component-node";
|
|
55
55
|
return TerpEvt;
|
|
56
56
|
})({});
|
|
57
|
+
const FakeNode = Symbol('fake-node');
|
|
57
58
|
let ParseErrorCode = function (ParseErrorCode) {
|
|
58
59
|
ParseErrorCode[ParseErrorCode["UNCLOSED_BRACE"] = 9001] = "UNCLOSED_BRACE";
|
|
59
60
|
ParseErrorCode[ParseErrorCode["UNCLOSED_STRING"] = 9002] = "UNCLOSED_STRING";
|
|
@@ -1456,6 +1457,14 @@ class InlineFragment {
|
|
|
1456
1457
|
}
|
|
1457
1458
|
const isUI = fn => typeof fn === 'function' && fn.__BOBE_IS_UI;
|
|
1458
1459
|
const isRenderAble = val => isStore(val) || isUI(val) || val instanceof InlineFragment;
|
|
1460
|
+
const SAFE_HANDLER = {
|
|
1461
|
+
has: () => true,
|
|
1462
|
+
get: (t, k) => {
|
|
1463
|
+
if (typeof k === 'symbol') return t[k];
|
|
1464
|
+
return k in t ? t[k] : undefined;
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
const safe = data => new Proxy(data, SAFE_HANDLER);
|
|
1459
1468
|
|
|
1460
1469
|
const KEY_INDEX = '__BOBE_KEY_INDEX';
|
|
1461
1470
|
let _ctxStack;
|
|
@@ -1467,9 +1476,6 @@ class Interpreter {
|
|
|
1467
1476
|
constructor(tokenizer) {
|
|
1468
1477
|
this.tokenizer = tokenizer;
|
|
1469
1478
|
}
|
|
1470
|
-
isLogicNode(node) {
|
|
1471
|
-
return node && node.__logicType & LogicalBit;
|
|
1472
|
-
}
|
|
1473
1479
|
rootComponent = null;
|
|
1474
1480
|
program(root, componentNode, before, ctxProvider) {
|
|
1475
1481
|
this.rootComponent = componentNode;
|
|
@@ -1488,7 +1494,7 @@ class Interpreter {
|
|
|
1488
1494
|
stack.push({
|
|
1489
1495
|
node: ctxProvider,
|
|
1490
1496
|
prev: null
|
|
1491
|
-
}, (ctxProvider.__logicType
|
|
1497
|
+
}, (ctxProvider.__logicType && ctxProvider.effect ? NodeSort.EffectNode : 0) | NodeSort.CtxProvider);
|
|
1492
1498
|
}
|
|
1493
1499
|
const rootLen = stack.length;
|
|
1494
1500
|
const ctx = this.ctx = {
|
|
@@ -1511,18 +1517,22 @@ class Interpreter {
|
|
|
1511
1517
|
const token = this.tokenizer.token;
|
|
1512
1518
|
if (token.type & TokenType.Indent) {
|
|
1513
1519
|
this.tokenizer.nextToken();
|
|
1514
|
-
const
|
|
1520
|
+
const isEffectNode = ctx.current && ctx.current.__logicType && ctx.current.effect;
|
|
1515
1521
|
stack.push({
|
|
1516
1522
|
node: ctx.current,
|
|
1517
1523
|
prev: ctx.prevSibling
|
|
1518
|
-
}, !ctx.current.__logicType ? NodeSort.Real : (
|
|
1524
|
+
}, !ctx.current.__logicType ? NodeSort.Real : (isEffectNode ? NodeSort.EffectNode : 0) | (ctx.current.__logicType & TokenizerSwitcherBit ? NodeSort.TokenizerSwitcher : 0) | (ctx.current.__logicType & ContextBit ? NodeSort.Context : 0) | (ctx.current.__logicType === FakeType.Component ? NodeSort.Component : 0) | (ctx.current.__logicType & CtxProviderBit ? NodeSort.CtxProvider : 0));
|
|
1519
1525
|
if (ctx.current.__logicType) {
|
|
1520
1526
|
this.beforeLogicIndent?.(ctx.current);
|
|
1521
|
-
if (
|
|
1527
|
+
if (isEffectNode) {
|
|
1522
1528
|
setPulling(ctx.current.effect);
|
|
1523
1529
|
if (ctx.current.__logicType & FakeType.ForItem) {
|
|
1524
1530
|
ctx.prevSibling = ctx.current.realBefore;
|
|
1525
1531
|
}
|
|
1532
|
+
if (ctx.current.__logicType & FakeType.Tp) {
|
|
1533
|
+
ctx.realParent = ctx.current.tpData[Keys.Raw].node;
|
|
1534
|
+
ctx.prevSibling = ctx.current.contentBefore;
|
|
1535
|
+
}
|
|
1526
1536
|
}
|
|
1527
1537
|
} else {
|
|
1528
1538
|
if (ctx.current) {
|
|
@@ -1558,14 +1568,17 @@ class Interpreter {
|
|
|
1558
1568
|
const prevSameType = stack.peekByType(NodeSort.Real);
|
|
1559
1569
|
ctx.realParent = prevSameType?.node || root;
|
|
1560
1570
|
} else {
|
|
1561
|
-
if (sort & NodeSort.
|
|
1562
|
-
const parentLogic = stack.peekByType(NodeSort.
|
|
1571
|
+
if (sort & NodeSort.EffectNode) {
|
|
1572
|
+
const parentLogic = stack.peekByType(NodeSort.EffectNode)?.node;
|
|
1563
1573
|
if (parentLogic) {
|
|
1564
1574
|
setPulling(parentLogic.effect);
|
|
1565
1575
|
} else {
|
|
1566
1576
|
setPulling(rootPulling);
|
|
1567
1577
|
}
|
|
1568
1578
|
}
|
|
1579
|
+
if (parent.__logicType === FakeType.Tp) {
|
|
1580
|
+
ctx.realParent = parent.realParent;
|
|
1581
|
+
}
|
|
1569
1582
|
if (sort & NodeSort.TokenizerSwitcher) {
|
|
1570
1583
|
const switcher = stack.peekByType(NodeSort.TokenizerSwitcher)?.node;
|
|
1571
1584
|
if (parent.resumeSnapshot) {
|
|
@@ -1602,13 +1615,17 @@ class Interpreter {
|
|
|
1602
1615
|
}
|
|
1603
1616
|
return componentNode;
|
|
1604
1617
|
}
|
|
1605
|
-
insertAnchor(name = 'anchor', isBefore = false) {
|
|
1618
|
+
insertAnchor(node, name = 'anchor', isBefore = false) {
|
|
1606
1619
|
const _this$ctx = this.ctx,
|
|
1607
1620
|
realParent = _this$ctx.realParent,
|
|
1608
1621
|
prevSibling = _this$ctx.prevSibling,
|
|
1609
1622
|
stack = _this$ctx.stack,
|
|
1610
1623
|
before = _this$ctx.before;
|
|
1624
|
+
_this$ctx.current;
|
|
1611
1625
|
const afterAnchor = this.createAnchor(name, isBefore);
|
|
1626
|
+
if (!isBefore) {
|
|
1627
|
+
this.anchorRefBack(afterAnchor, node);
|
|
1628
|
+
}
|
|
1612
1629
|
this.ctx.prevSibling = stack.length === 2 && !prevSibling ? before : prevSibling;
|
|
1613
1630
|
this.handleInsert(realParent, afterAnchor, prevSibling);
|
|
1614
1631
|
return afterAnchor;
|
|
@@ -1653,6 +1670,8 @@ class Interpreter {
|
|
|
1653
1670
|
return this.condDeclaration(ctx);
|
|
1654
1671
|
} else if (value === 'context') {
|
|
1655
1672
|
_node = this.createContextNode();
|
|
1673
|
+
} else if (value === 'tp') {
|
|
1674
|
+
return this.createTpNode();
|
|
1656
1675
|
} else if (value === 'for') {
|
|
1657
1676
|
return this.forDeclaration();
|
|
1658
1677
|
} else if (hookType) {
|
|
@@ -1692,11 +1711,11 @@ class Interpreter {
|
|
|
1692
1711
|
effect: null,
|
|
1693
1712
|
textNode: null,
|
|
1694
1713
|
owner: ctx.stack.peekByType(NodeSort.TokenizerSwitcher)?.node,
|
|
1695
|
-
snapshot: this.tokenizer.snapshot(['dentStack']),
|
|
1714
|
+
snapshot: this.tokenizer.snapshot(['dentStack', 'isFirstToken']),
|
|
1696
1715
|
parentDataProvider: ctx.stack.peekByType(NodeSort.CtxProvider)?.node
|
|
1697
1716
|
};
|
|
1698
1717
|
let isUpdate = false;
|
|
1699
|
-
node.realAfter = this.insertAnchor(`dynamic-after`);
|
|
1718
|
+
node.realAfter = this.insertAnchor(node, `dynamic-after`);
|
|
1700
1719
|
node.effect = this.effect(({
|
|
1701
1720
|
old,
|
|
1702
1721
|
val
|
|
@@ -1705,7 +1724,7 @@ class Interpreter {
|
|
|
1705
1724
|
oldTextNode = node.textNode;
|
|
1706
1725
|
if (oldLogicType) {
|
|
1707
1726
|
this.removeLogicNode(node);
|
|
1708
|
-
pickInPlace(node, ['realParent', 'realBefore', 'realAfter'
|
|
1727
|
+
pickInPlace(node, ['realParent', 'realBefore', 'realAfter', 'owner', 'snapshot', 'parentDataProvider']);
|
|
1709
1728
|
}
|
|
1710
1729
|
if (isRenderAble(val)) {
|
|
1711
1730
|
if (oldTextNode) {
|
|
@@ -1735,7 +1754,7 @@ class Interpreter {
|
|
|
1735
1754
|
}
|
|
1736
1755
|
if (isUpdate) {
|
|
1737
1756
|
this.tokenizer.useDedentAsEof = false;
|
|
1738
|
-
this.program(node.realParent, node
|
|
1757
|
+
this.program(node.realParent, node, node.realBefore);
|
|
1739
1758
|
} else {
|
|
1740
1759
|
this.tokenizer.useDedentAsEof = true;
|
|
1741
1760
|
this.tokenizer.initIndentWhenUseDedentAsEof();
|
|
@@ -1776,6 +1795,93 @@ class Interpreter {
|
|
|
1776
1795
|
});
|
|
1777
1796
|
return node;
|
|
1778
1797
|
}
|
|
1798
|
+
createTpNode() {
|
|
1799
|
+
const child = deepSignal({}, getPulling());
|
|
1800
|
+
const node = {
|
|
1801
|
+
__logicType: FakeType.Tp,
|
|
1802
|
+
data: this.getData(),
|
|
1803
|
+
realParent: null,
|
|
1804
|
+
realBefore: null,
|
|
1805
|
+
realAfter: null,
|
|
1806
|
+
contentBefore: null,
|
|
1807
|
+
contentAfter: null,
|
|
1808
|
+
effect: null,
|
|
1809
|
+
snapshot: null,
|
|
1810
|
+
tpData: child,
|
|
1811
|
+
owner: this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)?.node
|
|
1812
|
+
};
|
|
1813
|
+
this.onePropParsed = createStoreOnePropParsed(child);
|
|
1814
|
+
this.tokenizer.nextToken();
|
|
1815
|
+
this.headerLineAndExtensions(node);
|
|
1816
|
+
this.onePropParsed = this.oneRealPropParsed;
|
|
1817
|
+
node.realAfter = this.insertAnchor(node, 'tp-after');
|
|
1818
|
+
const before = node.contentBefore = this.createAnchor('tp-content-before', true);
|
|
1819
|
+
const after = node.contentAfter = this.createAnchor('tp-content-after', true);
|
|
1820
|
+
let firstRender = true;
|
|
1821
|
+
node.effect = this.effect(({
|
|
1822
|
+
old: oldDom,
|
|
1823
|
+
val: dom
|
|
1824
|
+
}) => {
|
|
1825
|
+
const removeTpChild = () => {
|
|
1826
|
+
if (oldDom) {
|
|
1827
|
+
let point = before;
|
|
1828
|
+
do {
|
|
1829
|
+
const next = this.nextSib(point);
|
|
1830
|
+
this.remove(point, oldDom, null);
|
|
1831
|
+
if (point === after) break;
|
|
1832
|
+
point = next;
|
|
1833
|
+
} while (true);
|
|
1834
|
+
}
|
|
1835
|
+
};
|
|
1836
|
+
if (firstRender) {
|
|
1837
|
+
if (dom) {
|
|
1838
|
+
this.handleInsert(dom, after, null);
|
|
1839
|
+
this.handleInsert(dom, before, null);
|
|
1840
|
+
} else {
|
|
1841
|
+
if (this.tokenizer.token.type === TokenType.Indent) {
|
|
1842
|
+
const dentLen = this.tokenizer.dentStack[this.tokenizer.dentStack.length - 2] ?? 0;
|
|
1843
|
+
this.tokenizer.skip(dentLen);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
} else {
|
|
1847
|
+
if (dom) {
|
|
1848
|
+
if (oldDom) {
|
|
1849
|
+
let point = before,
|
|
1850
|
+
lastInsert = null;
|
|
1851
|
+
do {
|
|
1852
|
+
const next = this.nextSib(point);
|
|
1853
|
+
const fakeNode = point[FakeNode];
|
|
1854
|
+
if (fakeNode) {
|
|
1855
|
+
fakeNode.realParent = dom;
|
|
1856
|
+
}
|
|
1857
|
+
this.handleInsert(dom, point, lastInsert);
|
|
1858
|
+
if (point === after) break;
|
|
1859
|
+
lastInsert = point;
|
|
1860
|
+
point = next;
|
|
1861
|
+
} while (true);
|
|
1862
|
+
} else {
|
|
1863
|
+
this.handleInsert(dom, after, null);
|
|
1864
|
+
this.handleInsert(dom, before, null);
|
|
1865
|
+
this.tokenizer = node.owner.tokenizer;
|
|
1866
|
+
this.tokenizer.resume(node.snapshot);
|
|
1867
|
+
this.tokenizer.useDedentAsEof = false;
|
|
1868
|
+
this.program(dom, node.owner, before, node);
|
|
1869
|
+
}
|
|
1870
|
+
} else {
|
|
1871
|
+
removeTpChild();
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
firstRender = false;
|
|
1875
|
+
return isDestroy => {
|
|
1876
|
+
if (isDestroy) {
|
|
1877
|
+
removeTpChild();
|
|
1878
|
+
}
|
|
1879
|
+
};
|
|
1880
|
+
}, [() => child.node], {
|
|
1881
|
+
type: 'render'
|
|
1882
|
+
});
|
|
1883
|
+
return node;
|
|
1884
|
+
}
|
|
1779
1885
|
createContextNode() {
|
|
1780
1886
|
const child = deepSignal({}, getPulling());
|
|
1781
1887
|
const parentContext = this.ctx.stack.peekByType(NodeSort.Context)?.node?.context;
|
|
@@ -1790,7 +1896,7 @@ class Interpreter {
|
|
|
1790
1896
|
realBefore: null,
|
|
1791
1897
|
realAfter: null
|
|
1792
1898
|
};
|
|
1793
|
-
node.realAfter = this.insertAnchor('context-after');
|
|
1899
|
+
node.realAfter = this.insertAnchor(node, 'context-after');
|
|
1794
1900
|
return node;
|
|
1795
1901
|
}
|
|
1796
1902
|
formatForCollection(collection) {
|
|
@@ -1880,15 +1986,15 @@ class Interpreter {
|
|
|
1880
1986
|
i: 0
|
|
1881
1987
|
};
|
|
1882
1988
|
if (keyExp) {
|
|
1883
|
-
|
|
1989
|
+
const rawGetKey = new Function('data', `with(data){return (${keyExp})}`);
|
|
1990
|
+
forNode.getKey = data => rawGetKey(safe(data));
|
|
1884
1991
|
}
|
|
1885
|
-
window['for1'] = forNode;
|
|
1886
1992
|
const data = this.getData();
|
|
1887
1993
|
const cells = data[Keys.Meta].cells;
|
|
1888
1994
|
const hasArrExpKey = Reflect.has(data[Keys.Raw], arrExp);
|
|
1889
1995
|
const arrSignal = hasArrExpKey ? (data[arrExp], cells.get(arrExp)) : new Computed(this.getFn(data, arrExp));
|
|
1890
1996
|
forNode.arrSignal = arrSignal;
|
|
1891
|
-
forNode.realAfter = this.insertAnchor('for-after');
|
|
1997
|
+
forNode.realAfter = this.insertAnchor(forNode, 'for-after');
|
|
1892
1998
|
const _forNode$snapshot = forNode.snapshot;
|
|
1893
1999
|
_forNode$snapshot.dentStack;
|
|
1894
2000
|
_forNode$snapshot.isFirstToken;
|
|
@@ -1911,8 +2017,8 @@ class Interpreter {
|
|
|
1911
2017
|
const len = arr.length;
|
|
1912
2018
|
for (let i = len; i--;) {
|
|
1913
2019
|
const item = this.createForItem(forNode, i, data);
|
|
1914
|
-
item.realAfter = this.insertAnchor('for-item-after');
|
|
1915
|
-
item.realBefore = this.insertAnchor('for-item-before', true);
|
|
2020
|
+
item.realAfter = this.insertAnchor(item, 'for-item-after');
|
|
2021
|
+
item.realBefore = this.insertAnchor(item, 'for-item-before', true);
|
|
1916
2022
|
item.realParent = forNode.realParent;
|
|
1917
2023
|
children[i] = item;
|
|
1918
2024
|
}
|
|
@@ -2074,10 +2180,14 @@ class Interpreter {
|
|
|
2074
2180
|
}, ScheduleType.Render);
|
|
2075
2181
|
return forNode.children[0] || forNode;
|
|
2076
2182
|
}
|
|
2183
|
+
anchorRefBack(anchor, node) {
|
|
2184
|
+
anchor[FakeNode] = node;
|
|
2185
|
+
}
|
|
2077
2186
|
insertForItem(forNode, i, parentData, newChildren, before, snapshotForUpdate) {
|
|
2078
2187
|
const item = this.createForItem(forNode, i, parentData);
|
|
2079
2188
|
newChildren[i] = item;
|
|
2080
2189
|
let realAfter = this.createAnchor('for-item-after');
|
|
2190
|
+
this.anchorRefBack(realAfter, item);
|
|
2081
2191
|
this.handleInsert(forNode.realParent, realAfter, before);
|
|
2082
2192
|
let realBefore = this.createAnchor('for-item-before', true);
|
|
2083
2193
|
this.handleInsert(forNode.realParent, realBefore, before);
|
|
@@ -2248,11 +2358,11 @@ class Interpreter {
|
|
|
2248
2358
|
resumeSnapshot
|
|
2249
2359
|
};
|
|
2250
2360
|
this.onePropParsed = onePropParsed;
|
|
2251
|
-
node.realAfter = this.insertAnchor('component-after');
|
|
2361
|
+
node.realAfter = this.insertAnchor(node, 'component-after');
|
|
2252
2362
|
return node;
|
|
2253
2363
|
}
|
|
2254
2364
|
getFn(data, expression) {
|
|
2255
|
-
return new Function('data', `
|
|
2365
|
+
return new Function('data', `with(data){return (${expression})}`).bind(undefined, safe(data));
|
|
2256
2366
|
}
|
|
2257
2367
|
getAssignFn(data, expression) {
|
|
2258
2368
|
const valueId = `value_bobe_${date32()}`;
|
|
@@ -2343,7 +2453,7 @@ class Interpreter {
|
|
|
2343
2453
|
break;
|
|
2344
2454
|
}
|
|
2345
2455
|
ifNode.condition = signal;
|
|
2346
|
-
ifNode.realAfter = this.insertAnchor(`${keyWord.value}-after`);
|
|
2456
|
+
ifNode.realAfter = this.insertAnchor(ifNode, `${keyWord.value}-after`);
|
|
2347
2457
|
const ef = this.effect(({
|
|
2348
2458
|
val
|
|
2349
2459
|
}) => {
|
|
@@ -2386,10 +2496,11 @@ class Interpreter {
|
|
|
2386
2496
|
const tokenizer = this.tokenizer;
|
|
2387
2497
|
do {
|
|
2388
2498
|
const isComponent = _node.__logicType & TokenizerSwitcherBit;
|
|
2499
|
+
const isTp = _node.__logicType === FakeType.Tp;
|
|
2389
2500
|
let snapshot, dentLen;
|
|
2390
2501
|
const data = this.getData();
|
|
2391
2502
|
const unHandledKey = this.attributeList(_node, data);
|
|
2392
|
-
if (isComponent) {
|
|
2503
|
+
if (isComponent || isTp) {
|
|
2393
2504
|
snapshot = tokenizer.snapshot(undefined, -1);
|
|
2394
2505
|
dentLen = tokenizer.dentStack[tokenizer.dentStack.length - 1];
|
|
2395
2506
|
}
|
|
@@ -2401,6 +2512,9 @@ class Interpreter {
|
|
|
2401
2512
|
if ((tokenizer.token.type & TokenType.Pipe) === 0) {
|
|
2402
2513
|
break;
|
|
2403
2514
|
}
|
|
2515
|
+
} else if (isTp) {
|
|
2516
|
+
_node.snapshot = snapshot;
|
|
2517
|
+
break;
|
|
2404
2518
|
} else {
|
|
2405
2519
|
break;
|
|
2406
2520
|
}
|
|
@@ -2602,6 +2716,7 @@ function bobe(fragments, ...values) {
|
|
|
2602
2716
|
return tokenizer;
|
|
2603
2717
|
};
|
|
2604
2718
|
ui.boundStore = Store.Current;
|
|
2719
|
+
ui[Keys.ProxyFreeObject] = true;
|
|
2605
2720
|
ui.__BOBE_IS_UI = true;
|
|
2606
2721
|
return ui;
|
|
2607
2722
|
}
|