From cb33849b4ddb10ed85efff8c79d777855dd386d2 Mon Sep 17 00:00:00 2001 From: Sameer Brink <122649269+LegoBrainBiker@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:24:48 -0700 Subject: [PATCH 1/9] Skyhight173/json: add cache to improve performance --- extensions/Skyhigh173/json.js | 115 +++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 51 deletions(-) diff --git a/extensions/Skyhigh173/json.js b/extensions/Skyhigh173/json.js index 8901233a82..b91dc8b00b 100644 --- a/extensions/Skyhigh173/json.js +++ b/extensions/Skyhigh173/json.js @@ -13,6 +13,19 @@ */ const vm = Scratch.vm; + const objectCache = {} + function parse(string) { + return objectCache[string] ?? JSON.parse(string); + } + function stringify(object) { + const string = JSON.stringify(object); + objectCache[string] = object; + setTimeout(() => { + delete objectCache[string]; + }, 100); // store it in the cache for 100 ms + return string; + } + const hasOwn = (obj, property) => Object.prototype.hasOwnProperty.call(obj, property); @@ -661,7 +674,7 @@ return false; } else { try { - JSON.parse(json); + parse(json); return true; } catch { return false; @@ -680,7 +693,7 @@ return json; } else { try { - return JSON.parse(json) ?? ""; + return parse(json) ?? ""; } catch { return json; } @@ -690,7 +703,7 @@ json_is({ json, types }) { if (!this.json_is_valid({ json: json })) return false; try { - json = JSON.parse(json); + json = parse(json); switch (types) { case "Object": return !Array.isArray(json); @@ -706,7 +719,7 @@ json_length({ json }) { try { - json = JSON.parse(json); + json = parse(json); return Object.keys(json).length; } catch { return " "; @@ -728,7 +741,7 @@ try { return ( this._fixInvalidJSONValues(this.json_valid_return(key)) in - JSON.parse(json) + parse(json) ); } catch { return false; @@ -737,7 +750,7 @@ json_has_value({ json, value }) { try { - json = JSON.parse(json); + json = parse(json); value = this.json_valid_return(value); return json.includes(value); } catch { @@ -747,8 +760,8 @@ json_equal({ json1, equal, json2 }) { try { - json1 = JSON.parse(json1); - json2 = JSON.parse(json2); + json1 = parse(json1); + json2 = parse(json2); const keys1 = Object.keys(json1); const keys2 = Object.keys(json2); @@ -765,16 +778,16 @@ json_get_all({ Stype, json }) { try { - json = JSON.parse(json); + json = parse(json); switch (Stype) { case "keys": - return JSON.stringify(Object.keys(json).map((key) => key ?? "")); + return stringify(Object.keys(json).map((key) => key ?? "")); case "values": - return JSON.stringify( + return stringify( Object.keys(json).map((key) => json[key] ?? "") ); case "datas": - return JSON.stringify( + return stringify( Object.keys(json).map((key) => [key, json[key] ?? ""]) ); default: @@ -787,11 +800,11 @@ json_get({ item, json }) { try { - json = JSON.parse(json); + json = parse(json); if (hasOwn(json, item)) { const result = json[item] ?? ""; if (typeof result === "object") { - return JSON.stringify(result); + return stringify(result); } else { return result; } @@ -813,11 +826,11 @@ json_set({ item, value, json }) { try { - json = JSON.parse(json); + json = parse(json); value = this.json_valid_return(value); value = this._fixInvalidJSONValues(value); json[item] = value; - return JSON.stringify(json); + return stringify(json); } catch { return ""; } @@ -825,9 +838,9 @@ json_delete({ item, json }) { try { - json = JSON.parse(json); + json = parse(json); delete json[item]; - return JSON.stringify(json); + return stringify(json); } catch { return ""; } @@ -846,7 +859,7 @@ if (item > 0) { item--; } - json = JSON.parse(json); + json = parse(json); let result; if (item >= 0) { result = json[item]; @@ -856,7 +869,7 @@ } result = result ?? ""; if (typeof result == "object") { - return JSON.stringify(result); + return stringify(result); } else { return result; } @@ -867,9 +880,9 @@ json_array_itemH({ item, json }) { try { - json = JSON.parse(json); + json = parse(json); item = this._fixInvalidJSONValues(this.json_valid_return(item)); - let result = JSON.stringify(json.indexOf(item) + 1); + let result = stringify(json.indexOf(item) + 1); return result; } catch { return ""; @@ -878,7 +891,7 @@ json_array_from({ json }) { try { - return JSON.stringify(Array.from(String(json))); + return stringify(Array.from(String(json))); } catch { return ""; } @@ -886,9 +899,9 @@ json_array_concat({ json, json2 }) { try { - json = JSON.parse(json); - json2 = JSON.parse(json2); - return JSON.stringify(json.concat(json2)); + json = parse(json); + json2 = parse(json2); + return stringify(json.concat(json2)); } catch { return ""; } @@ -896,10 +909,10 @@ json_array_push({ item, json }) { try { - json = JSON.parse(json); + json = parse(json); item = this._fixInvalidJSONValues(this.json_valid_return(item)); json.push(item); - return JSON.stringify(json); + return stringify(json); } catch { return ""; } @@ -907,10 +920,10 @@ json_array_insert({ item, pos, json }) { try { - json = JSON.parse(json); + json = parse(json); item = this._fixInvalidJSONValues(this.json_valid_return(item)); json.splice(pos - 1, 0, item); - return JSON.stringify(json); + return stringify(json); } catch { return ""; } @@ -918,11 +931,11 @@ json_array_set({ item, pos, json }) { try { - json = JSON.parse(json); + json = parse(json); json[pos - 1] = this._fixInvalidJSONValues( this.json_valid_return(item) ); - return JSON.stringify(json); + return stringify(json); } catch { return ""; } @@ -930,9 +943,9 @@ json_array_delete({ item, json }) { try { - json = JSON.parse(json); + json = parse(json); json.splice(item - 1, 1); - return JSON.stringify(json); + return stringify(json); } catch { return ""; } @@ -940,7 +953,7 @@ json_array_remove_all({ item, json }) { try { - json = JSON.parse(json); + json = parse(json); item = this._fixInvalidJSONValues(this.json_valid_return(item)); let i = 0; while (i < json.length) { @@ -950,7 +963,7 @@ ++i; } } - return JSON.stringify(json); + return stringify(json); } catch { return ""; } @@ -958,7 +971,7 @@ json_array_fromto({ json, item, item2 }) { try { - return JSON.stringify(JSON.parse(json).slice(item - 1, item2)); + return stringify(parse(json).slice(item - 1, item2)); } catch { return ""; } @@ -966,7 +979,7 @@ json_array_reverse({ json }) { try { - return JSON.stringify(JSON.parse(json).reverse()); + return stringify(parse(json).reverse()); } catch { return ""; } @@ -974,19 +987,19 @@ json_array_flat({ json, depth }) { try { - return JSON.stringify(JSON.parse(json).flat(depth)); + return stringify(parse(json).flat(depth)); } catch { return ""; } } json_array_create({ text, d }) { - return JSON.stringify(String(text).split(d)); + return stringify(String(text).split(d)); } json_array_join({ json, d }) { try { - return JSON.parse(json).join(d); + return parse(json).join(d); } catch { return ""; } @@ -994,8 +1007,8 @@ json_array_filter({ key, json }) { try { - json = JSON.parse(json); - return JSON.stringify( + json = parse(json); + return stringify( json.map((x) => { if (hasOwn(x, key)) { return x[key]; @@ -1010,9 +1023,9 @@ json_array_setlen({ json, len }) { try { - json = JSON.parse(json); + json = parse(json); json.length = len; - return JSON.stringify(json); + return stringify(json); } catch { return ""; } @@ -1022,7 +1035,7 @@ try { let listVariable = this.lookupList(list, util); if (listVariable) { - return JSON.stringify(listVariable.value); + return stringify(listVariable.value); } } catch (e) { // ignore @@ -1033,10 +1046,10 @@ try { let listVariable = this.lookupList(list, util); if (listVariable) { - const array = JSON.parse(json); + const array = parse(json); if (Array.isArray(array)) { const safeArray = array.map((i) => { - if (typeof i === "object") return JSON.stringify(i); + if (typeof i === "object") return stringify(i); return i ?? ""; }); listVariable.value = safeArray; @@ -1051,7 +1064,7 @@ json_array_sort(args) { let list; try { - list = JSON.parse(args.list); + list = parse(args.list); } catch { return ""; } @@ -1060,12 +1073,12 @@ } list.sort(Scratch.Cast.compare); if (args.order === "descending") list.reverse(); - return JSON.stringify(list); + return stringify(list); } json_array_analysis(args) { let list; try { - list = JSON.parse(args.list); + list = parse(args.list); } catch { return 0; } From 5093b213d9db460fb04009de1aabfc11bfb272c5 Mon Sep 17 00:00:00 2001 From: "DangoCat[bot]" Date: Thu, 9 Apr 2026 17:05:46 +0000 Subject: [PATCH 2/9] [Automated] Format code --- extensions/Skyhigh173/json.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/extensions/Skyhigh173/json.js b/extensions/Skyhigh173/json.js index b91dc8b00b..28bbf5fe1c 100644 --- a/extensions/Skyhigh173/json.js +++ b/extensions/Skyhigh173/json.js @@ -13,7 +13,7 @@ */ const vm = Scratch.vm; - const objectCache = {} + const objectCache = {}; function parse(string) { return objectCache[string] ?? JSON.parse(string); } @@ -25,7 +25,7 @@ }, 100); // store it in the cache for 100 ms return string; } - + const hasOwn = (obj, property) => Object.prototype.hasOwnProperty.call(obj, property); @@ -740,8 +740,7 @@ json_has_key({ json, key }) { try { return ( - this._fixInvalidJSONValues(this.json_valid_return(key)) in - parse(json) + this._fixInvalidJSONValues(this.json_valid_return(key)) in parse(json) ); } catch { return false; @@ -783,9 +782,7 @@ case "keys": return stringify(Object.keys(json).map((key) => key ?? "")); case "values": - return stringify( - Object.keys(json).map((key) => json[key] ?? "") - ); + return stringify(Object.keys(json).map((key) => json[key] ?? "")); case "datas": return stringify( Object.keys(json).map((key) => [key, json[key] ?? ""]) From 1ec5492ed0bf6d4f1e787fe5d8960b5ff89d882e Mon Sep 17 00:00:00 2001 From: Sameer Brink <122649269+LegoBrainBiker@users.noreply.github.com> Date: Thu, 9 Apr 2026 19:25:27 -0700 Subject: [PATCH 3/9] Skyhight173/json: also cache on parse --- extensions/Skyhigh173/json.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/Skyhigh173/json.js b/extensions/Skyhigh173/json.js index 28bbf5fe1c..ae3718c7dd 100644 --- a/extensions/Skyhigh173/json.js +++ b/extensions/Skyhigh173/json.js @@ -15,7 +15,9 @@ const vm = Scratch.vm; const objectCache = {}; function parse(string) { - return objectCache[string] ?? JSON.parse(string); + return objectCache[string] ?? (setTimeout(() => { + delete objectCache[string]; + }, 100), objectCache[string] = JSON.parse(string)); } function stringify(object) { const string = JSON.stringify(object); From 26ce23032c5b8c13f90e36b7b8afeff329b018c0 Mon Sep 17 00:00:00 2001 From: "DangoCat[bot]" Date: Fri, 10 Apr 2026 02:26:54 +0000 Subject: [PATCH 4/9] [Automated] Format code --- extensions/Skyhigh173/json.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/extensions/Skyhigh173/json.js b/extensions/Skyhigh173/json.js index ae3718c7dd..6c505be4f9 100644 --- a/extensions/Skyhigh173/json.js +++ b/extensions/Skyhigh173/json.js @@ -15,9 +15,13 @@ const vm = Scratch.vm; const objectCache = {}; function parse(string) { - return objectCache[string] ?? (setTimeout(() => { - delete objectCache[string]; - }, 100), objectCache[string] = JSON.parse(string)); + return ( + objectCache[string] ?? + (setTimeout(() => { + delete objectCache[string]; + }, 100), + (objectCache[string] = JSON.parse(string))) + ); } function stringify(object) { const string = JSON.stringify(object); From 6959b15a4db989a059351a02a62a6c5d13240bb3 Mon Sep 17 00:00:00 2001 From: Sameer Brink <122649269+LegoBrainBiker@users.noreply.github.com> Date: Thu, 9 Apr 2026 20:04:49 -0700 Subject: [PATCH 5/9] Skyhight173/json: clear cache on an interval --- extensions/Skyhigh173/json.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/extensions/Skyhigh173/json.js b/extensions/Skyhigh173/json.js index 6c505be4f9..91819b7d0d 100644 --- a/extensions/Skyhigh173/json.js +++ b/extensions/Skyhigh173/json.js @@ -13,22 +13,18 @@ */ const vm = Scratch.vm; - const objectCache = {}; + let objectCache = {}; + setInterval(100, () => { // clear the cache every 0.1 second + objectCache = {}; + }); function parse(string) { return ( - objectCache[string] ?? - (setTimeout(() => { - delete objectCache[string]; - }, 100), - (objectCache[string] = JSON.parse(string))) + objectCache[string] ?? (objectCache[string] = JSON.parse(string)) ); } function stringify(object) { const string = JSON.stringify(object); objectCache[string] = object; - setTimeout(() => { - delete objectCache[string]; - }, 100); // store it in the cache for 100 ms return string; } From 69c46bcf850f52be3fc87c034e3c0a2a1a079c02 Mon Sep 17 00:00:00 2001 From: "DangoCat[bot]" Date: Fri, 10 Apr 2026 03:05:34 +0000 Subject: [PATCH 6/9] [Automated] Format code --- extensions/Skyhigh173/json.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extensions/Skyhigh173/json.js b/extensions/Skyhigh173/json.js index 91819b7d0d..751d9c5dca 100644 --- a/extensions/Skyhigh173/json.js +++ b/extensions/Skyhigh173/json.js @@ -14,13 +14,12 @@ const vm = Scratch.vm; let objectCache = {}; - setInterval(100, () => { // clear the cache every 0.1 second + setInterval(100, () => { + // clear the cache every 0.1 second objectCache = {}; }); function parse(string) { - return ( - objectCache[string] ?? (objectCache[string] = JSON.parse(string)) - ); + return objectCache[string] ?? (objectCache[string] = JSON.parse(string)); } function stringify(object) { const string = JSON.stringify(object); From 6dfaca116feb55046dd6619df24ce5215ba0e91d Mon Sep 17 00:00:00 2001 From: Sameer Brink <122649269+LegoBrainBiker@users.noreply.github.com> Date: Thu, 9 Apr 2026 20:08:21 -0700 Subject: [PATCH 7/9] Skyhight173/json: put the parameters in the right order Fix setInterval usage to correctly clear the cache. --- extensions/Skyhigh173/json.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extensions/Skyhigh173/json.js b/extensions/Skyhigh173/json.js index 751d9c5dca..754d680ec5 100644 --- a/extensions/Skyhigh173/json.js +++ b/extensions/Skyhigh173/json.js @@ -14,10 +14,9 @@ const vm = Scratch.vm; let objectCache = {}; - setInterval(100, () => { - // clear the cache every 0.1 second + setInterval(() => { objectCache = {}; - }); + }, 100); // clear the cache every 0.1 second function parse(string) { return objectCache[string] ?? (objectCache[string] = JSON.parse(string)); } From 40b0ce53c1ab08d04b8abb0443b54d5bfe887858 Mon Sep 17 00:00:00 2001 From: Sameer Brink <122649269+LegoBrainBiker@users.noreply.github.com> Date: Sat, 16 May 2026 10:30:58 -0700 Subject: [PATCH 8/9] Skyhigh173/JSON: make copies of objects/arrays before editing them --- extensions/Skyhigh173/json.js | 41 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/extensions/Skyhigh173/json.js b/extensions/Skyhigh173/json.js index 754d680ec5..2d34227512 100644 --- a/extensions/Skyhigh173/json.js +++ b/extensions/Skyhigh173/json.js @@ -766,7 +766,7 @@ const keys2 = Object.keys(json2); const result = keys1.length === keys2.length && - Object.keys(json1).every((key) => json1[key] === json2[key]); + keys1.every((key) => json1[key] === json2[key]); if (equal === "=") return result; if (equal === "≠") return !result; } catch { @@ -826,7 +826,10 @@ json = parse(json); value = this.json_valid_return(value); value = this._fixInvalidJSONValues(value); - json[item] = value; + json = { + ...json, + [item]: value, + }; return stringify(json); } catch { return ""; @@ -835,7 +838,7 @@ json_delete({ item, json }) { try { - json = parse(json); + json = { ...parse(json) }; delete json[item]; return stringify(json); } catch { @@ -908,8 +911,7 @@ try { json = parse(json); item = this._fixInvalidJSONValues(this.json_valid_return(item)); - json.push(item); - return stringify(json); + return stringify(json.concat(item)); } catch { return ""; } @@ -919,7 +921,7 @@ try { json = parse(json); item = this._fixInvalidJSONValues(this.json_valid_return(item)); - json.splice(pos - 1, 0, item); + json = json.toSpliced(pos - 1, 0, item); return stringify(json); } catch { return ""; @@ -929,8 +931,12 @@ json_array_set({ item, pos, json }) { try { json = parse(json); - json[pos - 1] = this._fixInvalidJSONValues( - this.json_valid_return(item) + json = json.toSpliced( + pos - 1, + 1, + this._fixInvalidJSONValues( + this.json_valid_return(item) + ) ); return stringify(json); } catch { @@ -941,7 +947,7 @@ json_array_delete({ item, json }) { try { json = parse(json); - json.splice(item - 1, 1); + json = json.toSpliced(item - 1, 1); return stringify(json); } catch { return ""; @@ -952,15 +958,7 @@ try { json = parse(json); item = this._fixInvalidJSONValues(this.json_valid_return(item)); - let i = 0; - while (i < json.length) { - if (json[i] === item) { - json.splice(i, 1); - } else { - ++i; - } - } - return stringify(json); + return stringify(json.filter((v) => (v !==item))); } catch { return ""; } @@ -1020,7 +1018,7 @@ json_array_setlen({ json, len }) { try { - json = parse(json); + json = [...parse(json)]; json.length = len; return stringify(json); } catch { @@ -1068,8 +1066,9 @@ if (!Array.isArray(list)) { return ""; } - list.sort(Scratch.Cast.compare); - if (args.order === "descending") list.reverse(); + list = list.toSorted((value1, value2) => ( + Scratch.Cast.compare(value1,value2) * ((args.order === "ascending") ? 1 : -1) + )); return stringify(list); } json_array_analysis(args) { From 173c75f37406a040b4d1b8c97652030ae706417b Mon Sep 17 00:00:00 2001 From: "DangoCat[bot]" Date: Sat, 16 May 2026 17:32:22 +0000 Subject: [PATCH 9/9] [Automated] Format code --- extensions/Skyhigh173/json.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extensions/Skyhigh173/json.js b/extensions/Skyhigh173/json.js index 2d34227512..89dac19fa3 100644 --- a/extensions/Skyhigh173/json.js +++ b/extensions/Skyhigh173/json.js @@ -934,9 +934,7 @@ json = json.toSpliced( pos - 1, 1, - this._fixInvalidJSONValues( - this.json_valid_return(item) - ) + this._fixInvalidJSONValues(this.json_valid_return(item)) ); return stringify(json); } catch { @@ -958,7 +956,7 @@ try { json = parse(json); item = this._fixInvalidJSONValues(this.json_valid_return(item)); - return stringify(json.filter((v) => (v !==item))); + return stringify(json.filter((v) => v !== item)); } catch { return ""; } @@ -1066,9 +1064,11 @@ if (!Array.isArray(list)) { return ""; } - list = list.toSorted((value1, value2) => ( - Scratch.Cast.compare(value1,value2) * ((args.order === "ascending") ? 1 : -1) - )); + list = list.toSorted( + (value1, value2) => + Scratch.Cast.compare(value1, value2) * + (args.order === "ascending" ? 1 : -1) + ); return stringify(list); } json_array_analysis(args) {