From 4ed8aff682f92c0315165d9b475e5d72731b28f5 Mon Sep 17 00:00:00 2001 From: Iban Eguia Moraza <razican@protonmail.ch> Date: Sat, 24 Feb 2024 21:09:27 +0100 Subject: [PATCH] Fixed latest.json result files for the new format (#3348) --- dev/bench/index.html | 29 ++- playground/index.html | 27 ++- test262/fix.py | 255 ++++++++++++++++++++++ test262/index.html | 33 +-- test262/refs/tags/v0.15/features.json | 1 - test262/refs/tags/v0.16/features.json | 1 - test262/refs/tags/v0.17.1/features.json | 1 - test262/refs/tags/v0.17.2/features.json | 1 - test262/refs/tags/v0.17.3/features.json | 1 - test262/refs/tags/v0.17/features.json | 1 - test262/results.js | 267 +++++++++++++----------- 11 files changed, 462 insertions(+), 155 deletions(-) create mode 100644 test262/fix.py delete mode 100644 test262/refs/tags/v0.15/features.json delete mode 100644 test262/refs/tags/v0.16/features.json delete mode 100644 test262/refs/tags/v0.17.1/features.json delete mode 100644 test262/refs/tags/v0.17.2/features.json delete mode 100644 test262/refs/tags/v0.17.3/features.json delete mode 100644 test262/refs/tags/v0.17/features.json diff --git a/dev/bench/index.html b/dev/bench/index.html index c5b54012ec5..07f86ad86d5 100644 --- a/dev/bench/index.html +++ b/dev/bench/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html> <head> <meta charset="UTF-8" /> @@ -8,9 +8,20 @@ /> <style> html { - font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", Roboto, - Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", - Helvetica, Arial, sans-serif; + font-family: + BlinkMacSystemFont, + -apple-system, + "Segoe UI", + Roboto, + Oxygen, + Ubuntu, + Cantarell, + "Fira Sans", + "Droid Sans", + "Helvetica Neue", + Helvetica, + Arial, + sans-serif; -webkit-font-smoothing: antialiased; font-size: 16px; } @@ -286,7 +297,7 @@ .sort( (a, b) => arr.filter((v) => v === a).length - - arr.filter((v) => v === b).length + arr.filter((v) => v === b).length, ) .pop(); } @@ -335,7 +346,7 @@ // Render header document.getElementById("last-update").textContent = new Date( - data.lastUpdate + data.lastUpdate, ).toString(); const repoLink = document.getElementById("repository-link"); repoLink.href = data.repoUrl; @@ -470,7 +481,7 @@ for (const [benchName, benches] of benchSet.entries()) { const benchUnit = unit.get(benchName); charts.push( - renderGraph(graphsElem, benchName, benchUnit, benches) + renderGraph(graphsElem, benchName, benchUnit, benches), ); } return charts; @@ -483,10 +494,10 @@ } const darkModeCheckbox = document.querySelector( - ".dark-mode-toggle input[type=checkbox]" + ".dark-mode-toggle input[type=checkbox]", ); const darkModeHandle = document.querySelector( - ".dark-mode-toggle .handle" + ".dark-mode-toggle .handle", ); darkModeCheckbox.addEventListener("change", async (e) => { document.body.classList.toggle("dark"); diff --git a/playground/index.html b/playground/index.html index 3a920535a25..4dc1577627a 100644 --- a/playground/index.html +++ b/playground/index.html @@ -1,4 +1,13 @@ -<!doctype html><html><head><meta charset="utf-8"/><title>Boa Playground</title><link href="assets/bootstrap.min.css" rel="stylesheet"/><meta name="viewport" content="width=device-width,initial-scale=1"/><script defer="defer" src="app.js"></script></head><style>header { +<!doctype html> +<html> + <head> + <meta charset="utf-8" /> + <title>Boa Playground</title> + <link href="assets/bootstrap.min.css" rel="stylesheet" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <script defer="defer" src="app.js"></script></head + ><style> + header { display: flex; align-items: center; } @@ -50,4 +59,18 @@ .output { min-height: 100px; } - }</style><body><div class="container"><header><img class="demo__img" src="./assets/logo.svg"/><h1>Boa Playground</h1></header><div class="demo__repl"><div class="textbox"></div><p data-testid="output" class="output"></p></div></div></body></html> \ No newline at end of file + } + </style> + <body> + <div class="container"> + <header> + <img class="demo__img" src="./assets/logo.svg" /> + <h1>Boa Playground</h1> + </header> + <div class="demo__repl"> + <div class="textbox"></div> + <p data-testid="output" class="output"></p> + </div> + </div> + </body> +</html> diff --git a/test262/fix.py b/test262/fix.py new file mode 100644 index 00000000000..9069b3af70a --- /dev/null +++ b/test262/fix.py @@ -0,0 +1,255 @@ +import json +import os + + +def suite_conformance(suite): + global function_suite + res = { + "t": 0, + "o": 0, + "i": 0, + "p": 0 + } + + if "s" in suite.keys(): + for subSuite in suite["s"].values(): + conformance = suite_conformance(subSuite) + res["t"] += conformance["t"] + res["o"] += conformance["o"] + res["i"] += conformance["i"] + res["p"] += conformance["p"] + + if "t" in suite.keys(): + for testName in suite["t"].keys(): + test = suite["t"][testName] + + res["t"] += 1 + if "s" in test.keys() and "r" in test.keys(): + if test["s"] == "O" and test["r"] == "O": + res["o"] += 1 + elif test["s"] == "I" and test["r"] == "I": + res["i"] += 1 + elif test["s"] == "P" or test["r"] == "P": + res["p"] += 1 + elif "s" in test.keys(): + if test["s"] == "O": + res["o"] += 1 + elif test["s"] == "I": + res["i"] += 1 + elif test["s"] == "P": + res["p"] += 1 + else: + if test["r"] == "O": + res["o"] += 1 + elif test["r"] == "I": + res["i"] += 1 + elif test["r"] == "P": + res["p"] += 1 + + return res + + +def version_conformance(suite): + res = {} + + if "s" in suite.keys(): + for subSuite in suite["s"].values(): + versions = version_conformance(subSuite) + for key in versions.keys(): + if key not in res.keys(): + res[key] = { + "t": 0, + "o": 0, + "i": 0, + "p": 0 + } + + res[key]["t"] += versions[key]["t"] + res[key]["o"] += versions[key]["o"] + res[key]["i"] += versions[key]["i"] + res[key]["p"] += versions[key]["p"] + + if "t" in suite.keys(): + for testName in suite["t"].keys(): + test = suite["t"][testName] + + if "v" in test.keys(): + version = test["v"] + if version != 255: + key = str(version) + if key not in res.keys(): + res[key] = { + "t": 0, + "o": 0, + "i": 0, + "p": 0 + } + + res[key]["t"] += 1 + if "s" in test.keys() and "r" in test.keys(): + if test["s"] == "O" and test["r"] == "O": + res[key]["o"] += 1 + elif test["s"] == "I" and test["r"] == "I": + res[key]["i"] += 1 + elif test["s"] == "P" or test["r"] == "P": + res[key]["p"] += 1 + elif "s" in test.keys(): + if test["s"] == "O": + res[key]["o"] += 1 + elif test["s"] == "I": + res[key]["i"] += 1 + elif test["s"] == "P": + res[key]["p"] += 1 + else: + if test["r"] == "O": + res[key]["o"] += 1 + elif test["r"] == "I": + res[key]["i"] += 1 + elif test["r"] == "P": + res[key]["p"] += 1 + + return res + + +def fix_tests(tests): + fixed = {} + + for test in tests: + name = test["n"] + if test["n"] in fixed: + if test["s"]: + fixed[name]["s"] = test["r"] + else: + fixed[name]["r"] = test["r"] + else: + fixed[name] = {} + + if "v" in test.keys(): + fixed[name]["v"] = test["v"] + + if "s" in test.keys(): + if test["s"]: + fixed[name]["s"] = test["r"] + else: + fixed[name]["r"] = test["r"] + else: + fixed[name]["r"] = test["r"] + + return fixed + + +def fix_suite(suites): + fixed = {} + for suite in suites: + name = suite["n"] + fixed[name] = {} + + if "s" in suite.keys(): + fixed[name]["s"] = fix_suite(suite["s"]) + + if "t" in suite.keys(): + fixed[name]["t"] = fix_tests(suite["t"]) + + fixed[name]["a"] = suite_conformance(fixed[name]) + fixed[name]["v"] = version_conformance(fixed[name]) + + return fixed + + +def fix_all(latest): + fixed = { + "c": latest["c"], + "u": latest["u"], + "r": fix_suite(latest["r"]["s"]), + "a": { + "t": 0, + "o": 0, + "i": 0, + "p": 0 + }, + "v": {}, + } + + for suite in fixed["r"].values(): + fixed["a"]["t"] += suite["a"]["t"] + fixed["a"]["o"] += suite["a"]["o"] + fixed["a"]["i"] += suite["a"]["i"] + fixed["a"]["p"] += suite["a"]["p"] + + for key in suite["v"].keys(): + if key not in fixed["v"].keys(): + fixed["v"][key] = { + "t": 0, + "o": 0, + "i": 0, + "p": 0 + } + + fixed["v"][key]["t"] += suite["v"][key]["t"] + fixed["v"][key]["o"] += suite["v"][key]["o"] + fixed["v"][key]["i"] += suite["v"][key]["i"] + fixed["v"][key]["p"] += suite["v"][key]["p"] + + return fixed + + +def fix_file(file_name): + with open(file_name) as latest_f: + latest = json.load(latest_f) + fixed_latest = fix_all(latest) + + with open(file_name, 'w') as latest_of: + json.dump(fixed_latest, latest_of, separators=( + ',', ':'), ensure_ascii=False) + + return fixed_latest + + +def clean_main(latest): + with open("./refs/heads/main/results.json") as results_f: + results = json.load(results_f) + fixed_results = [] + for result in results: + fixed_results.append({ + "c": result["c"], + "u": result["u"], + "a": result["a"], + }) + + fixed_results[-1] = { + "c": latest["c"], + "u": latest["u"], + "a": latest["a"], + } + + with open("./refs/heads/main/results.json", 'w') as results_of: + json.dump(fixed_results, results_of, separators=( + ',', ':'), ensure_ascii=False) + + +def clean_old(file_name, results): + fixed_results = [{ + "c": results["c"], + "u": results["u"], + "a": results["a"], + }] + + with open(file_name, 'w') as results_of: + json.dump(fixed_results, results_of, separators=( + ',', ':'), ensure_ascii=False) + + +for top, dirs, files in os.walk("./refs/tags"): + for dir in dirs: + print("Fixing " + dir) + results = fix_file("./refs/tags/" + dir + "/latest.json") + clean_old("./refs/tags/" + dir + "/results.json", results) + + if os.path.exists("./refs/tags/" + dir + "/features.json"): + os.remove("./refs/tags/" + dir + "/features.json") + +print("Fixing main branch") +results = fix_file("./refs/heads/main/latest.json") +clean_main(results) +if os.path.exists("./refs/heads/main/features.json"): + os.remove("./refs/heads/main/features.json") diff --git a/test262/index.html b/test262/index.html index e6009302610..d9079777aa2 100644 --- a/test262/index.html +++ b/test262/index.html @@ -1,4 +1,4 @@ -<!DOCTYPE html> +<!doctype html> <html lang="en"> <head> <title>Boa EcmaScript conformance</title> @@ -6,14 +6,14 @@ <link rel="icon" href="../assets/logo.svg" type="image/svg+xml" /> <link rel="stylesheet" - href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" - integrity="sha256-IUOUHAPazai08QFs7W4MbzTlwEWFo7z/4zw8YmxEiko=" + href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css" + integrity="sha256-MBffSnbbXwHCuZtgPYiwMQbfE7z+GOZ7fBPCNB06Z98=" crossorigin="anonymous" /> <link rel="stylesheet" - href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css" - integrity="sha256-8M+b2Hj+vy/2J5tZ9pYDHeuPD59KsaEZn1XXj3xVhjg=" + href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1/font/bootstrap-icons.min.css" + integrity="sha256-6MNujrdbV0Z7S927PzUMXOmMLwkKdsdD7XIl/w89HMQ=" crossorigin="anonymous" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> @@ -159,8 +159,17 @@ <h2 class="card-title">Older versions</h2> </select> </div> <div class="form-check form-switch mx-4"> - <input class="form-check-input" type="checkbox" role="switch" id="info-options-hide-passing-switch"> - <label class="form-check-label" for="info-options-hide-passing-switch">Hide passing</label> + <input + class="form-check-input" + type="checkbox" + role="switch" + id="info-options-hide-passing-switch" + /> + <label + class="form-check-label" + for="info-options-hide-passing-switch" + >Hide passing</label + > </div> </div> </form> @@ -194,15 +203,11 @@ <h5 class="modal-title" id="modalTitle">Main branch progress</h5> </div> </div> <script - src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js" - integrity="sha256-h1OMS35Ij1pJ0S+Y1qBK/GHQDyankPMZVpeZrNQ062U=" - crossorigin="anonymous" - ></script> - <script - src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js" - integrity="sha256-+8RZJua0aEWg+QVVKg4LEzEEm/8RFez5Tb4JBNiV5xA=" + src="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/js/bootstrap.min.js" + integrity="sha256-YMa+wAM6QkVyz999odX7lPRxkoYAan8suedu4k2Zur8=" crossorigin="anonymous" ></script> + <script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script> <script type="module" src="./results.js"></script> </body> </html> diff --git a/test262/refs/tags/v0.15/features.json b/test262/refs/tags/v0.15/features.json deleted file mode 100644 index 211d57f824c..00000000000 --- a/test262/refs/tags/v0.15/features.json +++ /dev/null @@ -1 +0,0 @@ -[{"c":"9e81103cdf73893abc8ec3894c0bcf3c51329b0c","u":"79e3bc5176b6f29a5aed3b7164a9c623a3a9a63b","n":"test","f":["AggregateError","Array.prototype.at","Array.prototype.flat","Array.prototype.flatMap","Array.prototype.values","ArrayBuffer","Atomics","Atomics.waitAsync","BigInt","DataView","DataView.prototype.getFloat32","DataView.prototype.getFloat64","DataView.prototype.getInt16","DataView.prototype.getInt32","DataView.prototype.getInt8","DataView.prototype.getUint16","DataView.prototype.getUint32","DataView.prototype.setUint8","FinalizationRegistry","FinalizationRegistry.prototype.cleanupSome","Float32Array","Float64Array","Int16Array","Int32Array","Int8Array","Intl-enumeration","Intl.DateTimeFormat-datetimestyle","Intl.DateTimeFormat-dayPeriod","Intl.DateTimeFormat-extend-timezonename","Intl.DateTimeFormat-formatRange","Intl.DateTimeFormat-fractionalSecondDigits","Intl.DisplayNames","Intl.DisplayNames-v2","Intl.DurationFormat","Intl.ListFormat","Intl.Locale","Intl.Locale-info","Intl.NumberFormat-unified","Intl.NumberFormat-v3","Intl.RelativeTimeFormat","Intl.Segmenter","IsHTMLDDA","Map","Object.fromEntries","Object.hasOwn","Object.is","Promise","Promise.allSettled","Promise.any","Promise.prototype.finally","Proxy","Reflect","Reflect.construct","Reflect.set","Reflect.setPrototypeOf","Set","ShadowRealm","SharedArrayBuffer","String.fromCodePoint","String.prototype.at","String.prototype.endsWith","String.prototype.includes","String.prototype.matchAll","String.prototype.replaceAll","String.prototype.trimEnd","String.prototype.trimStart","Symbol","Symbol.asyncIterator","Symbol.hasInstance","Symbol.isConcatSpreadable","Symbol.iterator","Symbol.match","Symbol.matchAll","Symbol.prototype.description","Symbol.replace","Symbol.search","Symbol.species","Symbol.split","Symbol.toPrimitive","Symbol.toStringTag","Symbol.unscopables","Temporal","TypedArray","TypedArray.prototype.at","Uint16Array","Uint32Array","Uint8Array","Uint8ClampedArray","WeakMap","WeakRef","WeakSet","__getter__","__proto__","__setter__","align-detached-buffer-semantics-with-web-reality","arbitrary-module-namespace-names","array-find-from-last","array-grouping","arrow-function","async-functions","async-iteration","caller","class","class-fields-private","class-fields-private-in","class-fields-public","class-methods-private","class-static-block","class-static-fields-private","class-static-fields-public","class-static-methods-private","coalesce-expression","computed-property-names","const","cross-realm","decorators","default-parameters","destructuring-assignment","destructuring-binding","dynamic-import","error-cause","export-star-as-namespace-from-module","for-in-order","for-of","generators","globalThis","hashbang","host-gc-required","import-assertions","import.meta","intl-normative-optional","json-modules","json-superset","legacy-regexp","let","logical-assignment-operators","new.target","numeric-separator-literal","object-rest","object-spread","optional-catch-binding","optional-chaining","proxy-missing-checks","regexp-dotall","regexp-lookbehind","regexp-match-indices","regexp-named-groups","regexp-unicode-property-escapes","regexp-v-flag","resizable-arraybuffer","rest-parameters","string-trimming","super","tail-call-optimization","template","top-level-await","u180e","well-formed-json-stringify"]}] \ No newline at end of file diff --git a/test262/refs/tags/v0.16/features.json b/test262/refs/tags/v0.16/features.json deleted file mode 100644 index cc43755499f..00000000000 --- a/test262/refs/tags/v0.16/features.json +++ /dev/null @@ -1 +0,0 @@ -[{"c":"888cc28e1a5368295b9ec9269069c99fc9f5656e","u":"9215420deee3e5887d29f95822bf6a474c1bf728","n":"test","f":["AggregateError","Array.prototype.at","Array.prototype.flat","Array.prototype.flatMap","Array.prototype.values","ArrayBuffer","Atomics","Atomics.waitAsync","BigInt","DataView","DataView.prototype.getFloat32","DataView.prototype.getFloat64","DataView.prototype.getInt16","DataView.prototype.getInt32","DataView.prototype.getInt8","DataView.prototype.getUint16","DataView.prototype.getUint32","DataView.prototype.setUint8","FinalizationRegistry","FinalizationRegistry.prototype.cleanupSome","Float32Array","Float64Array","Int16Array","Int32Array","Int8Array","Intl-enumeration","Intl.DateTimeFormat-datetimestyle","Intl.DateTimeFormat-dayPeriod","Intl.DateTimeFormat-extend-timezonename","Intl.DateTimeFormat-formatRange","Intl.DateTimeFormat-fractionalSecondDigits","Intl.DisplayNames","Intl.DisplayNames-v2","Intl.DurationFormat","Intl.ListFormat","Intl.Locale","Intl.Locale-info","Intl.NumberFormat-unified","Intl.NumberFormat-v3","Intl.RelativeTimeFormat","Intl.Segmenter","IsHTMLDDA","Map","Object.fromEntries","Object.hasOwn","Object.is","Promise","Promise.allSettled","Promise.any","Promise.prototype.finally","Proxy","Reflect","Reflect.construct","Reflect.set","Reflect.setPrototypeOf","Set","ShadowRealm","SharedArrayBuffer","String.fromCodePoint","String.prototype.at","String.prototype.endsWith","String.prototype.includes","String.prototype.matchAll","String.prototype.replaceAll","String.prototype.trimEnd","String.prototype.trimStart","Symbol","Symbol.asyncIterator","Symbol.hasInstance","Symbol.isConcatSpreadable","Symbol.iterator","Symbol.match","Symbol.matchAll","Symbol.prototype.description","Symbol.replace","Symbol.search","Symbol.species","Symbol.split","Symbol.toPrimitive","Symbol.toStringTag","Symbol.unscopables","Temporal","TypedArray","TypedArray.prototype.at","Uint16Array","Uint32Array","Uint8Array","Uint8ClampedArray","WeakMap","WeakRef","WeakSet","__getter__","__proto__","__setter__","align-detached-buffer-semantics-with-web-reality","arbitrary-module-namespace-names","array-find-from-last","array-grouping","arrow-function","async-functions","async-iteration","caller","class","class-fields-private","class-fields-private-in","class-fields-public","class-methods-private","class-static-block","class-static-fields-private","class-static-fields-public","class-static-methods-private","coalesce-expression","computed-property-names","const","cross-realm","decorators","default-parameters","destructuring-assignment","destructuring-binding","dynamic-import","error-cause","export-star-as-namespace-from-module","for-in-order","for-of","generators","globalThis","hashbang","host-gc-required","import-assertions","import.meta","intl-normative-optional","json-modules","json-superset","legacy-regexp","let","logical-assignment-operators","new.target","numeric-separator-literal","object-rest","object-spread","optional-catch-binding","optional-chaining","proxy-missing-checks","regexp-dotall","regexp-duplicate-named-groups","regexp-lookbehind","regexp-match-indices","regexp-named-groups","regexp-unicode-property-escapes","regexp-v-flag","resizable-arraybuffer","rest-parameters","string-trimming","super","tail-call-optimization","template","top-level-await","u180e","well-formed-json-stringify"]}] \ No newline at end of file diff --git a/test262/refs/tags/v0.17.1/features.json b/test262/refs/tags/v0.17.1/features.json deleted file mode 100644 index 739e05b1414..00000000000 --- a/test262/refs/tags/v0.17.1/features.json +++ /dev/null @@ -1 +0,0 @@ -[{"c":"3379753b17b1ba502af0cdb06397dc3f150893c1","u":"8ce9864511c1c83ba2d0b351da3390c9e33fd60e","n":"test","f":["Uint8ClampedArray","Array.prototype.flatMap","Object.fromEntries","regexp-match-indices","DataView.prototype.getFloat32","Symbol.toPrimitive","class-static-methods-private","regexp-dotall","Symbol","Array.prototype.values","class-static-fields-private","Intl.RelativeTimeFormat","error-cause","String.prototype.replaceAll","super","Float64Array","Uint8Array","legacy-regexp","string-trimming","regexp-v-flag","const","TypedArray","new.target","Symbol.matchAll","destructuring-binding","Promise.allSettled","Intl.DateTimeFormat-fractionalSecondDigits","arraybuffer-transfer","String.prototype.isWellFormed","String.prototype.includes","rest-parameters","u180e","Int32Array","iterator-helpers","for-in-order","caller","Array.prototype.includes","DataView","String.prototype.trimStart","Reflect.set","Symbol.isConcatSpreadable","Symbol.asyncIterator","__getter__","proxy-missing-checks","regexp-named-groups","destructuring-assignment","Intl.DateTimeFormat-formatRange","Intl-enumeration","Map","DataView.prototype.getInt32","String.prototype.at","Symbol.hasInstance","symbols-as-weakmap-keys","numeric-separator-literal","String.fromCodePoint","tail-call-optimization","IsHTMLDDA","for-of","decorators","class-static-fields-public","intl-normative-optional","DataView.prototype.getInt8","top-level-await","class-fields-public","let","Promise","Array.fromAsync","json-modules","DataView.prototype.setUint8","Symbol.toStringTag","SharedArrayBuffer","Symbol.split","Temporal","logical-assignment-operators","Atomics","DataView.prototype.getInt16","default-parameters","Intl.DateTimeFormat-datetimestyle","Intl.DateTimeFormat-extend-timezonename","Intl.NumberFormat-unified","class","__setter__","change-array-by-copy","Set","class-static-block","regexp-duplicate-named-groups","arbitrary-module-namespace-names","optional-catch-binding","hashbang","Symbol.unscopables","Intl.ListFormat","Symbol.iterator","class-methods-private","template","BigInt","Object.is","DataView.prototype.getUint16","optional-chaining","String.prototype.endsWith","Intl.DurationFormat","AggregateError","Atomics.waitAsync","class-fields-private-in","String.prototype.trimEnd","DataView.prototype.getFloat64","Object.hasOwn","WeakSet","arrow-function","Symbol.match","Intl.Locale","cross-realm","ShadowRealm","regexp-lookbehind","computed-property-names","Intl.NumberFormat-v3","array-find-from-last","Proxy","exponentiation","ArrayBuffer","Promise.any","well-formed-json-stringify","Symbol.replace","object-rest","export-star-as-namespace-from-module","import.meta","Symbol.species","Float32Array","Symbol.search","FinalizationRegistry","Reflect.setPrototypeOf","Promise.prototype.finally","object-spread","dynamic-import","align-detached-buffer-semantics-with-web-reality","Reflect.construct","json-superset","Array.prototype.flat","Intl.DateTimeFormat-dayPeriod","Reflect","Symbol.prototype.description","array-grouping","host-gc-required","FinalizationRegistry.prototype.cleanupSome","Intl.Locale-info","Uint16Array","async-iteration","TypedArray.prototype.at","resizable-arraybuffer","Intl.Segmenter","WeakMap","String.prototype.toWellFormed","WeakRef","globalThis","String.prototype.matchAll","__proto__","DataView.prototype.getUint32","json-parse-with-source","Uint32Array","coalesce-expression","regexp-unicode-property-escapes","async-functions","generators","Int16Array","Intl.DisplayNames","Array.prototype.at","Intl.DisplayNames-v2","import-assertions","Int8Array","class-fields-private"]}] \ No newline at end of file diff --git a/test262/refs/tags/v0.17.2/features.json b/test262/refs/tags/v0.17.2/features.json deleted file mode 100644 index 10f84b20afb..00000000000 --- a/test262/refs/tags/v0.17.2/features.json +++ /dev/null @@ -1 +0,0 @@ -[{"c":"40241c09374581e19f0f6a4866de16c231b23296","u":"8ce9864511c1c83ba2d0b351da3390c9e33fd60e","n":"test","f":["Uint8ClampedArray","Array.prototype.flatMap","Object.fromEntries","regexp-match-indices","DataView.prototype.getFloat32","Symbol.toPrimitive","class-static-methods-private","regexp-dotall","Symbol","Array.prototype.values","class-static-fields-private","Intl.RelativeTimeFormat","error-cause","String.prototype.replaceAll","super","Float64Array","Uint8Array","legacy-regexp","string-trimming","regexp-v-flag","const","TypedArray","new.target","Symbol.matchAll","destructuring-binding","Promise.allSettled","Intl.DateTimeFormat-fractionalSecondDigits","arraybuffer-transfer","String.prototype.isWellFormed","String.prototype.includes","rest-parameters","u180e","Int32Array","iterator-helpers","for-in-order","caller","Array.prototype.includes","DataView","String.prototype.trimStart","Reflect.set","Symbol.isConcatSpreadable","Symbol.asyncIterator","__getter__","proxy-missing-checks","regexp-named-groups","destructuring-assignment","Intl.DateTimeFormat-formatRange","Intl-enumeration","Map","DataView.prototype.getInt32","String.prototype.at","Symbol.hasInstance","symbols-as-weakmap-keys","numeric-separator-literal","String.fromCodePoint","tail-call-optimization","IsHTMLDDA","for-of","decorators","class-static-fields-public","intl-normative-optional","DataView.prototype.getInt8","top-level-await","class-fields-public","let","Promise","Array.fromAsync","json-modules","DataView.prototype.setUint8","Symbol.toStringTag","SharedArrayBuffer","Symbol.split","Temporal","logical-assignment-operators","Atomics","DataView.prototype.getInt16","default-parameters","Intl.DateTimeFormat-datetimestyle","Intl.DateTimeFormat-extend-timezonename","Intl.NumberFormat-unified","class","__setter__","change-array-by-copy","Set","class-static-block","regexp-duplicate-named-groups","arbitrary-module-namespace-names","optional-catch-binding","hashbang","Symbol.unscopables","Intl.ListFormat","Symbol.iterator","class-methods-private","template","BigInt","Object.is","DataView.prototype.getUint16","optional-chaining","String.prototype.endsWith","Intl.DurationFormat","AggregateError","Atomics.waitAsync","class-fields-private-in","String.prototype.trimEnd","DataView.prototype.getFloat64","Object.hasOwn","WeakSet","arrow-function","Symbol.match","Intl.Locale","cross-realm","ShadowRealm","regexp-lookbehind","computed-property-names","Intl.NumberFormat-v3","array-find-from-last","Proxy","exponentiation","ArrayBuffer","Promise.any","well-formed-json-stringify","Symbol.replace","object-rest","export-star-as-namespace-from-module","import.meta","Symbol.species","Float32Array","Symbol.search","FinalizationRegistry","Reflect.setPrototypeOf","Promise.prototype.finally","object-spread","dynamic-import","align-detached-buffer-semantics-with-web-reality","Reflect.construct","json-superset","Array.prototype.flat","Intl.DateTimeFormat-dayPeriod","Reflect","Symbol.prototype.description","array-grouping","host-gc-required","FinalizationRegistry.prototype.cleanupSome","Intl.Locale-info","Uint16Array","async-iteration","TypedArray.prototype.at","resizable-arraybuffer","Intl.Segmenter","WeakMap","String.prototype.toWellFormed","WeakRef","globalThis","String.prototype.matchAll","__proto__","DataView.prototype.getUint32","json-parse-with-source","Uint32Array","coalesce-expression","regexp-unicode-property-escapes","async-functions","generators","Int16Array","Intl.DisplayNames","Array.prototype.at","Intl.DisplayNames-v2","import-assertions","Int8Array","class-fields-private"]}] \ No newline at end of file diff --git a/test262/refs/tags/v0.17.3/features.json b/test262/refs/tags/v0.17.3/features.json deleted file mode 100644 index 7a3ce481f83..00000000000 --- a/test262/refs/tags/v0.17.3/features.json +++ /dev/null @@ -1 +0,0 @@ -[{"c":"60086838665545aa8f9361b76642616898e42853","u":"8ce9864511c1c83ba2d0b351da3390c9e33fd60e","n":"test","f":["Uint8ClampedArray","Array.prototype.flatMap","Object.fromEntries","regexp-match-indices","DataView.prototype.getFloat32","Symbol.toPrimitive","class-static-methods-private","regexp-dotall","Symbol","Array.prototype.values","Intl.RelativeTimeFormat","class-static-fields-private","super","error-cause","String.prototype.replaceAll","Float64Array","Uint8Array","legacy-regexp","string-trimming","const","regexp-v-flag","TypedArray","new.target","Symbol.matchAll","destructuring-binding","Intl.DateTimeFormat-fractionalSecondDigits","Promise.allSettled","arraybuffer-transfer","String.prototype.isWellFormed","String.prototype.includes","rest-parameters","u180e","Int32Array","caller","for-in-order","iterator-helpers","Array.prototype.includes","Symbol.asyncIterator","DataView","Intl.DateTimeFormat-formatRange","regexp-named-groups","Reflect.set","String.prototype.trimStart","destructuring-assignment","Intl-enumeration","Symbol.isConcatSpreadable","__getter__","proxy-missing-checks","Map","DataView.prototype.getInt32","Symbol.hasInstance","symbols-as-weakmap-keys","String.prototype.at","numeric-separator-literal","tail-call-optimization","decorators","String.fromCodePoint","for-of","IsHTMLDDA","intl-normative-optional","class-static-fields-public","DataView.prototype.getInt8","top-level-await","let","class-fields-public","Promise","json-modules","Array.fromAsync","DataView.prototype.setUint8","Symbol.toStringTag","Temporal","SharedArrayBuffer","Symbol.split","logical-assignment-operators","Intl.DateTimeFormat-datetimestyle","Intl.DateTimeFormat-extend-timezonename","default-parameters","DataView.prototype.getInt16","Intl.NumberFormat-unified","Atomics","class","optional-catch-binding","change-array-by-copy","class-static-block","Set","hashbang","arbitrary-module-namespace-names","__setter__","regexp-duplicate-named-groups","Symbol.unscopables","Intl.ListFormat","class-methods-private","Symbol.iterator","template","BigInt","optional-chaining","DataView.prototype.getUint16","Intl.DurationFormat","Object.is","String.prototype.endsWith","AggregateError","Atomics.waitAsync","class-fields-private-in","String.prototype.trimEnd","DataView.prototype.getFloat64","Object.hasOwn","WeakSet","arrow-function","Intl.Locale","Symbol.match","cross-realm","ShadowRealm","regexp-lookbehind","computed-property-names","Intl.NumberFormat-v3","array-find-from-last","Proxy","exponentiation","ArrayBuffer","Promise.any","well-formed-json-stringify","Symbol.replace","object-rest","export-star-as-namespace-from-module","import.meta","object-spread","Float32Array","Symbol.species","dynamic-import","FinalizationRegistry","Reflect.setPrototypeOf","Symbol.search","Promise.prototype.finally","align-detached-buffer-semantics-with-web-reality","Reflect.construct","json-superset","Array.prototype.flat","Intl.DateTimeFormat-dayPeriod","Reflect","Intl.Locale-info","Symbol.prototype.description","host-gc-required","array-grouping","FinalizationRegistry.prototype.cleanupSome","Uint16Array","async-iteration","Intl.Segmenter","TypedArray.prototype.at","resizable-arraybuffer","WeakMap","String.prototype.toWellFormed","globalThis","WeakRef","String.prototype.matchAll","Uint32Array","__proto__","DataView.prototype.getUint32","json-parse-with-source","coalesce-expression","regexp-unicode-property-escapes","async-functions","generators","Int16Array","Intl.DisplayNames-v2","Intl.DisplayNames","Array.prototype.at","import-assertions","Int8Array","class-fields-private"]}] \ No newline at end of file diff --git a/test262/refs/tags/v0.17/features.json b/test262/refs/tags/v0.17/features.json deleted file mode 100644 index aa6ca6f4e32..00000000000 --- a/test262/refs/tags/v0.17/features.json +++ /dev/null @@ -1 +0,0 @@ -[{"c":"e027932ae2da3f548b28f9fafc4d12b04f69d0e4","u":"8ce9864511c1c83ba2d0b351da3390c9e33fd60e","n":"test","f":["Uint8ClampedArray","Array.prototype.flatMap","Object.fromEntries","regexp-match-indices","DataView.prototype.getFloat32","Symbol.toPrimitive","class-static-methods-private","regexp-dotall","Symbol","Array.prototype.values","Intl.RelativeTimeFormat","class-static-fields-private","error-cause","String.prototype.replaceAll","super","Float64Array","Uint8Array","legacy-regexp","string-trimming","regexp-v-flag","const","TypedArray","new.target","Symbol.matchAll","destructuring-binding","Promise.allSettled","Intl.DateTimeFormat-fractionalSecondDigits","arraybuffer-transfer","String.prototype.isWellFormed","String.prototype.includes","rest-parameters","u180e","iterator-helpers","caller","for-in-order","Int32Array","Array.prototype.includes","Symbol.asyncIterator","DataView","Reflect.set","Symbol.isConcatSpreadable","String.prototype.trimStart","regexp-named-groups","__getter__","proxy-missing-checks","Intl.DateTimeFormat-formatRange","Intl-enumeration","destructuring-assignment","Map","DataView.prototype.getInt32","Symbol.hasInstance","symbols-as-weakmap-keys","String.prototype.at","numeric-separator-literal","String.fromCodePoint","tail-call-optimization","decorators","for-of","IsHTMLDDA","intl-normative-optional","class-static-fields-public","DataView.prototype.getInt8","top-level-await","let","class-fields-public","Promise","Array.fromAsync","json-modules","DataView.prototype.setUint8","Temporal","Symbol.toStringTag","SharedArrayBuffer","Symbol.split","logical-assignment-operators","Atomics","DataView.prototype.getInt16","Intl.DateTimeFormat-datetimestyle","Intl.DateTimeFormat-extend-timezonename","Intl.NumberFormat-unified","default-parameters","class","change-array-by-copy","__setter__","Set","class-static-block","regexp-duplicate-named-groups","optional-catch-binding","hashbang","arbitrary-module-namespace-names","Symbol.unscopables","Intl.ListFormat","Symbol.iterator","class-methods-private","template","BigInt","DataView.prototype.getUint16","Object.is","Intl.DurationFormat","String.prototype.endsWith","optional-chaining","AggregateError","Atomics.waitAsync","class-fields-private-in","String.prototype.trimEnd","DataView.prototype.getFloat64","Object.hasOwn","WeakSet","arrow-function","Symbol.match","Intl.Locale","cross-realm","regexp-lookbehind","ShadowRealm","computed-property-names","Intl.NumberFormat-v3","array-find-from-last","Proxy","exponentiation","ArrayBuffer","Promise.any","well-formed-json-stringify","Symbol.replace","object-rest","export-star-as-namespace-from-module","import.meta","Symbol.species","Float32Array","Symbol.search","Promise.prototype.finally","Reflect.setPrototypeOf","FinalizationRegistry","object-spread","dynamic-import","align-detached-buffer-semantics-with-web-reality","Reflect.construct","json-superset","Array.prototype.flat","Intl.DateTimeFormat-dayPeriod","Reflect","Symbol.prototype.description","array-grouping","host-gc-required","FinalizationRegistry.prototype.cleanupSome","Intl.Locale-info","Uint16Array","async-iteration","TypedArray.prototype.at","resizable-arraybuffer","Intl.Segmenter","WeakMap","String.prototype.toWellFormed","globalThis","WeakRef","String.prototype.matchAll","DataView.prototype.getUint32","__proto__","json-parse-with-source","Uint32Array","coalesce-expression","regexp-unicode-property-escapes","async-functions","generators","Int16Array","Intl.DisplayNames-v2","Array.prototype.at","Intl.DisplayNames","import-assertions","Int8Array","class-fields-private"]}] \ No newline at end of file diff --git a/test262/results.js b/test262/results.js index c66b4bc3e9b..d9db3b5b080 100644 --- a/test262/results.js +++ b/test262/results.js @@ -1,31 +1,30 @@ +const ignored = ["v0.17.1", "v0.17.2"]; + const formatter = new Intl.NumberFormat("en-GB"); const esVersionPicker = document.getElementById("info-options-es-version"); -const hidePassingSwitch = document.getElementById("info-options-hide-passing-switch"); +const hidePassingSwitch = document.getElementById( + "info-options-hide-passing-switch" +); let hidePassingSuites = false; let currentData = null; let esVersion = 255; hidePassingSwitch.checked = false; -hidePassingSwitch - .addEventListener("change", () => { - hidePassingSuites = !hidePassingSuites; - showData(currentData); - }); +hidePassingSwitch.addEventListener("change", () => { + hidePassingSuites = !hidePassingSuites; + showData(currentData); +}); -esVersionPicker.getElementsByTagName('option')[0].selected = true; +esVersionPicker.getElementsByTagName("option")[0].selected = true; esVersionPicker.disabled = false; esVersionPicker.addEventListener("change", () => { const version = Number.parseInt(esVersionPicker.value); - console.log(`selected version: ${version}`); - esVersion = version; - showData(currentData) + showData(currentData); }); - - loadMainData(); loadMainResults(); @@ -40,6 +39,11 @@ loadLatestVersionResults(latestTag); const releaseTags = []; for (const release of releases) { const tag = release.tag_name; + + if (ignored.includes(tag)) { + continue; + } + const version = tag.split("."); // We know there is no data for versions lower than v0.10. @@ -56,7 +60,7 @@ const versionListHTMLItems = await Promise.all( releaseTags.map(async (tag) => { const response = await fetch(`./refs/tags/${tag}/latest.json`); const json = await response.json(); - const stats = json.r.a; + const stats = json.a; releaseData.set(tag, json); @@ -68,18 +72,19 @@ const versionListHTMLItems = await Promise.all( <span class="text-warning">${formatter.format(stats.i)}</span> / <span class="text-danger">${formatter.format( - stats.t - stats.o - stats.i - )} - ${json.r.p !== 0 - ? ` (${formatter.format( - stats.p - )} <i class="bi-exclamation-triangle"></i>)` - : "" - }</span> + stats.t - stats.o - stats.i + )} + ${ + stats.p !== 0 + ? ` (${formatter.format( + stats.p + )} <i class="bi-exclamation-triangle"></i>)` + : "" + }</span> / <b>${formatter.format( - Math.round((10000 * stats.o) / stats.t) / 100 - )}%</b> + Math.round((10000 * stats.o) / stats.t) / 100 + )}%</b> </div> <button type="button" class="btn btn-outline-primary" id="old-version-${tag}"> Test Results @@ -124,41 +129,40 @@ async function loadMainResults() { type: "line", data: { labels: data.map((data) => data.a.t), - datasets: - [ - { - label: "Passed", - data: data.map((data) => data.a.o), - backgroundColor: "#1fcb4a", - borderColor: "#0f6524", - borderWidth: 1, - fill: true, - }, - { - label: "Ignored", - data: data.map((data) => data.a.i), - backgroundColor: "#dfa800", - borderColor: "#6f5400", - borderWidth: 1, - fill: true, - }, - { - label: "Panics", - data: data.map((data) => data.a.p), - backgroundColor: "#a30000", - borderColor: "#510000", - borderWidth: 1, - fill: true, - }, - { - label: "Failed", - data: data.map((data) => data.a.t - data.a.i - data.a.o - data.a.p), - backgroundColor: "#ff4848", - borderColor: "#a30000", - borderWidth: 1, - fill: true, - }, - ], + datasets: [ + { + label: "Passed", + data: data.map((data) => data.a.o), + backgroundColor: "#1fcb4a", + borderColor: "#0f6524", + borderWidth: 1, + fill: true, + }, + { + label: "Ignored", + data: data.map((data) => data.a.i), + backgroundColor: "#dfa800", + borderColor: "#6f5400", + borderWidth: 1, + fill: true, + }, + { + label: "Panics", + data: data.map((data) => data.a.p), + backgroundColor: "#a30000", + borderColor: "#510000", + borderWidth: 1, + fill: true, + }, + { + label: "Failed", + data: data.map((data) => data.a.t - data.a.i - data.a.o - data.a.p), + backgroundColor: "#ff4848", + borderColor: "#a30000", + borderWidth: 1, + fill: true, + }, + ], }, options: { elements: { @@ -212,32 +216,34 @@ function createInfoFromResults(resultsData, nodeID) { "afterbegin", ` <li class="list-group-item"> - Latest commit: <a href="https://github.com/boa-dev/boa/commit/${latest.c - }" title="Check commit">${latest.c}</a> + Latest commit: <a href="https://github.com/boa-dev/boa/commit/${ + latest.c + }" title="Check commit">${latest.c}</a> </li> <li class="list-group-item"> Total tests: <span>${formatter.format(stats.t)}</span> </li> <li class="list-group-item"> Passed tests: <span class="text-success">${formatter.format( - stats.o - )}</span> + stats.o + )}</span> </li> <li class="list-group-item"> Ignored tests: <span class="text-warning">${formatter.format( - stats.i - )}</span> + stats.i + )}</span> </li> <li class="list-group-item"> Failed tests: <span class="text-danger">${formatter.format( - stats.t - stats.o - stats.i - )} - ${stats.p !== 0 - ? ` (${formatter.format( - stats.p - )} <i class="bi-exclamation-triangle"></i>)` - : "" - }</span> + stats.t - stats.o - stats.i + )} + ${ + stats.p !== 0 + ? ` (${formatter.format( + stats.p + )} <i class="bi-exclamation-triangle"></i>)` + : "" + }</span> </li> <li class="list-group-item"> Conformance: <b>${Math.round((10000 * stats.o) / stats.t) / 100}%</b> @@ -254,9 +260,10 @@ function showData(data) { const infoOptionsContainer = document.getElementById("info-options"); const progressInfoContainer = document.getElementById("progress-info"); - const stats = data.r.a; - if (!data.r.av) { - esVersionPicker.getElementsByTagName('option')[0].selected = true; + const stats = data.a; + + if (!data.v) { + esVersionPicker.getElementsByTagName("option")[0].selected = true; esVersionPicker.disabled = true; } else { esVersionPicker.disabled = false; @@ -295,26 +302,29 @@ function showData(data) { ></div> </div>`; - for (const suite of data.r.s) { - addSuite(suite, "info", "test/" + suite.n, data.u); + for (const suiteName in data.r) { + addSuite(suiteName, data.r[suiteName], "info", "test/" + suiteName, data.u); } } -function addSuite(suite, parentID, namespace, upstream) { - +function addSuite(suiteName, suite, parentID, namespace, upstream) { function shouldDisplayTest(test) { - if (hidePassingSuites && test.r === "O") { + if ( + hidePassingSuites && + (typeof test.r === "undefined" || test.r === "O") && + (typeof test.s === "undefined" || test.s === "O") + ) { return false; } return test.v ? test.v <= esVersion : true; } function shouldDisplaySuite(suite) { - const tests = suite.t ?? []; - const subSuites = suite.s ?? []; + const tests = suite.t ?? {}; + const subSuites = suite.s ?? {}; - const hasTests = tests.some(shouldDisplayTest); - const hasSubSuites = subSuites.some(shouldDisplaySuite); + const hasTests = Object.values(tests).some(shouldDisplayTest); + const hasSubSuites = Object.values(subSuites).some(shouldDisplaySuite); return hasTests || hasSubSuites; } @@ -324,7 +334,7 @@ function addSuite(suite, parentID, namespace, upstream) { return suite.a; } - const versioned_stats = suite.av; + const versioned_stats = suite.v; if (!versioned_stats) { return suite.a; } @@ -332,8 +342,8 @@ function addSuite(suite, parentID, namespace, upstream) { let version = esVersion; while (version >= 5) { - if (versioned_stats["es" + version]) { - return versioned_stats["es" + version]; + if (versioned_stats[version]) { + return versioned_stats[version]; } version -= 1; @@ -342,16 +352,23 @@ function addSuite(suite, parentID, namespace, upstream) { return suite.a; } - if (!shouldDisplaySuite(suite)) { return; } const stats = findStats(suite); - const tests = suite.t ? suite.t.filter(shouldDisplayTest) : []; + + const tests = suite.t + ? Object.keys(suite.t).reduce((r, k) => { + if (shouldDisplayTest(suite.t[k])) { + r[k] = suite.t[k]; + } + return r; + }, {}) + : []; const subSuites = suite.s ?? []; - const newID = (parentID + suite.n).replaceAll(".", "-"); + const newID = (parentID + suiteName).replaceAll(".", "-"); const newInnerID = newID + "-inner"; const headerID = newID + "header"; @@ -366,20 +383,21 @@ function addSuite(suite, parentID, namespace, upstream) { data-bs-target="#${newID}" > <span class="data-overview"> - <span class="name">${suite.n}</span> + <span class="name">${suiteName}</span> <span class="text-success">${formatter.format(stats.o)}</span> / <span class="text-warning">${formatter.format(stats.i)}</span> / <span class="text-danger">${formatter.format( - stats.t - stats.o - stats.i - )} - ${stats.p !== 0 - ? ` (${formatter.format( - stats.p - )} <i class="bi-exclamation-triangle"></i>)` - : "" - }</span> + stats.t - stats.o - stats.i + )} + ${ + stats.p !== 0 + ? ` (${formatter.format( + stats.p + )} <i class="bi-exclamation-triangle"></i>)` + : "" + }</span> / <span>${formatter.format(stats.t)}</span> </span> @@ -399,31 +417,31 @@ function addSuite(suite, parentID, namespace, upstream) { newContainer.addEventListener("show.bs.collapse", (event) => { event.stopPropagation(); - if (tests.length != 0) { - const rows = tests - .map((innerTest) => { - const panics = innerTest.r === "P"; - let style; - switch (innerTest.r) { - case "O": - style = "bg-success"; - break; - case "I": - style = "bg-warning"; - break; - default: - style = "bg-danger"; - } - - return `<a - title="${innerTest.n}" - class="card test embed-responsive ${style}${panics ? "" : " embed-responsive-1by1" - }" + if (Object.keys(tests).length != 0) { + const rows = Object.keys(tests).map((testName) => { + const innerTest = tests[testName]; + const panics = innerTest.r === "P" || innerTest.s === "P"; + const passes = innerTest.r === "O" || innerTest.s === "O"; + const ignored = innerTest.r === "I" || innerTest.s === "I"; + + let style; + if (passes) { + style = "bg-success"; + } else if (ignored) { + style = "bg-warning"; + } else { + style = "bg-danger"; + } + + return `<a + title="${testName}" + class="card test embed-responsive ${style}${ + panics ? "" : " embed-responsive-1by1" + }" target="_blank" - href="https://github.com/tc39/test262/blob/${upstream}/${namespace}/${innerTest.n - }.js" + href="https://github.com/tc39/test262/blob/${upstream}/${namespace}/${testName}.js" >${panics ? '<i class="bi-exclamation-triangle"></i>' : ""}</a>`; - }); + }); const testsHTML = `<div class="card"> <div class="row card-body"> @@ -434,11 +452,12 @@ function addSuite(suite, parentID, namespace, upstream) { newInnerContainer.insertAdjacentHTML("beforeend", testsHTML); } - for (const innerSuite of subSuites) { + for (const innerSuite in subSuites) { addSuite( innerSuite, + subSuites[innerSuite], newInnerID, - namespace + "/" + innerSuite.n, + namespace + "/" + innerSuite, upstream ); }