iobroker.javascript 9.2.1 → 9.2.3

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.
Files changed (84) hide show
  1. package/README.md +10 -16
  2. package/admin/assets/{AiChatPanel-Cc1KscBJ.js → AiChatPanel-C4zUsNmN.js} +15 -15
  3. package/admin/assets/{ScriptEditor-6qrtvwPL.js → ScriptEditor-C6W68ya0.js} +1 -1
  4. package/admin/assets/ScriptEditorVanillaMonaco-DYTcDqp_.js +3 -0
  5. package/admin/assets/cronHoverProvider-Bg0Vz-1E.js +2 -0
  6. package/admin/assets/index-45IwpC7_.js +1 -0
  7. package/admin/assets/{index-BZxCaQhO.js → index-BXfqctma.js} +1 -1
  8. package/admin/assets/{index-CYbVtccs.js → index-CUau9-il.js} +83 -83
  9. package/admin/assets/{index-DsW7vBcg.js → index-crBQrXKG.js} +1 -1
  10. package/admin/assets/{index-CexrwGGC.js → index-qoSy77Bg.js} +41 -37
  11. package/admin/assets/{localSharedImportMap-BCwqnmn4.js → localSharedImportMap-CVlAGiIu.js} +1 -1
  12. package/admin/assets/stateHoverProvider-BYBqzJuX.js +9 -0
  13. package/admin/assets/{virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-DNrEsMrg.js → virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-CeYV4czE.js} +2 -2
  14. package/admin/custom/assets/Components-jfkoGyES.js +1 -0
  15. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_emotion_mf_1_react__loadShare__.mjs-sg07E3QA.js +1 -0
  16. package/admin/custom/assets/ConfigCustomJavascriptSet__loadShare___mf_0_emotion_mf_1_styled__loadShare__.mjs-CwjI4A-J.js +1 -0
  17. package/admin/custom/assets/{ConfigCustomJavascriptSet__loadShare__react__loadShare__.mjs-0SjJESw9.js → ConfigCustomJavascriptSet__loadShare__react__loadShare__.mjs-BW9Qbxx5.js} +1 -1
  18. package/admin/custom/assets/{ConfigCustomJavascriptSet__loadShare__react__loadShare__.mjs_commonjs-proxy-CInLgMWW.js → ConfigCustomJavascriptSet__loadShare__react__loadShare__.mjs_commonjs-proxy-2W2BYT2K.js} +1 -1
  19. package/admin/custom/assets/{ConfigCustomJavascriptSet__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-CorOEig8.js → ConfigCustomJavascriptSet__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-D8zcZsJo.js} +1 -1
  20. package/admin/custom/assets/DefaultPropsProvider-CfKHPa-G.js +1 -0
  21. package/admin/custom/assets/{TextField-DNzklBSl.js → TextField-CxPfV5Sr.js} +12 -12
  22. package/admin/custom/assets/{ThemeProvider-B4G3jidj.js → ThemeProvider-DSTCckLJ.js} +4 -4
  23. package/admin/custom/assets/{createSvgIcon-ZdrQ8zSU.js → createSvgIcon-b2B2NI3g.js} +1 -1
  24. package/admin/custom/assets/createTheme-MsdB8zt7.js +8 -0
  25. package/admin/custom/assets/defaultTheme-CmVP-QNF.js +1 -0
  26. package/admin/custom/assets/emotion-cache.browser.esm-BgJfNZJN.js +1 -0
  27. package/admin/custom/assets/emotion-react.browser.esm-chZAeh_-.js +1 -0
  28. package/admin/custom/assets/emotion-serialize.esm-BUa21YfQ.js +1 -0
  29. package/admin/custom/assets/emotion-styled.browser.esm-Yi13plpH.js +1 -0
  30. package/admin/custom/assets/emotion-use-insertion-effect-with-fallbacks.browser.esm-CEPeBbh9.js +1 -0
  31. package/admin/custom/assets/extends-CF3RwP-h.js +1 -0
  32. package/admin/custom/assets/index-17vbGv00.js +1 -0
  33. package/admin/custom/assets/{index-iRHaQfi-.js → index-B5DqCD_a.js} +1 -1
  34. package/admin/custom/assets/{index-DNKzDki_.js → index-CS_GBN2m.js} +159 -159
  35. package/admin/custom/assets/{index-NItS-TWp.js → index-ChQotUCl.js} +1 -1
  36. package/admin/custom/assets/{index-YBvFYuP6.js → index-CzRngQHl.js} +1 -1
  37. package/admin/custom/assets/index-DLNtxshy.js +1 -0
  38. package/admin/custom/assets/{index-Dp7A3XHd.js → index-DV76KW3-.js} +4 -4
  39. package/admin/custom/assets/{index-D0iTiVVG.js → index-DlQbqHom.js} +1 -1
  40. package/admin/custom/assets/{index-BptSiKBK.js → index-FTmk0JJx.js} +5 -5
  41. package/admin/custom/assets/index-qs6J40Tp.js +964 -0
  42. package/admin/custom/assets/{jsx-runtime-DfVU3AZG.js → jsx-runtime-BplTyRFk.js} +1 -1
  43. package/admin/custom/assets/localSharedImportMap-BeObsVNc.js +1 -0
  44. package/admin/custom/assets/useTheme-BV4xOYIL.js +1 -0
  45. package/admin/custom/assets/useTheme-ldICnlmf.js +1 -0
  46. package/admin/custom/assets/{virtualExposes-jSvr-kK3.js → virtualExposes-wYe_Np-4.js} +1 -1
  47. package/admin/custom/assets/{virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-Br3IlnqO.js → virtual_mf-REMOTE_ENTRY_ID_ConfigCustomJavascriptSet__customComponents_js-BcRVut8U.js} +2 -2
  48. package/admin/custom/customComponents.js +1 -1
  49. package/admin/google-blockly/own/blocks_system.js +34 -0
  50. package/admin/google-blockly/own/blocks_words.js +4 -0
  51. package/admin/google-blockly/own/field_oid.js +151 -2
  52. package/admin/mf-manifest.json +1 -1
  53. package/admin/remoteEntry.js +1 -1
  54. package/admin/tab.html +10 -8
  55. package/build/lib/eventObj.js +21 -12
  56. package/build/lib/eventObj.js.map +1 -1
  57. package/build/lib/sandbox.js +168 -58
  58. package/build/lib/sandbox.js.map +1 -1
  59. package/build/lib/scheduler.js +18 -13
  60. package/build/lib/scheduler.js.map +1 -1
  61. package/build/main.js +224 -135
  62. package/build/main.js.map +1 -1
  63. package/build/types.d.ts +14 -6
  64. package/docs/de/README.md +2 -0
  65. package/docs/de/blockly.md +669 -8
  66. package/docs/en/blockly.md +33 -0
  67. package/io-package.json +27 -1
  68. package/package.json +1 -1
  69. package/admin/assets/ScriptEditorVanillaMonaco-bJua4sm1.js +0 -3
  70. package/admin/assets/index-SHs7_wDh.js +0 -1
  71. package/admin/assets/stateHoverProvider-CGChzV5W.js +0 -3
  72. package/admin/custom/assets/Components-B9ZyjeRI.js +0 -1
  73. package/admin/custom/assets/DefaultPropsProvider-CGb21NGY.js +0 -1
  74. package/admin/custom/assets/createTheme-Wd4QxQE0.js +0 -8
  75. package/admin/custom/assets/defaultTheme-F2iJF2G2.js +0 -1
  76. package/admin/custom/assets/index-AZB1OHDH.js +0 -1
  77. package/admin/custom/assets/index-C0RmLaAj.js +0 -1
  78. package/admin/custom/assets/index-sozs10Ij.js +0 -960
  79. package/admin/custom/assets/localSharedImportMap-BxT0VwTO.js +0 -1
  80. package/admin/custom/assets/useTheme-BfhDdtAr.js +0 -1
  81. package/admin/custom/assets/useTheme-DWZ6jNyq.js +0 -1
  82. /package/admin/custom/assets/{index-huvZQhZw.js → index-D_5kZmfw.js} +0 -0
  83. /package/admin/custom/assets/{index-CmJ8HzSc.js → index-DpJ18x6R.js} +0 -0
  84. /package/admin/custom/assets/{leaflet-src-k2rCV-Ix.js → leaflet-src-B472P7Y1.js} +0 -0
