iobroker.javascript 9.2.3 → 9.2.4
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/README.md +6 -14
- package/admin/assets/{AiChatPanel-C4zUsNmN.js → AiChatPanel-B4vPXgLz.js} +1 -1
- package/admin/assets/{ScriptEditor-C6W68ya0.js → ScriptEditor-CmEeMfC2.js} +1 -1
- package/admin/assets/{ScriptEditorVanillaMonaco-DYTcDqp_.js → ScriptEditorVanillaMonaco-C22Gpet7.js} +2 -2
- package/admin/assets/{index-crBQrXKG.js → index-7mrTpzQy.js} +1 -1
- package/admin/assets/{index-CUau9-il.js → index-BTQOdA7v.js} +28 -28
- package/admin/assets/{index-BXfqctma.js → index-Dggem6AX.js} +1 -1
- package/admin/assets/{stateHoverProvider-BYBqzJuX.js → stateHoverProvider-DxTNxyYN.js} +1 -1
- package/admin/custom/assets/{Components-jfkoGyES.js → Components-CGiJE5Zh.js} +1 -1
- package/admin/custom/assets/{index-CS_GBN2m.js → index-B6NrrORQ.js} +1 -1
- package/admin/custom/assets/index-CT5PwRfY.js +964 -0
- package/admin/custom/assets/{index-ChQotUCl.js → index-DTbSiEk2.js} +1 -1
- package/admin/custom/assets/{localSharedImportMap-BeObsVNc.js → localSharedImportMap-ChjFDKsq.js} +1 -1
- package/admin/custom/assets/{virtualExposes-wYe_Np-4.js → virtualExposes-D402kVGY.js} +1 -1
- package/admin/custom/assets/{virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-BcRVut8U.js → virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-ClQrb2n1.js} +2 -2
- package/admin/custom/customComponents.js +1 -1
- package/admin/i18n/es.json +77 -77
- package/admin/tab.html +1 -1
- package/build/lib/debugger.js +1 -1
- package/build/lib/debugger.js.map +1 -1
- package/build/lib/eventObj.js +10 -2
- package/build/lib/eventObj.js.map +1 -1
- package/build/lib/inspect.js +3 -3
- package/build/lib/inspect.js.map +1 -1
- package/build/lib/sandbox.js +169 -62
- package/build/lib/sandbox.js.map +1 -1
- package/build/main.js +63 -19
- package/build/main.js.map +1 -1
- package/build/types.d.ts +4 -0
- package/io-package.json +14 -14
- package/package.json +11 -11
- package/admin/custom/assets/index-qs6J40Tp.js +0 -964
package/build/lib/sandbox.js
CHANGED
|
@@ -33,6 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.isExactId = isExactId;
|
|
37
|
+
exports.removeFromDispatchIndex = removeFromDispatchIndex;
|
|
36
38
|
exports.sandBox = sandBox;
|
|
37
39
|
const jsonataMod = __importStar(require("jsonata"));
|
|
38
40
|
const adapter_core_1 = require("@iobroker/adapter-core");
|
|
@@ -43,6 +45,61 @@ const eventObjMod = __importStar(require("./eventObj"));
|
|
|
43
45
|
const patternCompareFunctions_1 = require("./patternCompareFunctions");
|
|
44
46
|
const SCRIPT_CODE_MARKER = 'script.js.';
|
|
45
47
|
const pattern2RegEx = adapter_core_1.commonTools.pattern2RegEx;
|
|
48
|
+
// Pre-compiled RegExp constants for formatTimeDiff – avoids recompiling on every call
|
|
49
|
+
const FTD_TEST_D = /(?<!\\)[DTД]/;
|
|
50
|
+
const FTD_REPL_DD = /(?<!\\)(?:DD|TT|ДД)/g;
|
|
51
|
+
const FTD_REPL_D = /(?<!\\)[DTД]/g;
|
|
52
|
+
const FTD_TEST_H = /(?<!\\)[hSч]/;
|
|
53
|
+
const FTD_REPL_HH = /(?<!\\)(?:hh|SS|чч)/g;
|
|
54
|
+
const FTD_REPL_H = /(?<!\\)[hSч]/g;
|
|
55
|
+
const FTD_TEST_M = /(?<!\\)[mм]/;
|
|
56
|
+
const FTD_REPL_MM = /(?<!\\)(?:mm|мм)/g;
|
|
57
|
+
const FTD_REPL_M = /(?<!\\)[mм]/g;
|
|
58
|
+
const FTD_TEST_S = /(?<!\\)[sс]/;
|
|
59
|
+
const FTD_REPL_SS = /(?<!\\)(?:ss|сс)/g;
|
|
60
|
+
const FTD_REPL_S = /(?<!\\)[sс]/g;
|
|
61
|
+
const FTD_UNESCAPE = [
|
|
62
|
+
[/\\([DTД])/g, '$1'],
|
|
63
|
+
[/\\([hSч])/g, '$1'],
|
|
64
|
+
[/\\([mм])/g, '$1'],
|
|
65
|
+
[/\\([sс])/g, '$1'],
|
|
66
|
+
];
|
|
67
|
+
/** Maximum number of cached selector RegExps before FIFO eviction kicks in */
|
|
68
|
+
const _SELECTOR_REGEXP_CACHE_MAX = 1000;
|
|
69
|
+
/** Cache for selector-string → RegExp to avoid recompiling identical patterns (FIFO-bounded) */
|
|
70
|
+
const _selectorRegExpCache = new Map();
|
|
71
|
+
/** Monotonically increasing handler-ID counter – avoids Date.now()+random collisions */
|
|
72
|
+
let _handlerIdCounter = 1;
|
|
73
|
+
/** Returns true when patId is a plain exact state-ID (no wildcards, no RegExp notation). */
|
|
74
|
+
function isExactId(patId) {
|
|
75
|
+
return (!!patId && typeof patId === 'string' && !patId.includes('*') && !patId.includes('?') && !patId.startsWith('/'));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Removes a subscription from the O(1) dispatch index (subscriptionsMap / subscriptionsWildcard).
|
|
79
|
+
* Must use the same exact-id classification as the subscribe side (isExactId),
|
|
80
|
+
* otherwise entries leak in the structure that was not searched.
|
|
81
|
+
*/
|
|
82
|
+
function removeFromDispatchIndex(ctx, sub) {
|
|
83
|
+
const patId = sub.pattern?.id;
|
|
84
|
+
if (isExactId(patId)) {
|
|
85
|
+
const bucket = ctx.subscriptionsMap.get(patId);
|
|
86
|
+
if (bucket) {
|
|
87
|
+
const pos = bucket.indexOf(sub);
|
|
88
|
+
if (pos !== -1) {
|
|
89
|
+
bucket.splice(pos, 1);
|
|
90
|
+
}
|
|
91
|
+
if (bucket.length === 0) {
|
|
92
|
+
ctx.subscriptionsMap.delete(patId);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const wPos = ctx.subscriptionsWildcard.indexOf(sub);
|
|
98
|
+
if (wPos !== -1) {
|
|
99
|
+
ctx.subscriptionsWildcard.splice(wPos, 1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
46
103
|
function sandBox(script, name, verbose, debug, context) {
|
|
47
104
|
const consts = constsMod;
|
|
48
105
|
const words = wordsMod;
|
|
@@ -211,14 +268,24 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
211
268
|
* @param str The selector string to transform into a regular expression
|
|
212
269
|
*/
|
|
213
270
|
function selectorStringToRegExp(str) {
|
|
271
|
+
const cached = _selectorRegExpCache.get(str);
|
|
272
|
+
if (cached) {
|
|
273
|
+
return cached;
|
|
274
|
+
}
|
|
214
275
|
const startsWithWildcard = str[0] === '*';
|
|
215
276
|
const endsWithWildcard = str[str.length - 1] === '*';
|
|
216
|
-
// Sanitize the selector, so it is safe to use in a RegEx
|
|
217
|
-
// Taken from https://stackoverflow.com/a/3561711/10179833 but modified
|
|
218
|
-
// since * has a special meaning in our selector and should not be escaped
|
|
219
277
|
// eslint-disable-next-line no-useless-escape
|
|
220
|
-
|
|
221
|
-
|
|
278
|
+
const escaped = str.replace(/[-\/\\^$+?.()|[\]{}]/g, '\\$&').replace(/\*/g, '.*');
|
|
279
|
+
const re = new RegExp((startsWithWildcard ? '' : '^') + escaped + (endsWithWildcard ? '' : '$'));
|
|
280
|
+
// FIFO eviction: drop the oldest entry once the cache exceeds its limit
|
|
281
|
+
if (_selectorRegExpCache.size >= _SELECTOR_REGEXP_CACHE_MAX) {
|
|
282
|
+
const oldestKey = _selectorRegExpCache.keys().next().value;
|
|
283
|
+
if (oldestKey !== undefined) {
|
|
284
|
+
_selectorRegExpCache.delete(oldestKey);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
_selectorRegExpCache.set(str, re);
|
|
288
|
+
return re;
|
|
222
289
|
}
|
|
223
290
|
/**
|
|
224
291
|
* Adds a regular expression for selectors targeting the state ID
|
|
@@ -741,8 +808,8 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
741
808
|
if (!context.channels || !context.devices) {
|
|
742
809
|
context.channels = {};
|
|
743
810
|
context.devices = {};
|
|
744
|
-
for (const _id
|
|
745
|
-
if (
|
|
811
|
+
for (const _id of Object.keys(objects)) {
|
|
812
|
+
if (objects[_id].type === 'state') {
|
|
746
813
|
const parts = _id.split('.');
|
|
747
814
|
parts.pop();
|
|
748
815
|
const chn = parts.join('.');
|
|
@@ -759,8 +826,8 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
759
826
|
if (name === 'schedule') {
|
|
760
827
|
if (!context.schedules) {
|
|
761
828
|
context.schedules = [];
|
|
762
|
-
for (const _id
|
|
763
|
-
if (
|
|
829
|
+
for (const _id of Object.keys(objects)) {
|
|
830
|
+
if (objects[_id].type === 'schedule') {
|
|
764
831
|
context.schedules.push(_id);
|
|
765
832
|
}
|
|
766
833
|
}
|
|
@@ -1087,7 +1154,7 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
1087
1154
|
sandbox.log(`Invalid callback for onLog`, 'warn');
|
|
1088
1155
|
return 0;
|
|
1089
1156
|
}
|
|
1090
|
-
const handler = { id:
|
|
1157
|
+
const handler = { id: _handlerIdCounter++, cb: callback, sandbox, severity };
|
|
1091
1158
|
context.logSubscriptions[sandbox.scriptName] = context.logSubscriptions[sandbox.scriptName] || [];
|
|
1092
1159
|
context.logSubscriptions[sandbox.scriptName].push(handler);
|
|
1093
1160
|
context.updateLogSubscriptions();
|
|
@@ -1455,6 +1522,16 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
1455
1522
|
subscribePattern(script, oPattern.id);
|
|
1456
1523
|
subs.patternCompareFunctions = getPatternCompareFunctions(oPattern);
|
|
1457
1524
|
context.subscriptions.push(subs);
|
|
1525
|
+
// O(1) dispatch index: exact string IDs go into the map, everything else into the wildcard array
|
|
1526
|
+
if (isExactId(oPattern.id)) {
|
|
1527
|
+
if (!context.subscriptionsMap.has(oPattern.id)) {
|
|
1528
|
+
context.subscriptionsMap.set(oPattern.id, []);
|
|
1529
|
+
}
|
|
1530
|
+
context.subscriptionsMap.get(oPattern.id).push(subs);
|
|
1531
|
+
}
|
|
1532
|
+
else {
|
|
1533
|
+
context.subscriptionsWildcard.push(subs);
|
|
1534
|
+
}
|
|
1458
1535
|
if (oPattern.enumName || oPattern.enumId) {
|
|
1459
1536
|
context.isEnums = true;
|
|
1460
1537
|
}
|
|
@@ -1462,13 +1539,13 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
1462
1539
|
},
|
|
1463
1540
|
getSubscriptions: function () {
|
|
1464
1541
|
const result = {};
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
});
|
|
1542
|
+
// Iterate over the O(1) dispatch index instead of the flat array
|
|
1543
|
+
for (const [id, bucket] of context.subscriptionsMap) {
|
|
1544
|
+
result[id] = bucket.map(s => ({ name: s.name, pattern: s.pattern }));
|
|
1545
|
+
}
|
|
1546
|
+
for (const s of context.subscriptionsWildcard) {
|
|
1547
|
+
const key = s.pattern.id;
|
|
1548
|
+
(result[key] ??= []).push({ name: s.name, pattern: s.pattern });
|
|
1472
1549
|
}
|
|
1473
1550
|
if (sandbox.verbose) {
|
|
1474
1551
|
sandbox.log(`getSubscriptions() => ${JSON.stringify(result)}`, 'info');
|
|
@@ -1527,8 +1604,11 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
1527
1604
|
if ((0, tools_1.isObject)(idOrObject)) {
|
|
1528
1605
|
for (let i = context.subscriptions.length - 1; i >= 0; i--) {
|
|
1529
1606
|
if (context.subscriptions[i] === idOrObject) {
|
|
1530
|
-
|
|
1607
|
+
const sub = context.subscriptions[i];
|
|
1608
|
+
unsubscribePattern(script, sub.pattern.id);
|
|
1531
1609
|
context.subscriptions.splice(i, 1);
|
|
1610
|
+
// Remove from O(1) dispatch structures
|
|
1611
|
+
removeFromDispatchIndex(context, sub);
|
|
1532
1612
|
sandbox.__engine.__subscriptions--;
|
|
1533
1613
|
return true;
|
|
1534
1614
|
}
|
|
@@ -1539,8 +1619,11 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
1539
1619
|
for (let i = context.subscriptions.length - 1; i >= 0; i--) {
|
|
1540
1620
|
if (context.subscriptions[i].name === name && context.subscriptions[i].pattern.id === idOrObject) {
|
|
1541
1621
|
deleted++;
|
|
1542
|
-
|
|
1622
|
+
const sub = context.subscriptions[i];
|
|
1623
|
+
unsubscribePattern(script, sub.pattern.id);
|
|
1543
1624
|
context.subscriptions.splice(i, 1);
|
|
1625
|
+
// Remove from O(1) dispatch structures
|
|
1626
|
+
removeFromDispatchIndex(context, sub);
|
|
1544
1627
|
sandbox.__engine.__subscriptions--;
|
|
1545
1628
|
}
|
|
1546
1629
|
}
|
|
@@ -2459,7 +2542,7 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
2459
2542
|
}
|
|
2460
2543
|
let result;
|
|
2461
2544
|
try {
|
|
2462
|
-
result =
|
|
2545
|
+
result = objects[id] ? structuredClone(objects[id]) : undefined;
|
|
2463
2546
|
}
|
|
2464
2547
|
catch (err) {
|
|
2465
2548
|
void adapter.setState(`scriptProblem.${name.substring(SCRIPT_CODE_MARKER.length)}`, {
|
|
@@ -2484,9 +2567,9 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
2484
2567
|
}
|
|
2485
2568
|
if (enumName) {
|
|
2486
2569
|
const e = eventObj.getObjectEnumsSync(context, id);
|
|
2487
|
-
const obj =
|
|
2488
|
-
obj.enumIds =
|
|
2489
|
-
obj.enumNames =
|
|
2570
|
+
const obj = structuredClone(objects[id]);
|
|
2571
|
+
obj.enumIds = structuredClone(e.enumIds);
|
|
2572
|
+
obj.enumNames = structuredClone(e.enumNames);
|
|
2490
2573
|
if (typeof enumName === 'string') {
|
|
2491
2574
|
const r = new RegExp(`^enum\\.${enumName}\\.`);
|
|
2492
2575
|
for (let i = obj.enumIds.length - 1; i >= 0; i--) {
|
|
@@ -2502,7 +2585,7 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
2502
2585
|
}
|
|
2503
2586
|
let result;
|
|
2504
2587
|
try {
|
|
2505
|
-
result =
|
|
2588
|
+
result = structuredClone(objects[id]);
|
|
2506
2589
|
}
|
|
2507
2590
|
catch (err) {
|
|
2508
2591
|
void adapter.setState(`scriptProblem.${name.substring(SCRIPT_CODE_MARKER.length)}`, {
|
|
@@ -2573,7 +2656,7 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
2573
2656
|
if (sandbox.verbose) {
|
|
2574
2657
|
sandbox.log(`getEnums(enumName=${enumName}) => ${JSON.stringify(result)}`, 'info');
|
|
2575
2658
|
}
|
|
2576
|
-
return
|
|
2659
|
+
return structuredClone(result);
|
|
2577
2660
|
},
|
|
2578
2661
|
createAlias: function (name, alias, forceCreation, common, native, callback) {
|
|
2579
2662
|
if (typeof native === 'function') {
|
|
@@ -3242,7 +3325,14 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
3242
3325
|
return;
|
|
3243
3326
|
}
|
|
3244
3327
|
const instances = res.rows.map(item => item.id.substring('system.adapter.'.length));
|
|
3245
|
-
// Store in cache for subsequent calls (invalidated on system.adapter.* object change)
|
|
3328
|
+
// Store in cache for subsequent calls (invalidated on system.adapter.* object change).
|
|
3329
|
+
// LRU eviction: keep the map bounded to avoid unbounded memory growth.
|
|
3330
|
+
if (context.sendToInstanceCache.size >= 200) {
|
|
3331
|
+
const firstKey = context.sendToInstanceCache.keys().next().value;
|
|
3332
|
+
if (firstKey !== undefined) {
|
|
3333
|
+
context.sendToInstanceCache.delete(firstKey);
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3246
3336
|
context.sendToInstanceCache.set(_adapter, instances);
|
|
3247
3337
|
instances.forEach(instance => {
|
|
3248
3338
|
sandbox.verbose &&
|
|
@@ -3715,50 +3805,45 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
3715
3805
|
const day = 24 * hour;
|
|
3716
3806
|
const neg = diff < 0;
|
|
3717
3807
|
diff = Math.abs(diff);
|
|
3718
|
-
if (
|
|
3808
|
+
if (FTD_TEST_D.test(text)) {
|
|
3719
3809
|
const days = Math.floor(diff / day);
|
|
3720
|
-
text = text
|
|
3721
|
-
.replace(/(?<!\\)(DD|TT|ДД)/g, days.toString().padStart(2, '0'))
|
|
3722
|
-
.replace(/(?<!\\)(D|T|Д)/g, days.toString());
|
|
3810
|
+
text = text.replace(FTD_REPL_DD, days.toString().padStart(2, '0')).replace(FTD_REPL_D, days.toString());
|
|
3723
3811
|
if (sandbox.verbose) {
|
|
3724
3812
|
sandbox.log(`formatTimeDiff(format=${format}, text=${text}, days=${days})`, 'debug');
|
|
3725
3813
|
}
|
|
3726
3814
|
diff -= days * day;
|
|
3727
3815
|
}
|
|
3728
|
-
if (
|
|
3816
|
+
if (FTD_TEST_H.test(text)) {
|
|
3729
3817
|
const hours = Math.floor(diff / hour);
|
|
3730
3818
|
text = text
|
|
3731
|
-
.replace(
|
|
3732
|
-
.replace(
|
|
3819
|
+
.replace(FTD_REPL_HH, hours.toString().padStart(2, '0'))
|
|
3820
|
+
.replace(FTD_REPL_H, hours.toString());
|
|
3733
3821
|
if (sandbox.verbose) {
|
|
3734
3822
|
sandbox.log(`formatTimeDiff(format=${format}, text=${text}, hours=${hours})`, 'debug');
|
|
3735
3823
|
}
|
|
3736
3824
|
diff -= hours * hour;
|
|
3737
3825
|
}
|
|
3738
|
-
if (
|
|
3826
|
+
if (FTD_TEST_M.test(text)) {
|
|
3739
3827
|
const minutes = Math.floor(diff / minute);
|
|
3740
3828
|
text = text
|
|
3741
|
-
.replace(
|
|
3742
|
-
.replace(
|
|
3829
|
+
.replace(FTD_REPL_MM, minutes.toString().padStart(2, '0'))
|
|
3830
|
+
.replace(FTD_REPL_M, minutes.toString());
|
|
3743
3831
|
if (sandbox.verbose) {
|
|
3744
3832
|
sandbox.log(`formatTimeDiff(format=${format}, text=${text}, minutes=${minutes})`, 'debug');
|
|
3745
3833
|
}
|
|
3746
3834
|
diff -= minutes * minute;
|
|
3747
3835
|
}
|
|
3748
|
-
if (
|
|
3836
|
+
if (FTD_TEST_S.test(text)) {
|
|
3749
3837
|
const seconds = Math.floor(diff / second);
|
|
3750
3838
|
text = text
|
|
3751
|
-
.replace(
|
|
3752
|
-
.replace(
|
|
3839
|
+
.replace(FTD_REPL_SS, seconds.toString().padStart(2, '0'))
|
|
3840
|
+
.replace(FTD_REPL_S, seconds.toString());
|
|
3753
3841
|
sandbox.verbose &&
|
|
3754
3842
|
sandbox.log(`formatTimeDiff(format=${format}, text=${text}, seconds=${seconds})`, 'debug');
|
|
3755
|
-
// diff -= seconds * second; // no milliseconds
|
|
3756
3843
|
}
|
|
3757
|
-
|
|
3758
|
-
.replace(
|
|
3759
|
-
|
|
3760
|
-
.replace(/\\(m|м)/g, '$1')
|
|
3761
|
-
.replace(/\\(s|с)/g, '$1');
|
|
3844
|
+
for (const [pattern, replacement] of FTD_UNESCAPE) {
|
|
3845
|
+
text = text.replace(pattern, replacement);
|
|
3846
|
+
}
|
|
3762
3847
|
if (sandbox.verbose) {
|
|
3763
3848
|
sandbox.log(`formatTimeDiff(format=${format}, text=${text})`, 'debug');
|
|
3764
3849
|
}
|
|
@@ -4382,7 +4467,7 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
4382
4467
|
context.messageBusHandlers[sandbox.scriptName] = context.messageBusHandlers[sandbox.scriptName] || {};
|
|
4383
4468
|
context.messageBusHandlers[sandbox.scriptName][messageName] =
|
|
4384
4469
|
context.messageBusHandlers[sandbox.scriptName][messageName] || [];
|
|
4385
|
-
const handler = { id:
|
|
4470
|
+
const handler = { id: _handlerIdCounter++, cb: callback, sandbox };
|
|
4386
4471
|
context.messageBusHandlers[sandbox.scriptName][messageName].push(handler);
|
|
4387
4472
|
sandbox.__engine.__subscriptionsMessage += 1;
|
|
4388
4473
|
if (sandbox.__engine.__subscriptionsMessage %
|
|
@@ -4397,23 +4482,18 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
4397
4482
|
let found = false;
|
|
4398
4483
|
if (ctx) {
|
|
4399
4484
|
if (typeof idOrName === 'number') {
|
|
4400
|
-
for (const messageName
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
sandbox.__engine.__subscriptionsMessage--;
|
|
4408
|
-
}
|
|
4409
|
-
found = true;
|
|
4410
|
-
break;
|
|
4485
|
+
outer: for (const messageName of Object.keys(ctx)) {
|
|
4486
|
+
for (let i = 0; i < ctx[messageName].length; i++) {
|
|
4487
|
+
if (ctx[messageName][i].id === idOrName) {
|
|
4488
|
+
ctx[messageName].splice(i, 1);
|
|
4489
|
+
if (!ctx[messageName].length) {
|
|
4490
|
+
delete ctx[messageName];
|
|
4491
|
+
sandbox.__engine.__subscriptionsMessage--;
|
|
4411
4492
|
}
|
|
4493
|
+
found = true;
|
|
4494
|
+
break outer;
|
|
4412
4495
|
}
|
|
4413
4496
|
}
|
|
4414
|
-
if (found) {
|
|
4415
|
-
break;
|
|
4416
|
-
}
|
|
4417
4497
|
}
|
|
4418
4498
|
}
|
|
4419
4499
|
else if (idOrName && ctx[idOrName]) {
|
|
@@ -4662,11 +4742,33 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
4662
4742
|
if (sandbox.verbose) {
|
|
4663
4743
|
sandbox.log(`extendObject(id=${id}, obj=${JSON.stringify(obj)})`, 'info');
|
|
4664
4744
|
}
|
|
4745
|
+
let objClone;
|
|
4746
|
+
try {
|
|
4747
|
+
objClone = structuredClone(obj);
|
|
4748
|
+
}
|
|
4749
|
+
catch (err) {
|
|
4750
|
+
// e.g. DataCloneError when the object contains functions
|
|
4751
|
+
void adapter.setState(`scriptProblem.${name.substring(SCRIPT_CODE_MARKER.length)}`, {
|
|
4752
|
+
val: true,
|
|
4753
|
+
ack: true,
|
|
4754
|
+
c: 'extendObject',
|
|
4755
|
+
});
|
|
4756
|
+
sandbox.log(`Object "${id}" can't be copied: ${JSON.stringify(err)}`, 'error');
|
|
4757
|
+
if (typeof callback === 'function') {
|
|
4758
|
+
try {
|
|
4759
|
+
callback.call(sandbox, new Error(`Object "${id}" can't be copied`));
|
|
4760
|
+
}
|
|
4761
|
+
catch (err) {
|
|
4762
|
+
errorInCallback(err);
|
|
4763
|
+
}
|
|
4764
|
+
}
|
|
4765
|
+
return;
|
|
4766
|
+
}
|
|
4665
4767
|
if (callback) {
|
|
4666
|
-
adapter.extendForeignObject(id,
|
|
4768
|
+
adapter.extendForeignObject(id, objClone, callback);
|
|
4667
4769
|
}
|
|
4668
4770
|
else {
|
|
4669
|
-
void adapter.extendForeignObject(id,
|
|
4771
|
+
void adapter.extendForeignObject(id, objClone);
|
|
4670
4772
|
}
|
|
4671
4773
|
}
|
|
4672
4774
|
};
|
|
@@ -4722,6 +4824,11 @@ function sandBox(script, name, verbose, debug, context) {
|
|
|
4722
4824
|
writable: false,
|
|
4723
4825
|
});
|
|
4724
4826
|
}
|
|
4827
|
+
// Shallow-freeze the console object exposed to scripts to prevent its methods from being overwritten
|
|
4828
|
+
// Note: __engine must NOT be frozen because its counter properties are mutated at runtime
|
|
4829
|
+
if (sandbox.console && typeof sandbox.console === 'object') {
|
|
4830
|
+
Object.freeze(sandbox.console);
|
|
4831
|
+
}
|
|
4725
4832
|
return sandbox;
|
|
4726
4833
|
}
|
|
4727
4834
|
//# sourceMappingURL=sandbox.js.map
|