package/admin/tab.html CHANGED
@@ -115,9 +115,9 @@
115
115
  type="text/javascript"
116
116
  src="google-blockly/own/blocks_object.js"
117
117
  ></script>
118
- <script type="module" crossorigin src="./assets/index-CYbVtccs.js"></script>
118
+ <script type="module" crossorigin src="./assets/index-CUau9-il.js"></script>
119
119
  <link rel="modulepreload" crossorigin href="./assets/preload-helper-BDBacUwf.js">
120
- <link rel="modulepreload" crossorigin href="./assets/virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-DNrEsMrg.js">
120
+ <link rel="modulepreload" crossorigin href="./assets/virtual_mf-REMOTE_ENTRY_ID_iobroker_javascript__remoteEntry_js-CeYV4czE.js">
121
121
  <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare__react__loadShare__.mjs-CTZOFJS2.js">
122
122
  <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare__react__loadShare__.mjs_commonjs-proxy-CE9lvhW8.js">
123
123
  <link rel="modulepreload" crossorigin href="./assets/iobroker_javascript__loadShare__prop_mf_2_types__loadShare__.mjs-BCtSFofY.js">
@@ -134,18 +134,20 @@
134
134
  <noscript> You need to enable JavaScript to run this app. </noscript>
135
135
  <script>
136
136
  if (window.localStorage.getItem('App.theme') === 'dark' && !window.vendorPrefix) {
137
- window.document.body.style.background = 'black';
137
+ window.document.body.style.backgroundColor = 'black';
138
+ } else if (window.vendorPrefix === 'HA') {
139
+ window.document.body.style.backgroundColor = '#000000';
138
140
  }
139
141
 
140
142
  // support for older blockly extensions like blockly-plus
141
143
  if (window.Blockly) {
142
- window.Blockly.Constants = window.Blockly.Constants || {};
143
- window.Blockly.Constants.Loops = window.Blockly.Constants.Loops || {};
144
- window.Blockly.Constants.Variables = window.Blockly.Constants.Variables || {};
144
+ window.Blockly.Constants ||= {};
145
+ window.Blockly.Constants.Loops ||= {};
146
+ window.Blockly.Constants.Variables ||= {};
145
147
  window.Blockly.Constants.Variables.HUE = 'rgb(165, 91, 128)';
146
- window.Blockly.Constants.Logic = window.Blockly.Constants.Logic || {};
148
+ window.Blockly.Constants.Logic ||= {};
147
149
  window.Blockly.Constants.Logic.HUE = 'rgb(91, 128, 165)';
148
- window.Blockly.Constants.Math = window.Blockly.Constants.Logic || {};
150
+ window.Blockly.Constants.Math ||= {};
149
151
  window.Blockly.Constants.Math.HUE = 'rgb(91, 103, 165)';
150
152
  }
151
153
  </script>
@@ -11,27 +11,34 @@ function getObjectEnumsSync(context, idObj, enumIds, enumNames) {
11
11
  if (!enumNames) {
12
12
  enumNames = [];
13
13
  }
14
+ // Use Sets for O(1) deduplication instead of Array.includes() O(n)
15
+ const enumIdSet = new Set(enumIds);
16
+ const enumNameSet = new Set(enumNames);
14
17
  if (context.cacheObjectEnums[idObj]) {
15
18
  for (const enumId of context.cacheObjectEnums[idObj].enumIds) {
16
- if (!enumIds.includes(enumId)) {
19
+ if (!enumIdSet.has(enumId)) {
20
+ enumIdSet.add(enumId);
17
21
  enumIds.push(enumId);
18
22
  }
19
23
  }
20
24
  for (const enumName of context.cacheObjectEnums[idObj].enumNames) {
21
- if (!enumNames.includes(enumName)) {
25
+ if (!enumNameSet.has(enumName)) {
26
+ enumNameSet.add(enumName);
22
27
  enumNames.push(enumName);
23
28
  }
24
29
  }
25
- return { enumIds: enumIds, enumNames: enumNames };
30
+ return { enumIds, enumNames };
26
31
  }
27
- for (let i = 0, l = context.enums.length; i < l; i++) {
28
- if (context.objects[context.enums[i]]?.common?.members?.includes(idObj)) {
29
- if (!enumIds.includes(context.enums[i])) {
30
- enumIds.push(context.enums[i]);
32
+ for (const enumId of context.enums) {
33
+ if (context.objects[enumId]?.common?.members?.includes(idObj)) {
34
+ if (!enumIdSet.has(enumId)) {
35
+ enumIdSet.add(enumId);
36
+ enumIds.push(enumId);
31
37
  }
32
- const name = context.objects[context.enums[i]].common.name;
38
+ const name = context.objects[enumId].common.name;
33
39
  const str = typeof name === 'object' ? name[gContext.language || 'en'] : name;
34
- if (str && !enumNames.includes(str)) {
40
+ if (str && !enumNameSet.has(str)) {
41
+ enumNameSet.add(str);
35
42
  enumNames.push(str);
36
43
  }
37
44
  }
@@ -46,19 +53,21 @@ function getObjectEnumsSync(context, idObj, enumIds, enumNames) {
46
53
  //get parent enums but do not propagate our enums to parent.
47
54
  getObjectEnumsSync(context, parent, parentEnumIds, parentEnumNames);
48
55
  for (const enumId of parentEnumIds) {
49
- if (!enumIds.includes(enumId)) {
56
+ if (!enumIdSet.has(enumId)) {
57
+ enumIdSet.add(enumId);
50
58
  enumIds.push(enumId);
51
59
  }
52
60
  }
53
61
  for (const enumName of parentEnumNames) {
54
- if (!enumNames.includes(enumName)) {
62
+ if (!enumNameSet.has(enumName)) {
63
+ enumNameSet.add(enumName);
55
64
  enumNames.push(enumName);
56
65
  }
57
66
  }
58
67
  }
59
68
  }
60
69
  }
61
- context.cacheObjectEnums[idObj] = { enumIds: enumIds, enumNames: enumNames };
70
+ context.cacheObjectEnums[idObj] = { enumIds, enumNames };
62
71
  return context.cacheObjectEnums[idObj];
63
72
  }
64
73
  function doGetter(obj, name, ret) {
@@ -1 +1 @@
1
- {"version":3,"file":"eventObj.js","sourceRoot":"","sources":["../../src/lib/eventObj.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JavascriptContext } from '../types';\n\nlet gContext: JavascriptContext;\n\nexport function getObjectEnumsSync(\n context: JavascriptContext,\n idObj: string,\n enumIds?: string[],\n enumNames?: string[],\n): { enumIds: string[]; enumNames: string[] } {\n if (!enumIds) {\n enumIds = [];\n }\n if (!enumNames) {\n enumNames = [];\n }\n\n if (context.cacheObjectEnums[idObj]) {\n for (const enumId of context.cacheObjectEnums[idObj].enumIds) {\n if (!enumIds.includes(enumId)) {\n enumIds.push(enumId);\n }\n }\n for (const enumName of context.cacheObjectEnums[idObj].enumNames) {\n if (!enumNames.includes(enumName)) {\n enumNames.push(enumName);\n }\n }\n return { enumIds: enumIds, enumNames: enumNames };\n }\n\n for (let i = 0, l = context.enums.length; i < l; i++) {\n if (context.objects[context.enums[i]]?.common?.members?.includes(idObj)) {\n if (!enumIds.includes(context.enums[i])) {\n enumIds.push(context.enums[i]);\n }\n const name: ioBroker.StringOrTranslated = context.objects[context.enums[i]].common.name;\n const str: string | undefined = typeof name === 'object' ? name[gContext.language || 'en'] : name;\n if (str && !enumNames.includes(str)) {\n enumNames.push(str);\n }\n }\n }\n\n if (context.objects[idObj]) {\n const pos = idObj.lastIndexOf('.');\n if (pos !== -1) {\n const parent = idObj.substring(0, pos);\n if (parent && context.objects[parent]) {\n const parentEnumIds: string[] = [];\n const parentEnumNames: string[] = [];\n //get parent enums but do not propagate our enums to parent.\n getObjectEnumsSync(context, parent, parentEnumIds, parentEnumNames);\n for (const enumId of parentEnumIds) {\n if (!enumIds.includes(enumId)) {\n enumIds.push(enumId);\n }\n }\n for (const enumName of parentEnumNames) {\n if (!enumNames.includes(enumName)) {\n enumNames.push(enumName);\n }\n }\n }\n }\n }\n\n context.cacheObjectEnums[idObj] = { enumIds: enumIds, enumNames: enumNames };\n return context.cacheObjectEnums[idObj];\n}\n\nfunction doGetter(obj: Record<string, any>, name: string, ret: any): any {\n //adapter.log.debug('getter: ' + name + ' returns ' + ret);\n Object.defineProperty(obj, name, { value: ret });\n return ret;\n}\n\nexport class EventObj {\n public id: string;\n public state: ioBroker.State;\n public newState: ioBroker.State;\n public oldState: ioBroker.State;\n\n constructor(\n id: string,\n state: ioBroker.State | null | undefined,\n oldState?: ioBroker.State | null,\n context?: JavascriptContext,\n ) {\n if (context && !gContext) {\n gContext = context;\n }\n this.id = id;\n if (!state) {\n this.newState = { q: undefined, c: undefined, user: undefined } as ioBroker.State;\n } else {\n this.newState = {\n val: state.val,\n ts: state.ts,\n ack: state.ack,\n lc: state.lc,\n from: state.from,\n q: state.q,\n c: state.c,\n user: state.user,\n };\n }\n // if (oldState === undefined) oldState = {};\n if (!oldState) {\n this.oldState = {\n q: undefined,\n c: undefined,\n user: undefined,\n } as ioBroker.State;\n } else {\n this.oldState = {\n val: oldState.val,\n ts: oldState.ts,\n ack: oldState.ack,\n lc: oldState.lc,\n from: oldState.from,\n q: oldState.q,\n c: oldState.c,\n user: oldState.user,\n };\n }\n this.state = this.newState;\n }\n\n get common(): ioBroker.ObjectCommon {\n const ret = gContext.objects[this.id] ? gContext.objects[this.id].common : {};\n return doGetter(this, 'common', ret);\n }\n get native(): Record<string, any> {\n const ret = gContext.objects[this.id] ? gContext.objects[this.id].native : {};\n return doGetter(this, 'native', ret);\n }\n get name(): ioBroker.StringOrTranslated {\n const ret = this.common ? this.common.name : null;\n return doGetter(this, 'name', ret);\n }\n get channelId(): string | null {\n const ret = this.id.replace(/\\.*[^.]+$/, '');\n return doGetter(this, 'channelId', gContext.objects[ret] ? ret : null);\n }\n get channelName(): string | null {\n const channelId = this.channelId;\n const ret = channelId && gContext.objects[channelId].common ? gContext.objects[channelId].common.name : null;\n return doGetter(this, 'channelName', ret);\n }\n get deviceId(): string | null {\n let deviceId: string;\n const channelId = this.channelId;\n if (!channelId || !(deviceId = channelId.replace(/\\.*[^.]+$/, '')) || !gContext.objects[deviceId]) {\n Object.defineProperty(this, 'deviceName', { value: null });\n return doGetter(this, 'deviceId', null);\n }\n return doGetter(this, 'deviceId', deviceId);\n }\n get deviceName(): ioBroker.StringOrTranslated | null {\n const deviceId = this.deviceId;\n const ret = deviceId && gContext.objects[deviceId].common ? gContext.objects[deviceId].common.name : null;\n return doGetter(this, 'deviceName', ret);\n }\n get enumIds(): string[] | undefined {\n if (!gContext.isEnums) {\n return undefined;\n }\n const enumIds: string[] = [];\n const enumNames: string[] = [];\n getObjectEnumsSync(gContext, this.id, enumIds, enumNames);\n Object.defineProperty(this, 'enumNames', { value: enumNames });\n return doGetter(this, 'enumIds', enumIds);\n }\n get enumNames(): string[] | undefined {\n if (!gContext.isEnums) {\n return undefined;\n }\n const enumIds: string[] = [];\n const enumNames: string[] = [];\n getObjectEnumsSync(gContext, this.id, enumIds, enumNames);\n Object.defineProperty(this, 'enumIds', { value: enumIds });\n return doGetter(this, 'enumNames', enumNames);\n }\n}\n\nexport function createEventObject(\n context: JavascriptContext,\n id: string,\n state: ioBroker.State | null | undefined,\n oldState: ioBroker.State | null | undefined,\n): EventObj {\n gContext = gContext || context;\n\n return new EventObj(id, state, oldState, context);\n}\n"]}
1
+ {"version":3,"file":"eventObj.js","sourceRoot":"","sources":["../../src/lib/eventObj.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JavascriptContext } from '../types';\n\nlet gContext: JavascriptContext;\n\nexport function getObjectEnumsSync(\n context: JavascriptContext,\n idObj: string,\n enumIds?: string[],\n enumNames?: string[],\n): { enumIds: string[]; enumNames: string[] } {\n if (!enumIds) {\n enumIds = [];\n }\n if (!enumNames) {\n enumNames = [];\n }\n\n // Use Sets for O(1) deduplication instead of Array.includes() O(n)\n const enumIdSet = new Set(enumIds);\n const enumNameSet = new Set(enumNames);\n\n if (context.cacheObjectEnums[idObj]) {\n for (const enumId of context.cacheObjectEnums[idObj].enumIds) {\n if (!enumIdSet.has(enumId)) {\n enumIdSet.add(enumId);\n enumIds.push(enumId);\n }\n }\n for (const enumName of context.cacheObjectEnums[idObj].enumNames) {\n if (!enumNameSet.has(enumName)) {\n enumNameSet.add(enumName);\n enumNames.push(enumName);\n }\n }\n return { enumIds, enumNames };\n }\n\n for (const enumId of context.enums) {\n if (context.objects[enumId]?.common?.members?.includes(idObj)) {\n if (!enumIdSet.has(enumId)) {\n enumIdSet.add(enumId);\n enumIds.push(enumId);\n }\n const name: ioBroker.StringOrTranslated = context.objects[enumId].common.name;\n const str: string | undefined = typeof name === 'object' ? name[gContext.language || 'en'] : name;\n if (str && !enumNameSet.has(str)) {\n enumNameSet.add(str);\n enumNames.push(str);\n }\n }\n }\n\n if (context.objects[idObj]) {\n const pos = idObj.lastIndexOf('.');\n if (pos !== -1) {\n const parent = idObj.substring(0, pos);\n if (parent && context.objects[parent]) {\n const parentEnumIds: string[] = [];\n const parentEnumNames: string[] = [];\n //get parent enums but do not propagate our enums to parent.\n getObjectEnumsSync(context, parent, parentEnumIds, parentEnumNames);\n for (const enumId of parentEnumIds) {\n if (!enumIdSet.has(enumId)) {\n enumIdSet.add(enumId);\n enumIds.push(enumId);\n }\n }\n for (const enumName of parentEnumNames) {\n if (!enumNameSet.has(enumName)) {\n enumNameSet.add(enumName);\n enumNames.push(enumName);\n }\n }\n }\n }\n }\n\n context.cacheObjectEnums[idObj] = { enumIds, enumNames };\n return context.cacheObjectEnums[idObj];\n}\n\nfunction doGetter(obj: Record<string, any>, name: string, ret: any): any {\n //adapter.log.debug('getter: ' + name + ' returns ' + ret);\n Object.defineProperty(obj, name, { value: ret });\n return ret;\n}\n\nexport class EventObj {\n public id: string;\n public state: ioBroker.State;\n public newState: ioBroker.State;\n public oldState: ioBroker.State;\n\n constructor(\n id: string,\n state: ioBroker.State | null | undefined,\n oldState?: ioBroker.State | null,\n context?: JavascriptContext,\n ) {\n if (context && !gContext) {\n gContext = context;\n }\n this.id = id;\n if (!state) {\n this.newState = { q: undefined, c: undefined, user: undefined } as ioBroker.State;\n } else {\n this.newState = {\n val: state.val,\n ts: state.ts,\n ack: state.ack,\n lc: state.lc,\n from: state.from,\n q: state.q,\n c: state.c,\n user: state.user,\n };\n }\n // if (oldState === undefined) oldState = {};\n if (!oldState) {\n this.oldState = {\n q: undefined,\n c: undefined,\n user: undefined,\n } as ioBroker.State;\n } else {\n this.oldState = {\n val: oldState.val,\n ts: oldState.ts,\n ack: oldState.ack,\n lc: oldState.lc,\n from: oldState.from,\n q: oldState.q,\n c: oldState.c,\n user: oldState.user,\n };\n }\n this.state = this.newState;\n }\n\n get common(): ioBroker.ObjectCommon {\n const ret = gContext.objects[this.id] ? gContext.objects[this.id].common : {};\n return doGetter(this, 'common', ret);\n }\n get native(): Record<string, any> {\n const ret = gContext.objects[this.id] ? gContext.objects[this.id].native : {};\n return doGetter(this, 'native', ret);\n }\n get name(): ioBroker.StringOrTranslated {\n const ret = this.common ? this.common.name : null;\n return doGetter(this, 'name', ret);\n }\n get channelId(): string | null {\n const ret = this.id.replace(/\\.*[^.]+$/, '');\n return doGetter(this, 'channelId', gContext.objects[ret] ? ret : null);\n }\n get channelName(): string | null {\n const channelId = this.channelId;\n const ret = channelId && gContext.objects[channelId].common ? gContext.objects[channelId].common.name : null;\n return doGetter(this, 'channelName', ret);\n }\n get deviceId(): string | null {\n let deviceId: string;\n const channelId = this.channelId;\n if (!channelId || !(deviceId = channelId.replace(/\\.*[^.]+$/, '')) || !gContext.objects[deviceId]) {\n Object.defineProperty(this, 'deviceName', { value: null });\n return doGetter(this, 'deviceId', null);\n }\n return doGetter(this, 'deviceId', deviceId);\n }\n get deviceName(): ioBroker.StringOrTranslated | null {\n const deviceId = this.deviceId;\n const ret = deviceId && gContext.objects[deviceId].common ? gContext.objects[deviceId].common.name : null;\n return doGetter(this, 'deviceName', ret);\n }\n get enumIds(): string[] | undefined {\n if (!gContext.isEnums) {\n return undefined;\n }\n const enumIds: string[] = [];\n const enumNames: string[] = [];\n getObjectEnumsSync(gContext, this.id, enumIds, enumNames);\n Object.defineProperty(this, 'enumNames', { value: enumNames });\n return doGetter(this, 'enumIds', enumIds);\n }\n get enumNames(): string[] | undefined {\n if (!gContext.isEnums) {\n return undefined;\n }\n const enumIds: string[] = [];\n const enumNames: string[] = [];\n getObjectEnumsSync(gContext, this.id, enumIds, enumNames);\n Object.defineProperty(this, 'enumIds', { value: enumIds });\n return doGetter(this, 'enumNames', enumNames);\n }\n}\n\nexport function createEventObject(\n context: JavascriptContext,\n id: string,\n state: ioBroker.State | null | undefined,\n oldState: ioBroker.State | null | undefined,\n): EventObj {\n gContext = gContext || context;\n\n return new EventObj(id, state, oldState, context);\n}\n"]}
@@ -90,7 +90,8 @@ function sandBox(script, name, verbose, debug, context) {
90
90
  });
91
91
  }
92
92
  else {
93
- adapter.getForeignStates(pattern, (_err, _states) => _states && Object.keys(_states).forEach(id => (states[id] = _states[id])));
93
+ // IO-3: Object.assign instead of Object.keys().forEach() no temporary keys array
94
+ adapter.getForeignStates(pattern, (_err, _states) => _states && Object.assign(states, _states));
94
95
  }
95
96
  }
96
97
  else {
@@ -482,9 +483,21 @@ function sandBox(script, name, verbose, debug, context) {
482
483
  if (!adapter.config.subscribe && context.interimStateValues[id]) {
483
484
  // if the state is changed, we will compare it with interimStateValues
484
485
  const oldState = context.interimStateValues[id];
485
- const attrs = Object.keys(stateAsObject).filter(attr => attr !== 'ts' && stateAsObject[attr] !== undefined);
486
- if (!attrs.every(attr => stateAsObject[attr] ===
487
- oldState[attr])) {
486
+ // IO-1: for…in instead of Object.keys().filter().every() no temporary array per call
487
+ let stateHasChanged = false;
488
+ for (const attr in stateAsObject) {
489
+ if (attr === 'ts') {
490
+ continue;
491
+ }
492
+ if (stateAsObject[attr] === undefined) {
493
+ continue;
494
+ }
495
+ if (stateAsObject[attr] !== oldState[attr]) {
496
+ stateHasChanged = true;
497
+ break;
498
+ }
499
+ }
500
+ if (stateHasChanged) {
488
501
  // state is changed for sure, and we will call setForeignState
489
502
  // and store new state to interimStateValues
490
503
  context.interimStateValues[id] = stateAsObject;
@@ -735,10 +748,10 @@ function sandBox(script, name, verbose, debug, context) {
735
748
  const chn = parts.join('.');
736
749
  parts.pop();
737
750
  const dev = parts.join('.');
738
- context.devices[dev] = context.devices[dev] || [];
739
- context.devices[dev].push(_id);
740
- context.channels[chn] = context.channels[chn] || [];
741
- context.channels[chn].push(_id);
751
+ context.devices[dev] = context.devices[dev] || new Set();
752
+ context.devices[dev].add(_id);
753
+ context.channels[chn] = context.channels[chn] || new Set();
754
+ context.channels[chn].add(_id);
742
755
  }
743
756
  }
744
757
  }
@@ -851,7 +864,7 @@ function sandBox(script, name, verbose, debug, context) {
851
864
  }
852
865
  // retrieve the state ID collection for all remaining channels
853
866
  res = res
854
- .map(id => channels[id])
867
+ .map(id => [...(channels[id] || [])])
855
868
  // and flatten the array to get only the state IDs
856
869
  .reduce((acc, next) => acc.concat(next), []);
857
870
  // now filter out those that don't match every ID selector for the state ID
@@ -884,7 +897,7 @@ function sandBox(script, name, verbose, debug, context) {
884
897
  }
885
898
  // retrieve the state ID collection for all remaining devices
886
899
  res = res
887
- .map(id => devices[id])
900
+ .map(id => [...(devices[id] || [])])
888
901
  // and flatten the array to get only the state IDs
889
902
  .reduce((acc, next) => acc.concat(next), []);
890
903
  // now filter out those that don't match every ID selector for the state ID
@@ -921,12 +934,8 @@ function sandBox(script, name, verbose, debug, context) {
921
934
  res = res.filter(id => applyEnumSelectors(id));
922
935
  }
923
936
  }
924
- const resUnique = [];
925
- for (let i = 0; i < res.length; i++) {
926
- if (!resUnique.includes(res[i])) {
927
- resUnique.push(res[i]);
928
- }
929
- }
937
+ // IO-2: O(1) deduplication via Set instead of O(n²) resUnique.includes()
938
+ const resUnique = [...new Set(res)];
930
939
  for (let i = 0; i < resUnique.length; i++) {
931
940
  result[i] = resUnique[i];
932
941
  }
@@ -1355,8 +1364,8 @@ function sandBox(script, name, verbose, debug, context) {
1355
1364
  if (oPattern?.id && Array.isArray(oPattern.id)) {
1356
1365
  const result = [];
1357
1366
  for (let t = 0; t < oPattern.id.length; t++) {
1358
- const pa = JSON.parse(JSON.stringify(oPattern));
1359
- pa.id = oPattern.id[t];
1367
+ // IO-4: Spread instead of JSON.parse(JSON.stringify()) – no deep clone needed (only primitive fields)
1368
+ const pa = { ...oPattern, id: oPattern.id[t] };
1360
1369
  result.push(sandbox.subscribe(pa, callbackOrChangeTypeOrId, value));
1361
1370
  }
1362
1371
  return result;
@@ -1431,10 +1440,11 @@ function sandBox(script, name, verbose, debug, context) {
1431
1440
  const _adapter = `system.adapter.${a}`;
1432
1441
  if (objects[_adapter] && objects[_adapter].common && objects[_adapter].common.subscribable) {
1433
1442
  const alive = `system.adapter.${a}.alive`;
1434
- context.adapterSubs[alive] = context.adapterSubs[alive] || [];
1435
- const subExists = context.adapterSubs[alive].filter(sub => sub === oPattern.id).length > 0;
1443
+ context.adapterSubs[alive] = context.adapterSubs[alive] || new Set();
1444
+ // Set.has() is O(1) and automatically prevents duplicates
1445
+ const subExists = context.adapterSubs[alive].has(oPattern.id);
1436
1446
  if (!subExists) {
1437
- context.adapterSubs[alive].push(oPattern.id);
1447
+ context.adapterSubs[alive].add(oPattern.id);
1438
1448
  adapter.sendTo(a, 'subscribe', oPattern.id);
1439
1449
  }
1440
1450
  }
@@ -1491,8 +1501,8 @@ function sandBox(script, name, verbose, debug, context) {
1491
1501
  if (objects[_adapter]?.common?.subscribable) {
1492
1502
  const a = `${parts[0]}.${parts[1]}`;
1493
1503
  const alive = `system.adapter.${a}.alive`;
1494
- context.adapterSubs[alive] = context.adapterSubs[alive] || [];
1495
- context.adapterSubs[alive].push(id);
1504
+ context.adapterSubs[alive] = context.adapterSubs[alive] || new Set();
1505
+ context.adapterSubs[alive].add(id);
1496
1506
  if (sandbox.verbose) {
1497
1507
  sandbox.log(`adapterSubscribe: ${a} - ${id}`, 'info');
1498
1508
  }
@@ -1542,7 +1552,7 @@ function sandBox(script, name, verbose, debug, context) {
1542
1552
  return sandbox.subscribe(pattern, callbackOrChangeTypeOrId, value);
1543
1553
  },
1544
1554
  onEnumMembers: function (enumId, callback) {
1545
- if (enums.includes(enumId)) {
1555
+ if (enums.has(enumId)) {
1546
1556
  const subscriptions = {};
1547
1557
  const init = () => {
1548
1558
  const obj = objects[enumId];
@@ -1557,7 +1567,8 @@ function sandBox(script, name, verbose, debug, context) {
1557
1567
  }
1558
1568
  // Subscribe to all members of enum
1559
1569
  for (const objId of members) {
1560
- if (!Object.keys(subscriptions).includes(objId)) {
1570
+ // IO-6: `in` operator instead of Object.keys().includes() – O(1) instead of O(n)
1571
+ if (!(objId in subscriptions)) {
1561
1572
  if (objects?.[objId]?.type === 'state') {
1562
1573
  // Just subscribe to states
1563
1574
  subscriptions[objId] = sandbox.subscribe(objId, callback); // TODO: more features
@@ -2059,11 +2070,13 @@ function sandBox(script, name, verbose, debug, context) {
2059
2070
  const schedules = context.scheduler?.getList() || [];
2060
2071
  if (allScripts) {
2061
2072
  Object.keys(context.scripts).forEach(name => context.scripts[name].schedules &&
2062
- context.scripts[name].schedules.forEach(s => schedules.push(JSON.parse(JSON.stringify(s._ioBroker)))));
2073
+ // IO-8: Spread instead of JSON.parse(JSON.stringify()) – _ioBroker has only primitive fields
2074
+ context.scripts[name].schedules.forEach(s => schedules.push({ ...s._ioBroker })));
2063
2075
  }
2064
2076
  else {
2065
2077
  script.schedules &&
2066
- script.schedules.forEach(s => schedules.push(JSON.parse(JSON.stringify(s._ioBroker))));
2078
+ // IO-8: Spread instead of JSON.parse(JSON.stringify())
2079
+ script.schedules.forEach(s => schedules.push({ ...s._ioBroker }));
2067
2080
  }
2068
2081
  return schedules;
2069
2082
  },
@@ -2100,10 +2113,22 @@ function sandBox(script, name, verbose, debug, context) {
2100
2113
  if (timers[id]) {
2101
2114
  sandbox.verbose &&
2102
2115
  sandbox.log(`setStateDelayed: clear ${timers[id].length} running timers`, 'info');
2116
+ // collect affected scriptNames before deleting
2117
+ const affectedScripts = new Set(timers[id].map(e => e.scriptName));
2103
2118
  for (let i = 0; i < timers[id].length; i++) {
2104
2119
  clearTimeout(timers[id][i].t);
2105
2120
  }
2106
2121
  delete timers[id];
2122
+ // update timersByScript reverse-index for all affected scripts
2123
+ for (const scriptName of affectedScripts) {
2124
+ const scriptSet = context.timersByScript.get(scriptName);
2125
+ if (scriptSet) {
2126
+ scriptSet.delete(id);
2127
+ if (!scriptSet.size) {
2128
+ context.timersByScript.delete(scriptName);
2129
+ }
2130
+ }
2131
+ }
2107
2132
  }
2108
2133
  else {
2109
2134
  if (sandbox.verbose) {
@@ -2130,18 +2155,36 @@ function sandBox(script, name, verbose, debug, context) {
2130
2155
  if (timers[_id]) {
2131
2156
  // optimisation
2132
2157
  if (timers[_id].length === 1) {
2158
+ const scriptName = timers[_id][0].scriptName;
2133
2159
  delete timers[_id];
2160
+ // update timersByScript reverse-index
2161
+ const scriptSet = context.timersByScript.get(scriptName);
2162
+ if (scriptSet) {
2163
+ scriptSet.delete(_id);
2164
+ if (!scriptSet.size) {
2165
+ context.timersByScript.delete(scriptName);
2166
+ }
2167
+ }
2134
2168
  }
2135
2169
  else {
2136
2170
  for (let t = 0; t < timers[_id].length; t++) {
2137
2171
  if (timers[_id][t].id === _timerId) {
2172
+ const scriptName = timers[_id][t].scriptName;
2138
2173
  timers[_id].splice(t, 1);
2174
+ if (!timers[_id].length) {
2175
+ delete timers[_id];
2176
+ // update timersByScript reverse-index
2177
+ const scriptSet = context.timersByScript.get(scriptName);
2178
+ if (scriptSet) {
2179
+ scriptSet.delete(_id);
2180
+ if (!scriptSet.size) {
2181
+ context.timersByScript.delete(scriptName);
2182
+ }
2183
+ }
2184
+ }
2139
2185
  break;
2140
2186
  }
2141
2187
  }
2142
- if (!timers[_id].length) {
2143
- delete timers[_id];
2144
- }
2145
2188
  }
2146
2189
  }
2147
2190
  }, delay, context.timerId, id, state, isAck);
@@ -2161,6 +2204,11 @@ function sandBox(script, name, verbose, debug, context) {
2161
2204
  : isAck,
2162
2205
  scriptName: name,
2163
2206
  });
2207
+ // Keep reverse-index in sync for O(1) cleanup in stopScript
2208
+ if (!context.timersByScript.has(name)) {
2209
+ context.timersByScript.set(name, new Set());
2210
+ }
2211
+ context.timersByScript.get(name).add(id);
2164
2212
  return context.timerId;
2165
2213
  },
2166
2214
  clearStateDelayed: function (id, timerId) {
@@ -2172,14 +2220,18 @@ function sandBox(script, name, verbose, debug, context) {
2172
2220
  sandbox.log(`clearStateDelayed(id=${id}, timerId=${timerId})`, 'info');
2173
2221
  }
2174
2222
  if (timers[id]) {
2223
+ // collect scriptNames of entries that will be removed
2224
+ const removedScripts = new Set();
2175
2225
  for (let i = timers[id].length - 1; i >= 0; i--) {
2176
2226
  if (timerId === undefined || timers[id][i].id === timerId) {
2227
+ const clearedTimerId = timers[id][i].id;
2228
+ removedScripts.add(timers[id][i].scriptName);
2177
2229
  clearTimeout(timers[id][i].t);
2178
2230
  if (timerId !== undefined) {
2179
2231
  timers[id].splice(i, 1);
2180
2232
  }
2181
2233
  if (sandbox.verbose) {
2182
- sandbox.log(`clearStateDelayed: clear timer ${timers[id][i].id}`, 'info');
2234
+ sandbox.log(`clearStateDelayed: clear timer ${clearedTimerId}`, 'info');
2183
2235
  }
2184
2236
  }
2185
2237
  }
@@ -2191,6 +2243,25 @@ function sandBox(script, name, verbose, debug, context) {
2191
2243
  delete timers[id];
2192
2244
  }
2193
2245
  }
2246
+ // IO-7: keep the timersByScript reverse-index in sync. For every script whose
2247
+ // timer(s) we just removed, drop `id` from its set – unless that script still has
2248
+ // another timer for this state (other scripts' timers may keep timers[id] alive).
2249
+ if (removedScripts.size) {
2250
+ const remaining = timers[id]; // undefined if the whole entry was deleted
2251
+ for (const scriptName of removedScripts) {
2252
+ const stateIds = context.timersByScript.get(scriptName);
2253
+ if (!stateIds) {
2254
+ continue;
2255
+ }
2256
+ if (remaining?.some(e => e.scriptName === scriptName)) {
2257
+ continue;
2258
+ }
2259
+ stateIds.delete(id);
2260
+ if (!stateIds.size) {
2261
+ context.timersByScript.delete(scriptName);
2262
+ }
2263
+ }
2264
+ }
2194
2265
  return true;
2195
2266
  }
2196
2267
  return false;
@@ -2489,11 +2560,11 @@ function sandBox(script, name, verbose, debug, context) {
2489
2560
  getEnums: function (enumName) {
2490
2561
  const result = [];
2491
2562
  const r = enumName ? new RegExp(`^enum\\.${enumName}\\.`) : false;
2492
- for (let i = 0; i < enums.length; i++) {
2493
- if (!r || r.test(enums[i])) {
2494
- const common = objects[enums[i]].common || {};
2563
+ for (const enumId of enums) {
2564
+ if (!r || r.test(enumId)) {
2565
+ const common = objects[enumId].common || {};
2495
2566
  result.push({
2496
- id: enums[i],
2567
+ id: enumId,
2497
2568
  members: common.members || [],
2498
2569
  name: common.name || '',
2499
2570
  });
@@ -3154,19 +3225,32 @@ function sandBox(script, name, verbose, debug, context) {
3154
3225
  adapter.sendTo(_adapter, cmd, msg, cbFunc, options);
3155
3226
  }
3156
3227
  else {
3157
- // Send it to all instances
3158
- context.adapter.getObjectView('system', 'instance', { startkey: `system.adapter.${_adapter}.`, endkey: `system.adapter.${_adapter}.\u9999` }, options, (err, res) => {
3159
- if (err || !res) {
3160
- sandbox.log(`sendTo failed: ${err?.message}`, 'error');
3161
- return;
3162
- }
3163
- const instances = res.rows.map(item => item.id.substring('system.adapter.'.length));
3164
- instances.forEach(instance => {
3228
+ // IO-9: Cache sendTo broadcast instance list – avoid repeated getObjectView DB calls
3229
+ const cached = context.sendToInstanceCache.get(_adapter);
3230
+ if (cached) {
3231
+ cached.forEach(instance => {
3165
3232
  sandbox.verbose &&
3166
- sandbox.log(`sendTo(instance=${instance}, cmd=${cmd}, msg=${JSON.stringify(msg)}, hasCallback=${typeof callback === 'function'})`, 'info');
3233
+ sandbox.log(`sendTo(instance=${instance}, cmd=${cmd}, msg=${JSON.stringify(msg)}, hasCallback=${typeof callback === 'function'}) [cached]`, 'info');
3167
3234
  adapter.sendTo(instance, cmd, msg, cbFunc, options);
3168
3235
  });
3169
- });
3236
+ }
3237
+ else {
3238
+ // Send it to all instances
3239
+ context.adapter.getObjectView('system', 'instance', { startkey: `system.adapter.${_adapter}.`, endkey: `system.adapter.${_adapter}.\u9999` }, options, (err, res) => {
3240
+ if (err || !res) {
3241
+ sandbox.log(`sendTo failed: ${err?.message}`, 'error');
3242
+ return;
3243
+ }
3244
+ 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)
3246
+ context.sendToInstanceCache.set(_adapter, instances);
3247
+ instances.forEach(instance => {
3248
+ sandbox.verbose &&
3249
+ sandbox.log(`sendTo(instance=${instance}, cmd=${cmd}, msg=${JSON.stringify(msg)}, hasCallback=${typeof callback === 'function'})`, 'info');
3250
+ adapter.sendTo(instance, cmd, msg, cbFunc, options);
3251
+ });
3252
+ });
3253
+ }
3170
3254
  }
3171
3255
  },
3172
3256
  sendto: function (_adapter, cmd, msg, callback) {
@@ -3230,7 +3314,8 @@ function sandBox(script, name, verbose, debug, context) {
3230
3314
  errorInCallback(err);
3231
3315
  }
3232
3316
  }, ms);
3233
- script.intervals.push(int);
3317
+ // IO-10: Set.add() – O(1) instead of Array.push()
3318
+ script.intervals.add(int);
3234
3319
  if (sandbox.verbose) {
3235
3320
  sandbox.log(`setInterval(ms=${ms})`, 'info');
3236
3321
  }
@@ -3240,13 +3325,13 @@ function sandBox(script, name, verbose, debug, context) {
3240
3325
  return null;
3241
3326
  },
3242
3327
  clearInterval: function (id) {
3243
- const pos = script.intervals.indexOf(id);
3244
- if (pos !== -1) {
3328
+ // IO-10: Set.has/delete – O(1) instead of Array.indexOf+splice O(n)
3329
+ if (script.intervals.has(id)) {
3245
3330
  if (sandbox.verbose) {
3246
3331
  sandbox.log('clearInterval() => cleared', 'info');
3247
3332
  }
3248
3333
  clearInterval(id);
3249
- script.intervals.splice(pos, 1);
3334
+ script.intervals.delete(id);
3250
3335
  }
3251
3336
  else {
3252
3337
  if (sandbox.verbose) {
@@ -3257,11 +3342,8 @@ function sandBox(script, name, verbose, debug, context) {
3257
3342
  setTimeout: function (callback, ms, ...args) {
3258
3343
  if (typeof callback === 'function') {
3259
3344
  const to = setTimeout(() => {
3260
- // Remove timeout from the list
3261
- const pos = script.timeouts.indexOf(to);
3262
- if (pos !== -1) {
3263
- script.timeouts.splice(pos, 1);
3264
- }
3345
+ // IO-10: Set.delete O(1) instead of Array.indexOf+splice O(n)
3346
+ script.timeouts.delete(to);
3265
3347
  try {
3266
3348
  callback.call(sandbox, ...args);
3267
3349
  }
@@ -3272,20 +3354,21 @@ function sandBox(script, name, verbose, debug, context) {
3272
3354
  if (sandbox.verbose) {
3273
3355
  sandbox.log(`setTimeout(ms=${ms})`, 'info');
3274
3356
  }
3275
- script.timeouts.push(to);
3357
+ // IO-10: Set.add – O(1) instead of Array.push
3358
+ script.timeouts.add(to);
3276
3359
  return to;
3277
3360
  }
3278
3361
  sandbox.log(`Invalid callback for setTimeout! - ${typeof callback}`, 'error');
3279
3362
  return null;
3280
3363
  },
3281
3364
  clearTimeout: function (id) {
3282
- const pos = script.timeouts.indexOf(id);
3283
- if (pos !== -1) {
3365
+ // IO-10: Set.has/delete – O(1) instead of Array.indexOf+splice O(n)
3366
+ if (script.timeouts.has(id)) {
3284
3367
  if (sandbox.verbose) {
3285
3368
  sandbox.log('clearTimeout() => cleared', 'info');
3286
3369
  }
3287
3370
  clearTimeout(id);
3288
- script.timeouts.splice(pos, 1);
3371
+ script.timeouts.delete(id);
3289
3372
  }
3290
3373
  else {
3291
3374
  if (sandbox.verbose) {
@@ -4401,6 +4484,11 @@ function sandBox(script, name, verbose, debug, context) {
4401
4484
  }
4402
4485
  adapter.subscribeForeignObjects(pattern);
4403
4486
  context.subscriptionsObject.push(subs);
4487
+ // Keep O(1) dispatch map in sync
4488
+ if (!context.subscriptionsObjectMap.has(pattern)) {
4489
+ context.subscriptionsObjectMap.set(pattern, []);
4490
+ }
4491
+ context.subscriptionsObjectMap.get(pattern).push(subs);
4404
4492
  return subs;
4405
4493
  },
4406
4494
  unsubscribeObject: function (subObject) {
@@ -4418,6 +4506,17 @@ function sandBox(script, name, verbose, debug, context) {
4418
4506
  if (context.subscriptionsObject[i] === subObject) {
4419
4507
  adapter.unsubscribeForeignObjects(subObject.pattern);
4420
4508
  context.subscriptionsObject.splice(i, 1);
4509
+ // Keep O(1) dispatch map in sync
4510
+ const mapSubs = context.subscriptionsObjectMap.get(subObject.pattern);
4511
+ if (mapSubs) {
4512
+ const pos = mapSubs.indexOf(subObject);
4513
+ if (pos !== -1) {
4514
+ mapSubs.splice(pos, 1);
4515
+ }
4516
+ if (!mapSubs.length) {
4517
+ context.subscriptionsObjectMap.delete(subObject.pattern);
4518
+ }
4519
+ }
4421
4520
  sandbox.__engine.__subscriptionsObject--;
4422
4521
  return true;
4423
4522
  }
@@ -4428,6 +4527,17 @@ function sandBox(script, name, verbose, debug, context) {
4428
4527
  context.subscriptionsObject[i].pattern === subObject.pattern) {
4429
4528
  deleted++;
4430
4529
  adapter.unsubscribeForeignObjects(subObject.pattern);
4530
+ // Keep O(1) dispatch map in sync
4531
+ const mapSubsP = context.subscriptionsObjectMap.get(subObject.pattern);
4532
+ if (mapSubsP) {
4533
+ const pos = mapSubsP.indexOf(context.subscriptionsObject[i]);
4534
+ if (pos !== -1) {
4535
+ mapSubsP.splice(pos, 1);
4536
+ }
4537
+ if (!mapSubsP.length) {
4538
+ context.subscriptionsObjectMap.delete(subObject.pattern);
4539
+ }
4540
+ }
4431
4541
  context.subscriptionsObject.splice(i, 1);
4432
4542
  sandbox.__engine.__subscriptionsObject--;
4433
4543
  }