From 8d5efa9b6818af3854afecbc8421f998f9a37bcf Mon Sep 17 00:00:00 2001 From: Philipp Schaad Date: Tue, 23 Apr 2024 16:16:08 +0200 Subject: [PATCH] April fixes (#140) --- .eslintrc.js | 76 +- .github/workflows/build.yml | 2 +- .github/workflows/build_dist.yml | 2 +- .github/workflows/gh-pages.yml | 2 +- .github/workflows/test.yml | 2 +- LICENSE | 2 +- embed.html | 2 +- index.html | 2 +- package-lock.json | 2085 +++++++++-------- package.json | 6 +- samples/embed-iframe.html | 2 +- samples/embed-script.html | 2 +- src/index.ts | 35 +- .../graphlib/algorithms/components.ts | 7 +- src/layouter/graphlib/algorithms/cycles.ts | 11 +- src/layouter/graphlib/algorithms/dominance.ts | 2 + src/layouter/graphlib/algorithms/traversal.ts | 8 +- src/layouter/graphlib/di_graph.ts | 20 +- src/layouter/graphlib/graph.ts | 12 +- src/layouter/graphlib/graph_types.ts | 2 + src/layouter/state_machine/sm_layouter.ts | 28 +- src/local_view/elements/computation_node.ts | 18 +- src/local_view/elements/data_container.ts | 9 +- src/local_view/elements/dimensions.ts | 4 +- src/local_view/elements/edge.ts | 2 +- src/local_view/elements/element.ts | 2 +- src/local_view/elements/map_node.ts | 100 +- .../elements/memory_movement_edge.ts | 40 +- src/local_view/elements/memory_node.ts | 104 +- src/local_view/elements/node.ts | 2 +- src/local_view/graph/graph.ts | 15 +- src/local_view/gui/button.ts | 7 +- src/local_view/gui/gui_component.ts | 2 +- src/local_view/gui/slider.ts | 6 +- src/local_view/lview_layouter.ts | 6 +- src/local_view/lview_parser.ts | 37 +- src/local_view/lview_renderer.ts | 22 +- .../overlays/access_pattern_overlay.ts | 2 +- src/local_view/overlays/base_overlays.ts | 4 +- src/local_view/overlays/cache_line_overlay.ts | 2 +- .../overlays/physical_movement_overlay.ts | 2 +- .../overlays/reuse_distance_overlay.ts | 2 +- src/overlay_manager.ts | 8 +- src/overlays/avg_parallelism_overlay.ts | 152 +- src/overlays/depth_overlay.ts | 51 +- src/overlays/generic_sdfg_overlay.ts | 12 +- src/overlays/logical_group_overlay.ts | 47 +- src/overlays/memory_location_overlay.ts | 68 +- src/overlays/memory_volume_overlay.ts | 258 +- src/overlays/operational_intensity_overlay.ts | 50 +- src/overlays/runtime_micro_seconds_overlay.ts | 28 +- ...simulated_operational_intensity_overlay.ts | 66 +- src/overlays/static_flops_overlay.ts | 51 +- src/renderer/canvas_manager.ts | 187 +- src/renderer/renderer.ts | 1489 +++++++----- src/renderer/renderer_elements.ts | 396 ++-- src/sdfv.ts | 126 +- src/utils/bounding_box.ts | 6 +- src/utils/collections.ts | 6 +- src/utils/lerp_matrix.ts | 9 +- src/utils/sanitization.ts | 11 +- src/utils/sdfg/display.ts | 54 +- src/utils/sdfg/json_serializer.ts | 18 +- src/utils/sdfg/memlet_trees.ts | 255 ++ src/utils/sdfg/sdfg_parser.ts | 31 +- src/utils/sdfg/sdfg_utils.ts | 279 +-- src/utils/sdfg/traversal.ts | 394 +--- src/utils/sdfv_settings.ts | 31 +- src/utils/utils.ts | 67 +- 69 files changed, 3762 insertions(+), 3086 deletions(-) create mode 100644 src/utils/sdfg/memlet_trees.ts diff --git a/.eslintrc.js b/.eslintrc.js index 6b31f5c5..86ee44e7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,9 +28,79 @@ module.exports = { ], "@typescript-eslint/no-unsafe-declaration-merging": "warn", "@typescript-eslint/no-var-requires": "warn", - "semi": "error", + "array-bracket-newline": ["warn", { + "multiline": true + }], + "array-bracket-spacing": ["warn", "never"], + "array-element-newline": ["warn", "consistent"], + "arrow-spacing": "warn", + "block-spacing": ["warn", "always"], + "brace-style": ["warn", "1tbs"], + //"camelcase": ["warn"], + "comma-spacing": "warn", + "comma-dangle": ["warn", { + "functions": "never", + "arrays": "always-multiline", + "objects": "always-multiline", + "imports": "always-multiline", + "exports": "always-multiline" + }], + "constructor-super": "warn", + "curly": ["warn", "multi-or-nest", "consistent"], + "eol-last": "warn", + "eqeqeq": "warn", + "func-call-spacing": ["warn", "never"], + "function-paren-newline": ["warn", "consistent"], + "implicit-arrow-linebreak": ["warn", "beside"], + "indent": ["warn", 4, { + "SwitchCase": 1 + }], + "lines-between-class-members": "off", + "max-len": ["warn", { + "code": 80, + "ignoreComments": false, + "ignoreTrailingComments": false, + "ignoreUrls": true, + "ignoreStrings": false, + "ignoreTemplateLiterals": true, + "ignoreRegExpLiterals": true + }], + "no-case-declarations": "off", + "no-empty": "off", + "no-fallthrough": "off", + "no-throw-literal": "warn", + "no-trailing-spaces": "warn", + "no-undef": "off", + "no-unused-vars": "off", "no-useless-escape": "off", + "no-multiple-empty-lines": "warn", + "no-nested-ternary": "warn", + "no-var": "warn", + "no-whitespace-before-property": "warn", + "new-parens": ["warn", "always"], + "nonblock-statement-body-position": ["warn", "below"], + "object-curly-newline": ["warn", { + "consistent": true + }], + "object-curly-spacing": ["warn", "always"], + "object-property-newline": ["warn", { + "allowMultiplePropertiesPerLine": true, + }], + "operator-linebreak": ["warn", "after"], + "padded-blocks": ["warn", { + "blocks": "never", + "classes": "always", + "switches": "never" + }], "prefer-arrow-callback": "error", - "no-empty": "off", - } + "quotes": ["warn", "single"], + "semi": "error", + "space-before-blocks": ["warn", "always"], + "space-before-function-paren": ["warn", { + "anonymous": "always", + "named": "never", + "asyncArrow": "always" + }], + "space-in-parens": ["warn", "never"], + }, }; diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 90ffdda1..ccde84b1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node-version: [18.4] + node-version: [18.12] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/build_dist.yml b/.github/workflows/build_dist.yml index 91c5f46b..9f00a8b3 100644 --- a/.github/workflows/build_dist.yml +++ b/.github/workflows/build_dist.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: - node-version: [18.4] + node-version: [18.12] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index fefabaff..b2578cd2 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -27,7 +27,7 @@ jobs: url: ${{ steps.deployment.outputs.page_url }} strategy: matrix: - node-version: [18.4] + node-version: [18.12] runs-on: ubuntu-latest steps: - name: Checkout diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 58497c89..cafec168 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node-version: [18.4] + node-version: [18.12] steps: - uses: actions/checkout@v3 diff --git a/LICENSE b/LICENSE index 0bdd0f3e..6bceeb8c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2019-2022, Scalable Parallel Computing Lab, ETH Zurich, and all contributors listed in AUTHORS +Copyright (c) 2019-2024, Scalable Parallel Computing Lab, ETH Zurich, and all contributors listed in AUTHORS All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/embed.html b/embed.html index fd43b2ff..5126f6e1 100644 --- a/embed.html +++ b/embed.html @@ -1,4 +1,4 @@ - + diff --git a/index.html b/index.html index e93e573a..e9b4d1d0 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ - + diff --git a/package-lock.json b/package-lock.json index b88520dd..89c99353 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@spcl/sdfv", - "version": "1.1.6", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@spcl/sdfv", - "version": "1.1.6", + "version": "1.2.0", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -62,10 +62,10 @@ "typescript": "^5.3.3", "webpack": "^5.89.0", "webpack-cli": "^5.1.4", - "webpack-dev-server": "^4.15.1" + "webpack-dev-server": "^5.0" }, "engines": { - "node": ">=18.4.0" + "node": ">=18.12.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -78,25 +78,25 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/cli": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.23.4.tgz", - "integrity": "sha512-j3luA9xGKCXVyCa5R7lJvOMM+Kc2JEnAEIgz2ggtjQ/j5YUVgfsg/WsG95bbsgq7YLHuiCOzMnoSasuY16qiCw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.24.1.tgz", + "integrity": "sha512-HbmrtxyFUr34LwAlV9jS+sSIjUp4FpdtIMGwgufY3AsxrIfsh/HxlMTywsONAZsU0RMYbZtbZFpUCrSGs7o0EA==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.25", "commander": "^4.0.1", "convert-source-map": "^2.0.0", "fs-readdir-recursive": "^1.1.0", @@ -120,43 +120,43 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", - "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.7", - "@babel/parser": "^7.23.6", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.7", - "@babel/types": "^7.23.6", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -172,14 +172,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", "dev": true, "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -227,9 +227,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", - "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz", + "integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", @@ -237,7 +237,7 @@ "@babel/helper-function-name": "^7.23.0", "@babel/helper-member-expression-to-functions": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", "semver": "^6.3.1" @@ -267,9 +267,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", - "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", + "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -329,12 +329,12 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -372,9 +372,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -398,13 +398,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-member-expression-to-functions": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { @@ -451,9 +451,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -492,37 +492,38 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", - "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.7", - "@babel/types": "^7.23.6" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", - "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -531,13 +532,29 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz", + "integrity": "sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", - "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", + "integrity": "sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -547,14 +564,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", - "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz", + "integrity": "sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.23.3" + "@babel/plugin-transform-optional-chaining": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -564,13 +581,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", - "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz", + "integrity": "sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -667,12 +684,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", - "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -682,12 +699,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", - "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz", + "integrity": "sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -721,12 +738,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -838,12 +855,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -869,12 +886,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", - "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", + "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -884,13 +901,13 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz", - "integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", + "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-remap-async-to-generator": "^7.22.20", "@babel/plugin-syntax-async-generators": "^7.8.4" }, @@ -902,13 +919,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", - "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", + "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-module-imports": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-remap-async-to-generator": "^7.22.20" }, "engines": { @@ -919,12 +936,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", - "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", + "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -934,12 +951,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", - "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz", + "integrity": "sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -949,13 +966,13 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", - "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", + "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -965,13 +982,13 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", - "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", + "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.4", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -982,17 +999,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", - "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", + "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, @@ -1004,13 +1021,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", - "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", + "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.15" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/template": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1020,12 +1037,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", - "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", + "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1035,13 +1052,13 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", - "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz", + "integrity": "sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1051,12 +1068,12 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", - "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz", + "integrity": "sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1066,12 +1083,12 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", - "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz", + "integrity": "sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -1082,13 +1099,13 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", - "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", + "integrity": "sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==", "dev": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1098,12 +1115,12 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", - "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz", + "integrity": "sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -1114,12 +1131,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", - "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", + "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { @@ -1130,14 +1147,14 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", - "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", + "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1147,12 +1164,12 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", - "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz", + "integrity": "sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -1163,12 +1180,12 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", - "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", + "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1178,12 +1195,12 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", - "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz", + "integrity": "sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -1194,12 +1211,12 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", - "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", + "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1209,13 +1226,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", - "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz", + "integrity": "sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1225,13 +1242,13 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-simple-access": "^7.22.5" }, "engines": { @@ -1242,14 +1259,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", - "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz", + "integrity": "sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==", "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { @@ -1260,13 +1277,13 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", - "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz", + "integrity": "sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1292,12 +1309,12 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", - "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz", + "integrity": "sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1307,12 +1324,12 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", - "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", + "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -1323,12 +1340,12 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", - "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz", + "integrity": "sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -1339,16 +1356,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", - "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz", + "integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.3", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.23.3" + "@babel/plugin-transform-parameters": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1358,13 +1374,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", - "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", + "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.20" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1374,12 +1390,12 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", - "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz", + "integrity": "sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -1390,12 +1406,12 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", - "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz", + "integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, @@ -1407,12 +1423,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", - "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", + "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1422,13 +1438,13 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", - "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", + "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1438,14 +1454,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", - "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", + "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1456,12 +1472,12 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", - "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", + "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1471,12 +1487,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", - "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz", + "integrity": "sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "regenerator-transform": "^0.15.2" }, "engines": { @@ -1487,12 +1503,12 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", - "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz", + "integrity": "sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1502,16 +1518,16 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.7.tgz", - "integrity": "sha512-fa0hnfmiXc9fq/weK34MUV0drz2pOL/vfKWvN7Qw127hiUPabFCUMgAbYWcchRzMJit4o5ARsK/s+5h0249pLw==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", + "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "babel-plugin-polyfill-corejs2": "^0.4.7", - "babel-plugin-polyfill-corejs3": "^0.8.7", - "babel-plugin-polyfill-regenerator": "^0.5.4", + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-plugin-utils": "^7.24.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, "engines": { @@ -1522,12 +1538,12 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", - "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", + "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1537,12 +1553,12 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", - "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", + "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { @@ -1553,12 +1569,12 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", - "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz", + "integrity": "sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1568,12 +1584,12 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", - "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", + "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1583,12 +1599,12 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", - "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz", + "integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1598,15 +1614,15 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", - "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.4.tgz", + "integrity": "sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-typescript": "^7.23.3" + "@babel/helper-create-class-features-plugin": "^7.24.4", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-typescript": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1616,12 +1632,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", - "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz", + "integrity": "sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1631,13 +1647,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", - "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz", + "integrity": "sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1647,13 +1663,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", - "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz", + "integrity": "sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1663,13 +1679,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", - "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz", + "integrity": "sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -1679,26 +1695,27 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.8.tgz", - "integrity": "sha512-lFlpmkApLkEP6woIKprO6DO60RImpatTQKtz4sUcDjVcK8M8mQ4sZsuxaTMNOZf0sqAq/ReYW1ZBHnOQwKpLWA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.4.tgz", + "integrity": "sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.5", + "@babel/compat-data": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.4", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.23.3", - "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-assertions": "^7.24.1", + "@babel/plugin-syntax-import-attributes": "^7.24.1", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -1710,58 +1727,58 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.23.3", - "@babel/plugin-transform-async-generator-functions": "^7.23.7", - "@babel/plugin-transform-async-to-generator": "^7.23.3", - "@babel/plugin-transform-block-scoped-functions": "^7.23.3", - "@babel/plugin-transform-block-scoping": "^7.23.4", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-class-static-block": "^7.23.4", - "@babel/plugin-transform-classes": "^7.23.8", - "@babel/plugin-transform-computed-properties": "^7.23.3", - "@babel/plugin-transform-destructuring": "^7.23.3", - "@babel/plugin-transform-dotall-regex": "^7.23.3", - "@babel/plugin-transform-duplicate-keys": "^7.23.3", - "@babel/plugin-transform-dynamic-import": "^7.23.4", - "@babel/plugin-transform-exponentiation-operator": "^7.23.3", - "@babel/plugin-transform-export-namespace-from": "^7.23.4", - "@babel/plugin-transform-for-of": "^7.23.6", - "@babel/plugin-transform-function-name": "^7.23.3", - "@babel/plugin-transform-json-strings": "^7.23.4", - "@babel/plugin-transform-literals": "^7.23.3", - "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", - "@babel/plugin-transform-member-expression-literals": "^7.23.3", - "@babel/plugin-transform-modules-amd": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-modules-systemjs": "^7.23.3", - "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-arrow-functions": "^7.24.1", + "@babel/plugin-transform-async-generator-functions": "^7.24.3", + "@babel/plugin-transform-async-to-generator": "^7.24.1", + "@babel/plugin-transform-block-scoped-functions": "^7.24.1", + "@babel/plugin-transform-block-scoping": "^7.24.4", + "@babel/plugin-transform-class-properties": "^7.24.1", + "@babel/plugin-transform-class-static-block": "^7.24.4", + "@babel/plugin-transform-classes": "^7.24.1", + "@babel/plugin-transform-computed-properties": "^7.24.1", + "@babel/plugin-transform-destructuring": "^7.24.1", + "@babel/plugin-transform-dotall-regex": "^7.24.1", + "@babel/plugin-transform-duplicate-keys": "^7.24.1", + "@babel/plugin-transform-dynamic-import": "^7.24.1", + "@babel/plugin-transform-exponentiation-operator": "^7.24.1", + "@babel/plugin-transform-export-namespace-from": "^7.24.1", + "@babel/plugin-transform-for-of": "^7.24.1", + "@babel/plugin-transform-function-name": "^7.24.1", + "@babel/plugin-transform-json-strings": "^7.24.1", + "@babel/plugin-transform-literals": "^7.24.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", + "@babel/plugin-transform-member-expression-literals": "^7.24.1", + "@babel/plugin-transform-modules-amd": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-modules-systemjs": "^7.24.1", + "@babel/plugin-transform-modules-umd": "^7.24.1", "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.23.3", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", - "@babel/plugin-transform-numeric-separator": "^7.23.4", - "@babel/plugin-transform-object-rest-spread": "^7.23.4", - "@babel/plugin-transform-object-super": "^7.23.3", - "@babel/plugin-transform-optional-catch-binding": "^7.23.4", - "@babel/plugin-transform-optional-chaining": "^7.23.4", - "@babel/plugin-transform-parameters": "^7.23.3", - "@babel/plugin-transform-private-methods": "^7.23.3", - "@babel/plugin-transform-private-property-in-object": "^7.23.4", - "@babel/plugin-transform-property-literals": "^7.23.3", - "@babel/plugin-transform-regenerator": "^7.23.3", - "@babel/plugin-transform-reserved-words": "^7.23.3", - "@babel/plugin-transform-shorthand-properties": "^7.23.3", - "@babel/plugin-transform-spread": "^7.23.3", - "@babel/plugin-transform-sticky-regex": "^7.23.3", - "@babel/plugin-transform-template-literals": "^7.23.3", - "@babel/plugin-transform-typeof-symbol": "^7.23.3", - "@babel/plugin-transform-unicode-escapes": "^7.23.3", - "@babel/plugin-transform-unicode-property-regex": "^7.23.3", - "@babel/plugin-transform-unicode-regex": "^7.23.3", - "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/plugin-transform-new-target": "^7.24.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", + "@babel/plugin-transform-numeric-separator": "^7.24.1", + "@babel/plugin-transform-object-rest-spread": "^7.24.1", + "@babel/plugin-transform-object-super": "^7.24.1", + "@babel/plugin-transform-optional-catch-binding": "^7.24.1", + "@babel/plugin-transform-optional-chaining": "^7.24.1", + "@babel/plugin-transform-parameters": "^7.24.1", + "@babel/plugin-transform-private-methods": "^7.24.1", + "@babel/plugin-transform-private-property-in-object": "^7.24.1", + "@babel/plugin-transform-property-literals": "^7.24.1", + "@babel/plugin-transform-regenerator": "^7.24.1", + "@babel/plugin-transform-reserved-words": "^7.24.1", + "@babel/plugin-transform-shorthand-properties": "^7.24.1", + "@babel/plugin-transform-spread": "^7.24.1", + "@babel/plugin-transform-sticky-regex": "^7.24.1", + "@babel/plugin-transform-template-literals": "^7.24.1", + "@babel/plugin-transform-typeof-symbol": "^7.24.1", + "@babel/plugin-transform-unicode-escapes": "^7.24.1", + "@babel/plugin-transform-unicode-property-regex": "^7.24.1", + "@babel/plugin-transform-unicode-regex": "^7.24.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.7", - "babel-plugin-polyfill-corejs3": "^0.8.7", - "babel-plugin-polyfill-regenerator": "^0.5.4", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", "core-js-compat": "^3.31.0", "semver": "^6.3.1" }, @@ -1787,16 +1804,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz", + "integrity": "sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-syntax-jsx": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-typescript": "^7.24.1" }, "engines": { "node": ">=6.9.0" @@ -1812,9 +1829,9 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", - "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", + "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -1823,33 +1840,33 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", - "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.6", - "@babel/types": "^7.23.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1858,9 +1875,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", - "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.23.4", @@ -2023,9 +2040,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2087,9 +2104,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@isaacs/cliui": { @@ -2609,14 +2626,14 @@ } }, "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", - "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", "dev": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", "semver": "^7.5.4" }, @@ -2637,9 +2654,9 @@ } }, "node_modules/@jest/reporters/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -2936,45 +2953,45 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { @@ -2984,9 +3001,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", - "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2999,9 +3016,9 @@ "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" }, "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "dev": true }, "node_modules/@nicolo-ribaudo/chokidar-2": { @@ -3072,9 +3089,9 @@ } }, "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -3508,9 +3525,9 @@ "dev": true }, "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" @@ -3535,9 +3552,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true }, "node_modules/@tsconfig/node12": { @@ -3658,9 +3675,9 @@ "integrity": "sha512-qp3m9PPz4gULB9MhjGID7wpo3gJ4bTGXm7ltNDsmOvsPduTeHp8wSW9YckBj3mljeOh4F0m2z/0JKAALRKbmLQ==" }, "node_modules/@types/eslint": { - "version": "8.56.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz", - "integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==", + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", "dev": true, "dependencies": { "@types/estree": "*", @@ -3696,9 +3713,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.41", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", - "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz", + "integrity": "sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==", "dev": true, "dependencies": { "@types/node": "*", @@ -3756,9 +3773,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.11", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", - "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -3793,9 +3810,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.1.tgz", - "integrity": "sha512-DsXojJUES2M+FE8CpptJTKpg+r54moV9ZEncPstni1WHFmTcCzeFLnMFfyhCVS8XNOy/OQG+8lVxRLRrVHmV5A==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3817,9 +3834,9 @@ "dev": true }, "node_modules/@types/qs": { - "version": "6.9.11", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", "dev": true }, "node_modules/@types/range-parser": { @@ -3829,15 +3846,15 @@ "dev": true }, "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "dev": true }, "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/send": { @@ -3860,14 +3877,14 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", - "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dev": true, "dependencies": { "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" + "@types/node": "*", + "@types/send": "*" } }, "node_modules/@types/sizzle": { @@ -3916,16 +3933,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz", - "integrity": "sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/type-utils": "6.18.1", - "@typescript-eslint/utils": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -3963,9 +3980,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -3984,15 +4001,15 @@ "dev": true }, "node_modules/@typescript-eslint/parser": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.1.tgz", - "integrity": "sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4" }, "engines": { @@ -4012,13 +4029,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz", - "integrity": "sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -4029,13 +4046,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz", - "integrity": "sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.18.1", - "@typescript-eslint/utils": "6.18.1", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -4056,9 +4073,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.1.tgz", - "integrity": "sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -4069,13 +4086,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz", - "integrity": "sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/visitor-keys": "6.18.1", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -4109,9 +4126,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -4130,17 +4147,17 @@ "dev": true }, "node_modules/@typescript-eslint/utils": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.1.tgz", - "integrity": "sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.1", - "@typescript-eslint/types": "6.18.1", - "@typescript-eslint/typescript-estree": "6.18.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" }, "engines": { @@ -4167,9 +4184,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -4188,12 +4205,12 @@ "dev": true }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz", - "integrity": "sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.1", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4211,9 +4228,9 @@ "dev": true }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", @@ -4233,9 +4250,9 @@ "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { @@ -4256,15 +4273,15 @@ "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@webassemblyjs/wasm-gen": "1.12.1" } }, "node_modules/@webassemblyjs/ieee754": { @@ -4292,28 +4309,28 @@ "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", "@webassemblyjs/leb128": "1.11.6", @@ -4321,24 +4338,24 @@ } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", @@ -4347,12 +4364,12 @@ } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, @@ -4725,9 +4742,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.16", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", - "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", "dev": true, "funding": [ { @@ -4744,9 +4761,9 @@ } ], "dependencies": { - "browserslist": "^4.21.10", - "caniuse-lite": "^1.0.30001538", - "fraction.js": "^4.3.6", + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", + "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", "postcss-value-parser": "^4.2.0" @@ -4762,9 +4779,12 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -5025,13 +5045,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz", - "integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==", + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", + "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.4", + "@babel/helper-define-polyfill-provider": "^0.6.1", "semver": "^6.3.1" }, "peerDependencies": { @@ -5039,25 +5059,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", - "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.4", - "core-js-compat": "^3.33.1" + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz", - "integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", + "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.4" + "@babel/helper-define-polyfill-provider": "^0.6.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -5260,22 +5280,25 @@ } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dev": true, "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -5283,7 +5306,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -5354,9 +5377,9 @@ } }, "node_modules/bootstrap": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz", - "integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", "funding": [ { "type": "github", @@ -5400,9 +5423,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -5419,8 +5442,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -5481,6 +5504,21 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -5617,13 +5655,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5665,9 +5708,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001576", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz", - "integrity": "sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==", + "version": "1.0.30001612", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz", + "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==", "dev": true, "funding": [ { @@ -5708,14 +5751,14 @@ } }, "node_modules/chart.js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", - "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.2.tgz", + "integrity": "sha512-6GD7iKwFpP5kbSD4MeRRRlTnQvxfQREy36uEtm1hzHzcOqwWx0YEHuspuoNlslu+nciLIB7fjjsHkUv/FzFcOg==", "dependencies": { "@kurkle/color": "^0.3.0" }, "engines": { - "pnpm": ">=7" + "pnpm": ">=8" } }, "node_modules/chartjs-plugin-annotation": { @@ -5727,16 +5770,10 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -5749,6 +5786,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -6005,9 +6045,9 @@ "dev": true }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "dev": true, "engines": { "node": ">= 0.6" @@ -6028,12 +6068,12 @@ "hasInstallScript": true }, "node_modules/core-js-compat": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", - "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", + "version": "3.37.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.0.tgz", + "integrity": "sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==", "dev": true, "dependencies": { - "browserslist": "^4.22.2" + "browserslist": "^4.23.0" }, "funding": { "type": "opencollective", @@ -6201,16 +6241,16 @@ } }, "node_modules/css-loader": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.9.0.tgz", - "integrity": "sha512-3I5Nu4ytWlHvOP6zItjiHlefBNtrH+oehq8tnQa2kO305qpVyx9XNIT1CXIj5bgCJs7qICBCkgCYxQLKPANoLA==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", "dev": true, "dependencies": { "icss-utils": "^5.1.0", - "postcss": "^8.4.31", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.3", - "postcss-modules-scope": "^3.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", "semver": "^7.5.4" @@ -6223,7 +6263,16 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/css-loader/node_modules/lru-cache": { @@ -6239,9 +6288,9 @@ } }, "node_modules/css-loader/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -6337,9 +6386,9 @@ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" @@ -6365,6 +6414,34 @@ "node": ">=0.10.0" } }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/default-gateway": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", @@ -6378,25 +6455,31 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/define-properties": { @@ -6527,9 +6610,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.630", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.630.tgz", - "integrity": "sha512-osHqhtjojpCsACVnuD11xO5g9xaCyw7Qqn/C2KParkMv42i8jrJJgx3g7mkHfpxwhy9MnOJr8+pKOdZ7qzgizg==", + "version": "1.4.745", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.745.tgz", + "integrity": "sha512-tRbzkaRI5gbUn5DEvF0dV4TQbMZ5CLkWeTAXmpC9IrYT+GE+x76i9p+o3RJ5l9XmdQlI1pPhVtE9uNcJJ0G0EA==", "dev": true }, "node_modules/emittery": { @@ -6579,9 +6662,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", + "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -6601,9 +6684,9 @@ } }, "node_modules/envinfo": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", - "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.12.0.tgz", + "integrity": "sha512-Iw9rQJBGpJRd3rwXm9ft/JiGoAZmLxxJZELYDQoPRZ4USVhkKtIcNBPw6U+/K2mBpaqM25JSV6Yl4Az9vO2wJg==", "dev": true, "bin": { "envinfo": "dist/cli.js" @@ -6627,16 +6710,35 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.0.tgz", + "integrity": "sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw==", "dev": true }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -6663,16 +6765,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -7096,17 +7198,17 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -7211,9 +7313,9 @@ } }, "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -7410,15 +7512,15 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -7528,12 +7630,6 @@ "node": ">= 8" } }, - "node_modules/fs-monkey": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", - "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", - "dev": true - }, "node_modules/fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", @@ -7617,15 +7713,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7887,20 +7987,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -7920,11 +8020,11 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -7940,9 +8040,9 @@ "dev": true }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -8029,9 +8129,9 @@ } }, "node_modules/html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", "dev": true, "funding": [ { @@ -8230,9 +8330,9 @@ ] }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -8350,16 +8450,29 @@ "loose-envify": "^1.0.0" } }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, "node_modules/ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", "dev": true, "engines": { "node": ">= 10" @@ -8488,6 +8601,39 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-lambda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", @@ -8509,6 +8655,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -8560,11 +8718,11 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -8684,9 +8842,9 @@ } }, "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -8731,9 +8889,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -10042,9 +10200,9 @@ } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -10427,6 +10585,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -10458,9 +10622,9 @@ "dev": true }, "node_modules/json-stable-stringify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.0.tgz", - "integrity": "sha512-zfA+5SuwYN2VWqN1/5HZaDzQKLJHaBVMZIIM+wuYjdptkaQsqzDdqjqf+lZZJUuJq1aanHiY8LhH8LmH+qBYJA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz", + "integrity": "sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==", "dependencies": { "call-bind": "^1.0.5", "isarray": "^2.0.5", @@ -10754,16 +10918,16 @@ "integrity": "sha512-/2YoaB79IjUK2B2JB+vIXXYGtBfHb/XG66LvoKVM5ykHW7yfrV5SP6d7KLX6iijY6/G9GqwgtPQ/sbhFnOURVA==" }, "node_modules/material-symbols": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/material-symbols/-/material-symbols-0.14.5.tgz", - "integrity": "sha512-3fB0MEG93k8C7D7sI0HSQWlKy3rgIQ6HPICkEPs9blsod/nWofSBdDPvUa9XpNRIqciqLA+hZF8DVnA4J19BlQ==" + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/material-symbols/-/material-symbols-0.14.7.tgz", + "integrity": "sha512-65aJAnHtKx98tm41vz9gS6fQfUo+8pCg2sETOC/linpHKEv6gw7U+iHN5Bha6tfM8hDSGfjCwaKOWb+Rs/XyDg==" }, "node_modules/mathjs": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-12.3.0.tgz", - "integrity": "sha512-Mik+O8gbH14/1V2D/vdJNgu+qGXpF+2oeBJVBqN8nbOdZNuu4Nxw6aDbJ0QOkDSq/9bQ+AZpXoIxBuErRODS8w==", + "version": "12.4.1", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-12.4.1.tgz", + "integrity": "sha512-welnW3khgwYjPYvECFHO+xkCxAx9IKIIPDDWPi8B5rKAvmgoEHnQX9slEmHKZTNaJiE+OS4qrJJcB4sfDn/4sw==", "dependencies": { - "@babel/runtime": "^7.23.8", + "@babel/runtime": "^7.24.0", "complex.js": "^2.1.1", "decimal.js": "^10.4.3", "escape-latex": "^1.2.0", @@ -10802,15 +10966,19 @@ } }, "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.8.2.tgz", + "integrity": "sha512-j4WKth315edViMBGkHW6NTF0QBjsTrcRDmYNcGsPq+ozMEyCCCIlX2d2mJ5wuh6iHvJ3FevUrr48v58YRqVdYg==", "dev": true, "dependencies": { - "fs-monkey": "^1.0.4" + "tslib": "^2.0.0" }, "engines": { "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" } }, "node_modules/meow": { @@ -11139,9 +11307,9 @@ } }, "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", + "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==", "dev": true }, "node_modules/nanoid": { @@ -11364,9 +11532,9 @@ } }, "node_modules/node-gyp/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -11582,9 +11750,9 @@ } }, "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -11664,12 +11832,12 @@ } }, "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -11851,16 +12019,20 @@ } }, "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", "dev": true, "dependencies": { - "@types/retry": "0.12.0", + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", "retry": "^0.13.1" }, "engines": { - "node": ">=8" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-retry/node_modules/retry": { @@ -12030,9 +12202,9 @@ } }, "node_modules/patch-package/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -12091,12 +12263,12 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { @@ -12107,9 +12279,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -12333,10 +12505,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, "funding": [ { @@ -12355,7 +12535,7 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -12396,9 +12576,9 @@ } }, "node_modules/postcss-loader/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -12417,9 +12597,9 @@ "dev": true }, "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "dev": true, "engines": { "node": "^10 || ^12 || >= 14" @@ -12429,9 +12609,9 @@ } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", "dev": true, "dependencies": { "icss-utils": "^5.0.0", @@ -12446,9 +12626,9 @@ } }, "node_modules/postcss-modules-scope": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.0.tgz", - "integrity": "sha512-SaIbK8XW+MZbd0xHPf7kdfA/3eOt7vxJ72IRecn3EzuZVLr1r0orzf0MX/pN8m+NMDoo6X/SQd8oeKqGZd8PXg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.4" @@ -12476,9 +12656,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.15", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", - "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -12612,9 +12792,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -12628,11 +12808,11 @@ ] }, "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", + "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -12689,9 +12869,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { "bytes": "3.1.2", @@ -13036,16 +13216,16 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" }, "bin": { "glob": "dist/esm/bin.mjs" @@ -13066,6 +13246,18 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -13428,15 +13620,16 @@ "dev": true }, "node_modules/set-function-length": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", - "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -13489,13 +13682,17 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13543,16 +13740,16 @@ } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -13580,9 +13777,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -13609,9 +13806,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -13625,9 +13822,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, "node_modules/spdy": { @@ -13929,9 +14126,9 @@ } }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "dependencies": { "chownr": "^2.0.0", @@ -13961,9 +14158,9 @@ "dev": true }, "node_modules/terser": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", - "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "version": "5.30.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.30.3.tgz", + "integrity": "sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -14199,21 +14396,21 @@ "dev": true }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" } }, "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -14229,7 +14426,7 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", @@ -14266,9 +14463,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -14386,9 +14583,9 @@ } }, "node_modules/ts-loader/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -14470,6 +14667,12 @@ } } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -14525,9 +14728,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -14761,9 +14964,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -14783,34 +14986,34 @@ } }, "node_modules/webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "version": "5.91.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", + "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.16.0", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -14884,77 +15087,83 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz", + "integrity": "sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==", "dev": true, "dependencies": { "colorette": "^2.0.10", - "memfs": "^3.4.3", + "memfs": "^4.6.0", "mime-types": "^2.1.31", + "on-finished": "^2.4.1", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, "node_modules/webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", + "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", "default-gateway": "^6.0.3", "express": "^4.17.3", "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", + "html-entities": "^2.4.0", "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" + "webpack-dev-middleware": "^7.1.0", + "ws": "^8.16.0" }, "bin": { "webpack-dev-server": "bin/webpack-dev-server.js" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" + "webpack": "^5.0.0" }, "peerDependenciesMeta": { "webpack": { @@ -14965,36 +15174,37 @@ } } }, - "node_modules/webpack-dev-server/node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "node_modules/webpack-dev-server/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/webpack-dev-server/node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/webpack-merge": { @@ -15098,15 +15308,15 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -15286,9 +15496,12 @@ "dev": true }, "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } diff --git a/package.json b/package.json index 00e4101d..562c129e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@spcl/sdfv", - "version": "1.1.6", + "version": "1.2.0", "description": "A standalone viewer for SDFGs", "homepage": "https://github.com/spcl/dace-webclient", "main": "out/index.js", @@ -12,7 +12,7 @@ "spcl" ], "engines": { - "node": ">=18.4.0" + "node": ">=18.12.0" }, "bugs": { "url": "https://github.com/spcl/dace-webclient/issues" @@ -65,7 +65,7 @@ "typescript": "^5.3.3", "webpack": "^5.89.0", "webpack-cli": "^5.1.4", - "webpack-dev-server": "^4.15.1" + "webpack-dev-server": "^5.0" }, "dependencies": { "@babel/runtime": "^7.20.7", diff --git a/samples/embed-iframe.html b/samples/embed-iframe.html index b817beac..e54a5172 100644 --- a/samples/embed-iframe.html +++ b/samples/embed-iframe.html @@ -1,4 +1,4 @@ - + diff --git a/samples/embed-script.html b/samples/embed-script.html index d56a725f..47a5c335 100644 --- a/samples/embed-script.html +++ b/samples/embed-script.html @@ -1,4 +1,4 @@ - + diff --git a/src/index.ts b/src/index.ts index e73cde06..082bb6dd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { SDFGElement } from './renderer/renderer_elements'; @@ -32,7 +32,7 @@ export type SymbolMap = { [symbol: string]: number | undefined, }; -export type DagreSDFG = dagre.graphlib.Graph; +export type DagreGraph = dagre.graphlib.Graph; export type InvalidSDFGError = { message: string | undefined, @@ -43,40 +43,41 @@ export type InvalidSDFGError = { isedge_id: number | undefined, }; -export type JsonSDFGEdge = { +export interface JsonSDFGElement { attributes: any, + type: string, +} + +export interface JsonSDFGEdge extends JsonSDFGElement { dst: string, dst_connector: string | null, src: string, src_connector: string | null, - type: string, height: number, width: number, x?: number, y?: number, -}; +} -export interface JsonSDFGNode { - attributes: any, +export interface JsonSDFGNode extends JsonSDFGElement { id: number, label: string, scope_entry: string | null, scope_exit: string | null, - type: string, } -export interface JsonSDFGBlock { - attributes: any, +export interface JsonSDFGBlock extends JsonSDFGElement { collapsed: boolean, edges: JsonSDFGEdge[], nodes: (JsonSDFGBlock | JsonSDFGNode)[], id: number, label: string, - type: string, } -export interface JsonSDFGControlBlock extends JsonSDFGBlock { +export interface JsonSDFGControlFlowRegion extends JsonSDFGBlock { nodes: JsonSDFGBlock[], + start_block: number, + cfg_list_id: number, } export interface JsonSDFGState extends JsonSDFGBlock { @@ -84,15 +85,9 @@ export interface JsonSDFGState extends JsonSDFGBlock { nodes: JsonSDFGNode[], } -export type JsonSDFG = { - type: string, - start_block: number, - cfg_list_id: number, - attributes: any, - edges: any[], // TODO - nodes: any[], // TODO +export interface JsonSDFG extends JsonSDFGControlFlowRegion { error: InvalidSDFGError | undefined, -}; +} export type ModeButtons = { pan: HTMLElement | null, diff --git a/src/layouter/graphlib/algorithms/components.ts b/src/layouter/graphlib/algorithms/components.ts index a7f70bfd..c79d93fc 100644 --- a/src/layouter/graphlib/algorithms/components.ts +++ b/src/layouter/graphlib/algorithms/components.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { DiGraph } from '../di_graph'; export function* stronglyConnectedComponents( @@ -33,14 +35,15 @@ export function* stronglyConnectedComponents( lowlink.set(v, preorder.get(v)!); for (const w of g.neighborsIter(v)) { if (!sccFound.has(w)) { - if (preorder.get(w)! > preorder.get(v)!) + if (preorder.get(w)! > preorder.get(v)!) { lowlink.set(v, Math.min( lowlink.get(v)!, lowlink.get(w)! )); - else + } else { lowlink.set(v, Math.min( lowlink.get(v)!, preorder.get(w)! )); + } } } queue.pop(); diff --git a/src/layouter/graphlib/algorithms/cycles.ts b/src/layouter/graphlib/algorithms/cycles.ts index 8f645dc2..dc46bc70 100644 --- a/src/layouter/graphlib/algorithms/cycles.ts +++ b/src/layouter/graphlib/algorithms/cycles.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { DiGraph } from '../di_graph'; import { stronglyConnectedComponents } from './components'; @@ -34,7 +36,6 @@ export class NodeCycle { export function* simpleCycles( g: DiGraph ): Generator<[string[], [string, string][]]> { - function _unblock( thisnode: string, blocked: Set, B: Map> ): void { @@ -54,9 +55,10 @@ export function* simpleCycles( const subGraph = g.copy(); const sccs: Set[] = []; - for (const scc of stronglyConnectedComponents(subGraph)) + for (const scc of stronglyConnectedComponents(subGraph)) { if (scc.size > 1) sccs.push(scc); + } for (const node of subGraph.nodes()) { const selfEdge: [string, string] = [node, node]; @@ -79,7 +81,10 @@ export function* simpleCycles( blocked.add(startNode); const B = new Map>(); const stack: [string, string[]][] = [ - [startNode, sccGraph.neighbors(startNode)] + [ + startNode, + sccGraph.neighbors(startNode), + ], ]; while (stack.length > 0) { diff --git a/src/layouter/graphlib/algorithms/dominance.ts b/src/layouter/graphlib/algorithms/dominance.ts index d7c27ca6..c999800e 100644 --- a/src/layouter/graphlib/algorithms/dominance.ts +++ b/src/layouter/graphlib/algorithms/dominance.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { DiGraph } from '../di_graph'; import { dfsPostorderNodes } from './traversal'; diff --git a/src/layouter/graphlib/algorithms/traversal.ts b/src/layouter/graphlib/algorithms/traversal.ts index 72d26c1c..ad6d56be 100644 --- a/src/layouter/graphlib/algorithms/traversal.ts +++ b/src/layouter/graphlib/algorithms/traversal.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { DiGraph } from '../di_graph'; export function* dfsLabeledEdges( @@ -19,7 +21,11 @@ export function* dfsLabeledEdges( yield [start, start, 'forward']; visited.add(start); const stack: [string, number, string[]][] = [ - [start, depthLimit, graph.successors(start)] + [ + start, + depthLimit, + graph.successors(start), + ], ]; while (stack.length) { diff --git a/src/layouter/graphlib/di_graph.ts b/src/layouter/graphlib/di_graph.ts index a16b468b..0ed32ff5 100644 --- a/src/layouter/graphlib/di_graph.ts +++ b/src/layouter/graphlib/di_graph.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { Graph } from './graph'; export class DiGraph extends Graph { @@ -5,9 +7,7 @@ export class DiGraph extends Graph { private pred: Map> = new Map(); private succ: Map> = new Map(); - public constructor( - name: string = '', - ) { + public constructor(name: string = '') { super(name); } @@ -58,9 +58,10 @@ export class DiGraph extends Graph { } public* edgesIter(): Generator<[string, string]> { - for (const [u, neighbors] of this.succ) + for (const [u, neighbors] of this.succ) { for (const v of neighbors.keys()) yield [u, v]; + } } public hasEdge(u: string, v: string): boolean { @@ -71,9 +72,10 @@ export class DiGraph extends Graph { id: string, ignoreEdges: [string, string][] ): Generator { const ignoredTargets = new Set(); - for (const ie of ignoreEdges) - if (ie[0] == id) + for (const ie of ignoreEdges) { + if (ie[0] === id) ignoredTargets.add(ie[1]); + } for (const v of this.succ.get(id)?.keys() ?? []) { if (!ignoredTargets.has(v)) yield v; @@ -131,9 +133,10 @@ export class DiGraph extends Graph { } public* sourcesIter(): Generator { - for (const [id, neighbors] of this.pred) + for (const [id, neighbors] of this.pred) { if (neighbors.size === 0) yield id; + } } public sinks(): string[] { @@ -141,9 +144,10 @@ export class DiGraph extends Graph { } public* sinksIter(): Generator { - for (const [id, neighbors] of this.succ) + for (const [id, neighbors] of this.succ) { if (neighbors.size === 0) yield id; + } } public clear(): void { diff --git a/src/layouter/graphlib/graph.ts b/src/layouter/graphlib/graph.ts index f246cbbf..9215faa1 100644 --- a/src/layouter/graphlib/graph.ts +++ b/src/layouter/graphlib/graph.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + import { GraphI } from './graph_types'; export class Graph implements GraphI { @@ -6,7 +8,7 @@ export class Graph implements GraphI { protected adjacencyList: Map> = new Map(); public constructor( - public name: string = '', + public name: string = '' ) { return; } @@ -118,9 +120,10 @@ export class Graph implements GraphI { public* edgesIter(): Generator<[string, string]> { const taken = new Set<[string, string]>(); for (const [src, adj] of this.adjacencyList.entries()) { - for (const dst of adj.keys()) + for (const dst of adj.keys()) { if (!taken.has([dst, src]) && !taken.has([src, dst])) yield [src, dst]; + } } } @@ -136,11 +139,12 @@ export class Graph implements GraphI { public* adjListIter(): Generator { for (const [src, adj] of this.adjacencyList.entries()) { - if (adj.size) + if (adj.size) { for (const dst of adj) yield [src, dst[0]]; - else + } else { yield src; + } } } diff --git a/src/layouter/graphlib/graph_types.ts b/src/layouter/graphlib/graph_types.ts index 2c35ce84..4733c9b1 100644 --- a/src/layouter/graphlib/graph_types.ts +++ b/src/layouter/graphlib/graph_types.ts @@ -1,3 +1,5 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + export interface GraphI { get(id: string): NodeT | null; diff --git a/src/layouter/state_machine/sm_layouter.ts b/src/layouter/state_machine/sm_layouter.ts index 36e3c576..25fcd31a 100644 --- a/src/layouter/state_machine/sm_layouter.ts +++ b/src/layouter/state_machine/sm_layouter.ts @@ -1,4 +1,6 @@ -import { DagreSDFG } from '../..'; +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + +import { DagreGraph } from '../..'; import * as dagre from 'dagre'; import { allBackedges } from '../graphlib/algorithms/cycles'; import { @@ -7,6 +9,7 @@ import { } from '../graphlib/algorithms/dominance'; import { DiGraph } from '../graphlib/di_graph'; +/* eslint-disable @typescript-eslint/no-var-requires */ const dagreOrder = require('dagre/lib/order'); const ARTIFICIAL_START = '__smlayouter_artifical_start'; @@ -182,10 +185,10 @@ export class SMLayouter { * Perform state machine layout for an existing dagre.js layout graph. * This translates the dagre graph into a minimal DiGraph necessary for * performing the layout. - * @param {DagreSDFG} dagreGraph Dagre.js graph to perform layouting for. + * @param {DagreGraph} dagreGraph Dagre.js graph to perform layouting for. */ public static layoutDagreCompat( - dagreGraph: DagreSDFG, startState?: string + dagreGraph: DagreGraph, startState?: string ): void { const g = new DiGraph(); for (const stateId of dagreGraph.nodes()) @@ -220,7 +223,7 @@ export class SMLayouter { * Add a 'lane' to the left of the laid out graph where all back-edges * are routed upwards in the vertical layout. Ensures that the number * of crossings is reduced to a minimum. - * + * * Note: This operates in-place on the layout graph. * @see {@link SMLayouter.doRanking} * @see {@link SMLayouter.normalizeEdges} @@ -268,11 +271,12 @@ export class SMLayouter { if (!routedEdges.has(edgeData)) unrouted.add(edgeData); } - if (unrouted.size > 0) + if (unrouted.size > 0) { console.warn( 'The following edges were not routed:', unrouted ); + } } private propagate( @@ -312,9 +316,10 @@ export class SMLayouter { scopes.push([ScopeType.BRANCH, rank, mergeNodeRank]); } - for (const s of successors) + for (const s of successors) { if (s !== mergeNode) q.push([s, rank + 1]); + } } } @@ -323,12 +328,14 @@ export class SMLayouter { oNode: string ): void { let exitCandidates = new Set(); - for (const n of successors) + for (const n of successors) { if (n !== oNode && !this.allDom.get(n)?.has(oNode)) exitCandidates.add(n); - for (const n of this.graph.successorsIter(oNode)) + } + for (const n of this.graph.successorsIter(oNode)) { if (n !== node) exitCandidates.add(n); + } if (exitCandidates.size < 1) { throw new Error('No exit candidates found.'); @@ -405,11 +412,12 @@ export class SMLayouter { const successors: string[] = []; for (const s of this.graph.successorsIter(node)) { let foundAsBackedge = false; - for (const sBe of this.backedgesCombined) + for (const sBe of this.backedgesCombined) { if (sBe[1] === s && sBe[0] === node) { foundAsBackedge = true; break; } + } if (!foundAsBackedge) successors.push(s); } @@ -522,7 +530,7 @@ export class SMLayouter { // If the edge spans only one rank or is within the same rank, // nothing needs to be done. - if (srcRank === dstRank - 1 || srcRank == dstRank) + if (srcRank === dstRank - 1 || srcRank === dstRank) continue; // We also don't want to handle back edges here. diff --git a/src/local_view/elements/computation_node.ts b/src/local_view/elements/computation_node.ts index 2e0803b1..81a30668 100644 --- a/src/local_view/elements/computation_node.ts +++ b/src/local_view/elements/computation_node.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import CoffeeQuate from 'coffeequate'; import * as math from 'mathjs'; @@ -9,7 +9,7 @@ import { AccessMap, ConcreteDataAccess, DataContainer, - SymbolicDataAccess + SymbolicDataAccess, } from './data_container'; import { DEFAULT_LINE_STYLE, DEFAULT_TEXT_STYLE } from './element'; import { Node } from './node'; @@ -29,7 +29,7 @@ export class ComputationNode extends Node { public readonly accessOrder: SymbolicDataAccess[], public readonly farText: string | undefined = undefined, public drawBorder: boolean = true, - renderer?: LViewRenderer, + renderer?: LViewRenderer ) { super(parentGraph, id, renderer); @@ -100,12 +100,12 @@ export class ComputationNode extends Node { * For a given symbol scope, this method appends all data accesses to an * index map, which are related to accesses to the given source container * under that symbol scope. - * + * * For example: * - On a computation node calculating C[i, j] = A[i, j] + B[i, j]. * - Given A as the source container and a symbol scope of { i: 1, j: 3 }. * - Appends the accesses to C[1, 3] and B[1, 3] to the provided index map. - * + * * Unknown / undefined symbols under the provided scope are taken all the * way from their minium to their maximum value. In the example above, * if i is in [0:N] and j is in [0:M], if the provided scope is only @@ -135,13 +135,14 @@ export class ComputationNode extends Node { idx.push(res); } const prev = idxMap.get(access.dataContainer); - if (prev !== undefined) + if (prev !== undefined) { prev.push([access.accessMode, idx]); - else + } else { idxMap.set( access.dataContainer, [[access.accessMode, idx]] ); + } } } } @@ -181,11 +182,12 @@ export class ComputationNode extends Node { const variables = equation.getAllVariables(); if (variables.length === 1) { const solutions = equation.solve(variables[0]); - if (solutions.length === 1) + if (solutions.length === 1) { scope.set( variables[0], math.evaluate(solutions[0].toString()) ); + } } } }); diff --git a/src/local_view/elements/data_container.ts b/src/local_view/elements/data_container.ts index c6fec26e..530f8edd 100644 --- a/src/local_view/elements/data_container.ts +++ b/src/local_view/elements/data_container.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { StorageType } from '../../overlays/memory_location_overlay'; import { DataDimension } from './dimensions'; @@ -43,21 +43,20 @@ export class DataContainer { } else { const squaredDims = this.dim.slice(); if (squaredDims.length > 1) { - for (let i = squaredDims.length - 2; i >= 0; i--) + for (let i = squaredDims.length - 2; i >= 0; i--) { squaredDims[i] = new DataDimension( '(' + squaredDims[i].name + ')*(' + squaredDims[i + 1].name + ')', squaredDims[i].value * squaredDims[i + 1].value ); + } } if (squaredDims.length > 1) { this.strides = squaredDims.slice(1); this.strides.push(new DataDimension('1', 1)); } else { - this.strides = [ - new DataDimension('1', 1), - ]; + this.strides = [new DataDimension('1', 1)]; } } } diff --git a/src/local_view/elements/dimensions.ts b/src/local_view/elements/dimensions.ts index 50f213af..1ee7ee6b 100644 --- a/src/local_view/elements/dimensions.ts +++ b/src/local_view/elements/dimensions.ts @@ -1,10 +1,10 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. export class DataDimension { constructor( public readonly name: string, - public readonly value: number, + public readonly value: number ) { } diff --git a/src/local_view/elements/edge.ts b/src/local_view/elements/edge.ts index 8b441c49..b4f36ba2 100644 --- a/src/local_view/elements/edge.ts +++ b/src/local_view/elements/edge.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { LViewRenderer } from '../lview_renderer'; import { Element } from './element'; diff --git a/src/local_view/elements/element.ts b/src/local_view/elements/element.ts index 2636d9a7..291e0e44 100644 --- a/src/local_view/elements/element.ts +++ b/src/local_view/elements/element.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { Graphics, TextStyle } from 'pixi.js'; import { LViewRenderer } from '../lview_renderer'; diff --git a/src/local_view/elements/map_node.ts b/src/local_view/elements/map_node.ts index 7472b7ac..cd64f2b5 100644 --- a/src/local_view/elements/map_node.ts +++ b/src/local_view/elements/map_node.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { Polygon, Rectangle } from '@pixi/math'; import $ from 'jquery'; @@ -60,7 +60,7 @@ export class MapNode extends Node { public readonly innerGraph: Graph, private readonly overrideWidth?: number, private readonly overrideHeight?: number, - renderer?: LViewRenderer, + renderer?: LViewRenderer ) { super(parentGraph, id, renderer); @@ -91,11 +91,12 @@ export class MapNode extends Node { else this._width = this.innerGraph.width + (2 * this.nestingPadding); - if (this.overrideHeight !== undefined) + if (this.overrideHeight !== undefined) { this._height = this.overrideHeight; - else + } else { this._height = this.innerGraph.height + this.headerHeight + (2 * this.nestingPadding); + } // Construct the labels and sliders for each dimension. let maxLabelWidth = 0; @@ -120,7 +121,7 @@ export class MapNode extends Node { maxLabelWidth, this._width / this.ranges.length ); - + this._width = (this.labelWidth * this.ranges.length); } @@ -169,9 +170,12 @@ export class MapNode extends Node { const buttonRadius = this.buttonSize / 4; const playPolygon = new Polygon([ - this.buttonSize / 4, this.buttonSize / 4, - 3 * this.buttonSize / 4, this.buttonSize / 2, - this.buttonSize / 4, 3 * this.buttonSize / 4, + this.buttonSize / 4, + this.buttonSize / 4, + 3 * this.buttonSize / 4, + this.buttonSize / 2, + this.buttonSize / 4, + 3 * this.buttonSize / 4, ]); this.playButton = new Button( () => { @@ -249,19 +253,21 @@ export class MapNode extends Node { } public recalculateSize(): void { - if (this.overrideWidth !== undefined) + if (this.overrideWidth !== undefined) { this._width = this.overrideWidth; - else + } else { this._width = Math.max( this.labelWidth * this.ranges.length, this.innerGraph.width + 2 * this.nestingPadding ); + } - if (this.overrideHeight !== undefined) + if (this.overrideHeight !== undefined) { this._height = this.overrideHeight; - else + } else { this._height = this.innerGraph.height + this.headerHeight + 2 * this.nestingPadding; + } this.labelWidth = this._width / this.ranges.length; for (let i = 0; i < this.labels.length; i++) { @@ -296,12 +302,12 @@ export class MapNode extends Node { } const updateParameters = true; - const [accessMap, orderedAccesses] = this.innerGraph.getAccessesFor( + const accessMapRet = this.innerGraph.getAccessesFor( scope, updateParameters ); - + this.clearAccessMarkings(); - this.showAccesses(accessMap); + this.showAccesses(accessMapRet[0]); } private recursiveSimulate( @@ -320,10 +326,11 @@ export class MapNode extends Node { typeof(nRange.step) === 'string') return; - if (nRange.step === 0) + if (nRange.step === 0) { throw new LViewGraphParseError( 'This graph cannot be simulated due to a map step of 0' ); + } const cond = nRange.step > 0 ? (i: number) => i <= +nRange.end : (i: number) => i >= +nRange.end; for (let i = nRange.start; cond(i); i += nRange.step) { @@ -366,7 +373,7 @@ export class MapNode extends Node { if (cl && cl.length > 0) { const start = cl[0]; const distance = lineStack.touch(start); - + const tile = node.getTileAt(access.index as number[]); const prev = tile?.stackDistances.get(distance); @@ -382,14 +389,15 @@ export class MapNode extends Node { const mnPrev = MemoryNode.reuseDistanceHistogram.get(distance); - if (mnPrev !== undefined) + if (mnPrev !== undefined) { MemoryNode.reuseDistanceHistogram.set( distance, mnPrev + 1 ); - else + } else { MemoryNode.reuseDistanceHistogram.set( distance, 1 ); + } if (distance < 0 || distance >= distThreshold) { if (tile) { @@ -399,14 +407,15 @@ export class MapNode extends Node { ); if (missPrev !== undefined && missPrev >= 0) { - if (missPrev > 1) + if (missPrev > 1) { MemoryNode.missesHistogram.set( tile.totalMisses, missPrev - 1 ); - else + } else { MemoryNode.missesHistogram.delete( tile.totalMisses ); + } } tile.totalMisses++; @@ -414,14 +423,15 @@ export class MapNode extends Node { MemoryNode.missesHistogram.get( tile.totalMisses ); - if (nMissPrev !== undefined) + if (nMissPrev !== undefined) { MemoryNode.missesHistogram.set( tile.totalMisses, nMissPrev + 1 ); - else + } else { MemoryNode.missesHistogram.set( tile.totalMisses, 1 ); + } } } } @@ -552,16 +562,26 @@ export class MapNode extends Node { this.lineStyle(DEFAULT_LINE_STYLE); this.beginFill(0xffffff, 0.95); this.drawPolygon([ - 0, this.headerHeight, - 0, this.headerHeight / 2, - this.headerHeight / 2, 0, - this._width - (this.headerHeight / 2), 0, - this._width, this.headerHeight / 2, - this._width, this.headerHeight, - this._width, this._height, - 0, this._height, - 0, this.headerHeight, - this._width, this.headerHeight, + 0, + this.headerHeight, + 0, + this.headerHeight / 2, + this.headerHeight / 2, + 0, + this._width - (this.headerHeight / 2), + 0, + this._width, + this.headerHeight / 2, + this._width, + this.headerHeight, + this._width, + this._height, + 0, + this._height, + 0, + this.headerHeight, + this._width, + this.headerHeight, ]); this.endFill(); @@ -686,7 +706,7 @@ export class MapNode extends Node { vals.push(i); rangeValuesMap.push([range.itvar, vals]); } else { - let errMsg = `Failed to get accesses for the scope: {`; + let errMsg = 'Failed to get accesses for the scope: {'; let sep = ''; for (const [k, v] of scope) { errMsg += sep + k + ': ' + v.toString(); @@ -727,7 +747,7 @@ export class MapNode extends Node { } public getRelatedAccesses( - source: DataContainer, index: number[], origin?: Node + source: DataContainer, index: number[], _origin?: Node ): AccessMap<(number | undefined)[]> { return this.innerGraph.getRelatedAccesses(source, index); } @@ -740,21 +760,23 @@ export class MapNode extends Node { } public get unscaledWidth(): number { - if (this.overrideWidth) + if (this.overrideWidth) { return this.overrideWidth; - else + } else { return Math.max( this.labelWidth * this.ranges.length, this.innerGraph.width + 2 * this.nestingPadding ); + } } public get unscaledHeight(): number { - if (this.overrideHeight) + if (this.overrideHeight) { return this.overrideHeight; - else + } else { return this.innerGraph.height + this.headerHeight + 2 * this.nestingPadding; + } } } diff --git a/src/local_view/elements/memory_movement_edge.ts b/src/local_view/elements/memory_movement_edge.ts index 4edc7d1c..687de390 100644 --- a/src/local_view/elements/memory_movement_edge.ts +++ b/src/local_view/elements/memory_movement_edge.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import $ from 'jquery'; import { cos, sin, tanh } from 'mathjs'; @@ -26,7 +26,7 @@ export class MemoryMovementEdge extends Edge { public points: Point[], src: Node, dst: Node, - renderer?: LViewRenderer, + renderer?: LViewRenderer ) { super(src, dst, renderer); @@ -83,11 +83,10 @@ export class MemoryMovementEdge extends Edge { public calculateMovementVolume(): number { this._volume = 0; - if (this.src instanceof MemoryNode) { + if (this.src instanceof MemoryNode) this._volume = this.getVolumeFromMemNode(this.src); - } else if (this.dst instanceof MemoryNode) { + else if (this.dst instanceof MemoryNode) this._volume = this.getVolumeFromMemNode(this.dst); - } return this._volume; } @@ -119,10 +118,10 @@ export class MemoryMovementEdge extends Edge { const lastPoint = this.points.length ? this.points[this.points.length - 1] : this.dst.position; const theta = (lastPoint.x === secondToLastPoint.x) ? - 0 : 0 - tanh( - (secondToLastPoint.x - lastPoint.x) / - (secondToLastPoint.y - lastPoint.y) - ); + 0 : 0 - tanh( + (secondToLastPoint.x - lastPoint.x) / + (secondToLastPoint.y - lastPoint.y) + ); let color = 0x000000; let text: string | null = null; @@ -133,10 +132,11 @@ export class MemoryMovementEdge extends Edge { if (this.physMovementOverlayActive) { let badness = 0; if (this.renderer) { - const keys = [ - ...this.renderer.globalMemoryMovementHistogram.keys() - ]; - keys.sort((a, b) => { return a - b; }); + const keys = + [...this.renderer.globalMemoryMovementHistogram.keys()]; + keys.sort((a, b) => { + return a - b; + }); const idx = keys.indexOf(this._volume); @@ -227,15 +227,19 @@ export class MemoryMovementEdge extends Edge { this.lineStyle({ color: color, }).beginFill(color).drawPolygon([ - lastPoint.x - (lineWidth / 2), lastPoint.y, - arrowTopLeft.x, arrowTopLeft.y, - arrowTopRight.x, arrowTopRight.y, - lastPoint.x + (lineWidth / 2), lastPoint.y, + lastPoint.x - (lineWidth / 2), + lastPoint.y, + arrowTopLeft.x, + arrowTopLeft.y, + arrowTopRight.x, + arrowTopRight.y, + lastPoint.x + (lineWidth / 2), + lastPoint.y, ]); let textX; let textY; - if (this.points.length == 2) { + if (this.points.length === 2) { textX = (this.points[0].x + this.points[1].x) / 2; textY = (this.points[0].y + this.points[1].y) / 2; } else if (this.points.length) { diff --git a/src/local_view/elements/memory_node.ts b/src/local_view/elements/memory_node.ts index 93b32397..b4280a13 100644 --- a/src/local_view/elements/memory_node.ts +++ b/src/local_view/elements/memory_node.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { Rectangle } from '@pixi/math'; import $ from 'jquery'; @@ -49,7 +49,7 @@ class MemoryTile extends Graphics { public readonly elementY: number, public readonly elementWidth: number, public readonly elementHeight: number, - public readonly index: number[], + public readonly index: number[] ) { super(); @@ -106,12 +106,13 @@ class MemoryTile extends Graphics { ); neighborAccesses.forEach((accesses, container) => { const containerAccesses = relatedAccesses.get(container); - if (containerAccesses) + if (containerAccesses) { relatedAccesses.set(container, containerAccesses.concat( accesses )); - else + } else { relatedAccesses.set(container, accesses); + } }); } } @@ -123,16 +124,17 @@ class MemoryTile extends Graphics { accesses.forEach((access) => { nodes.forEach(node => { const tiles: MemoryTile[] = []; - if (asAccess) + if (asAccess) { node[1].applyToIdx( access[1], (t) => t.onMarkAccess(), undefined, undefined, tiles ); - else + } else { node[1].applyToIdx( access[1], (t) => t.onMarkRelated(), undefined, undefined, tiles ); + } tiles.forEach(tile => { if (asAccess) this.accessMarkedTiles.add(tile); @@ -165,7 +167,8 @@ class MemoryTile extends Graphics { (t: MemoryTile) => { if (!t.borderMarkingColors.includes(color)) t.borderMarkingColors.push(color); - }); + } + ); }); if (!redrawNodes.includes(node)) @@ -201,12 +204,14 @@ class MemoryTile extends Graphics { const coldMisses = this.stackDistances.get(-1); const newData = { labels: [...allVals, 'Cold'], - datasets: [{ - label: this.memoryNode.dataContainer.name + - '[' + this.index.toString() + ']', - backgroundColor: '#00538A', - data: [...data, coldMisses === undefined ? 0 : coldMisses], - }], + datasets: [ + { + label: this.memoryNode.dataContainer.name + + '[' + this.index.toString() + ']', + backgroundColor: '#00538A', + data: [...data, coldMisses === undefined ? 0 : coldMisses], + }, + ], }; this.memoryNode.renderer?.showReuseDistanceHist(newData); @@ -245,7 +250,7 @@ class MemoryTile extends Graphics { this.draw(); } - public onMouseOver(mouseEvent: InteractionEvent): void { + public onMouseOver(_mouseEvent: InteractionEvent): void { if (this.stackedAccesses > 0) { const globalPos = this.toGlobal({ x: this.elementX, @@ -312,12 +317,13 @@ class MemoryTile extends Graphics { if (this.stackedAccesses > 0) { const prev = MemoryNode.accessHistogram.get(this.stackedAccesses); if (prev !== undefined) { - if (prev <= 1) + if (prev <= 1) { MemoryNode.accessHistogram.delete(this.stackedAccesses); - else + } else { MemoryNode.accessHistogram.set( this.stackedAccesses, prev - 1 ); + } } } } @@ -407,7 +413,9 @@ class MemoryTile extends Graphics { this.beginFill(0xA0A0FF); } else if (this.stackedAccesses > 0) { const keys = [...MemoryNode.accessHistogram.keys()]; - keys.sort((a, b) => { return a - b; }); + keys.sort((a, b) => { + return a - b; + }); const idx = keys.indexOf(this.stackedAccesses); let badness = 0; if (idx < 0) @@ -443,15 +451,11 @@ class MemoryTile extends Graphics { switch (this.memoryNode.reuseDistanceMetric) { case 'max': v = max(this.stackDistancesFlattened); - keys = [ - ...MemoryNode.maxReuseDistanceHistogram.keys() - ]; + keys = [...MemoryNode.maxReuseDistanceHistogram.keys()]; break; case 'min': v = min(this.stackDistancesFlattened); - keys = [ - ...MemoryNode.minReuseDistanceHistogram.keys() - ]; + keys = [...MemoryNode.minReuseDistanceHistogram.keys()]; break; case 'misses': v = this.totalMisses; @@ -460,13 +464,13 @@ class MemoryTile extends Graphics { case 'median': default: v = median(this.stackDistancesFlattened); - keys = [ - ...MemoryNode.reuseDistanceHistogram.keys() - ]; + keys = [...MemoryNode.reuseDistanceHistogram.keys()]; break; } - keys.sort((a, b) => { return a - b; }); + keys.sort((a, b) => { + return a - b; + }); let idx = -1; for (let i = 0; i < keys.length; i++) { const key = keys[i]; @@ -499,7 +503,7 @@ class MemoryTile extends Graphics { this.tint = 0xCCCCCC; else this.tint = 0xFFFFFF; - + this.drawRect( this.elementX, this.elementY, this.elementWidth, this.elementHeight @@ -547,7 +551,7 @@ export class MemoryNode extends Node { renderer?: LViewRenderer ) { super(parentGraph, id, renderer); - + this._unscaledWidth = this.calcUnscaledWidthRecursive( this.dataContainer.dim.slice() ); @@ -582,53 +586,57 @@ export class MemoryNode extends Node { } private calcUnscaledWidthRecursive(dims: DataDimension[]): number { - if (dims.length === 1) + if (dims.length === 1) { return dims[0].value * ( this.tileSizeOverride !== undefined ? this.tileSizeOverride : TILE_SIZE ); - else if (dims.length === 2) + } else if (dims.length === 2) { return dims[1].value * ( this.tileSizeOverride !== undefined ? this.tileSizeOverride : TILE_SIZE ); - else if (dims.length % 2 === 0) + } else if (dims.length % 2 === 0) { return INTERNAL_PADDING + this.calcUnscaledWidthRecursive( dims.slice(1) ); - else + } else { return dims[0].value * ( INTERNAL_PADDING + this.calcUnscaledWidthRecursive( dims.slice(1) ) ); + } } private calcUnscaledHeightRecursive(dims: DataDimension[]): number { - if (dims.length === 1) + if (dims.length === 1) { return ( this.tileSizeOverride !== undefined ? this.tileSizeOverride : TILE_SIZE ); - else if (dims.length === 2) + } else if (dims.length === 2) { return dims[0].value * ( this.tileSizeOverride !== undefined ? this.tileSizeOverride : TILE_SIZE ); - else if (dims.length % 2 !== 0) + } else if (dims.length % 2 !== 0) { return INTERNAL_PADDING + this.calcUnscaledHeightRecursive( dims.slice(1) ); - else + } else { return dims[0].value * ( INTERNAL_PADDING + this.calcUnscaledHeightRecursive( dims.slice(1) ) ); + } } public clearAllAccesses(): void { - this.applyToAll(this.tiles, tile => { tile.onClearAccesses(); }); + this.applyToAll(this.tiles, tile => { + tile.onClearAccesses(); + }); } public getTilingRegionsForIdx(idx: number[]): [ @@ -702,12 +710,11 @@ export class MemoryNode extends Node { else if (typeof(lineBytesRaw) === 'string') lineBytes = parseInt(lineBytesRaw); } - + if (lineBytes !== undefined && lineBytes > 0 && idx.length === this.dataContainer.strides.length) { - let flatIdx = this.dataContainer.startOffset; - + for (let i = 0; i < idx.length; i++) flatIdx += idx[i] * this.dataContainer.strides[i].value; @@ -734,9 +741,9 @@ export class MemoryNode extends Node { for (let j = 0; j < this.dataContainer.strides.length; j++) { const stride = this.dataContainer.strides[j]; const dimIdx = Math.floor(remIdx / stride.value); - + remIdx = remIdx % stride.value; - + if (dimIdx >= this.dataContainer.dim[j].value) { invalid = true; break; @@ -744,7 +751,7 @@ export class MemoryNode extends Node { reconstructedIdx.push(dimIdx); } - + if (!invalid) { const targetTile = this.getTileAt(reconstructedIdx); if (targetTile) @@ -823,7 +830,7 @@ export class MemoryNode extends Node { ): void { const index = idx[i]; - if (index !== undefined && typeof index === 'number'){ + if (index !== undefined && typeof index === 'number') { if (index < 0 || index >= pivot.length) return; @@ -838,10 +845,11 @@ export class MemoryNode extends Node { } else { if (i < idx.length - 1) { pivot.forEach(el => { - if (el.descendants) + if (el.descendants) { this.applyToIdx( idx, fun, i + 1, el.descendants, targets ); + } }); } else { pivot.forEach(el => { @@ -898,7 +906,9 @@ export class MemoryNode extends Node { } public clearStackDistances(): void { - this.applyToAll(this.tiles, tile => { tile.stackDistances.clear(); }); + this.applyToAll(this.tiles, tile => { + tile.stackDistances.clear(); + }); } public getTotalCacheMisses(): number { diff --git a/src/local_view/elements/node.ts b/src/local_view/elements/node.ts index 301cc291..d51a5543 100644 --- a/src/local_view/elements/node.ts +++ b/src/local_view/elements/node.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { Graph } from '../graph/graph'; import { LViewRenderer } from '../lview_renderer'; diff --git a/src/local_view/graph/graph.ts b/src/local_view/graph/graph.ts index dc50f305..e2eb92e0 100644 --- a/src/local_view/graph/graph.ts +++ b/src/local_view/graph/graph.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { DisplayObject, Graphics } from 'pixi.js'; import { StorageType } from '../../overlays/memory_location_overlay'; @@ -8,7 +8,7 @@ import { AccessMode, ConcreteDataAccess, DataContainer, - SymbolicDataAccess + SymbolicDataAccess, } from '../elements/data_container'; import { Edge } from '../elements/edge'; import { Element } from '../elements/element'; @@ -178,7 +178,7 @@ export class Graph extends Graphics { index: number[] ): AccessMap<(number | undefined)[]> { const idxMap = new AccessMap<(number | undefined)[]>(); - + for (const child of this.children) { if (child instanceof MapNode || child instanceof ComputationNode) { const childMap = child.getRelatedAccesses(source, index); @@ -206,10 +206,11 @@ export class Graph extends Graphics { children.forEach(child => { if (child instanceof Node) { this.nodes.add(child); - if (child instanceof MemoryNode) + if (child instanceof MemoryNode) { this.registerMemoryNode( child.dataContainer, child, child.accessMode ); + } } else if (child instanceof Edge) { this.edges.add(child); } @@ -339,15 +340,17 @@ export class Graph extends Graphics { } public *inEdges(node: Node): Generator { - for (const edge of this.edges) + for (const edge of this.edges) { if (edge.dst === node && edge.src !== node) yield edge; + } } public *outEdges(node: Node): Generator { - for (const edge of this.edges) + for (const edge of this.edges) { if (edge.src === node && edge.dst !== node) yield edge; + } } public *neighborEdges(node: Node): Generator { diff --git a/src/local_view/gui/button.ts b/src/local_view/gui/button.ts index 99bd2b0b..8e49cbb0 100644 --- a/src/local_view/gui/button.ts +++ b/src/local_view/gui/button.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { IShape, RoundedRectangle } from '@pixi/math'; import { Graphics, Text } from 'pixi.js'; @@ -19,7 +19,7 @@ export class Button extends GUIComponent { w?: number, h?: number, private readonly radius: number = 0, - fontSize: number = 30, + fontSize: number = 30 ) { super(); @@ -41,11 +41,12 @@ export class Button extends GUIComponent { } else { this.labelGraphic = new Graphics(); - if (w === undefined || h === undefined) + if (w === undefined || h === undefined) { throw new Error( 'When using a graphical label, both height and width ' + 'need to be provided!' ); + } } this.addChild(this.labelGraphic); diff --git a/src/local_view/gui/gui_component.ts b/src/local_view/gui/gui_component.ts index 3bf3d4e4..110c0a85 100644 --- a/src/local_view/gui/gui_component.ts +++ b/src/local_view/gui/gui_component.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { Graphics } from 'pixi.js'; diff --git a/src/local_view/gui/slider.ts b/src/local_view/gui/slider.ts index a4514900..d5c8d3c7 100644 --- a/src/local_view/gui/slider.ts +++ b/src/local_view/gui/slider.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { Graphics, Text } from 'pixi.js'; import { GUIComponent } from './gui_component'; @@ -30,7 +30,7 @@ export class Slider extends GUIComponent { private readonly lineThickness: number = 2, private readonly lineColor: number = 0x000000, private readonly pommelRadius: number = 6, - private readonly pommelColor: number = 0x444444, + private readonly pommelColor: number = 0x444444 ) { super(); @@ -78,7 +78,7 @@ export class Slider extends GUIComponent { const xOffset = targetX - this.minPommelX; const nValOffset = Math.floor(xOffset / this.lineSegmentLength); const nVal = this.min + nValOffset; - if (this.val != nVal && nVal % this.step === 0) { + if (this.val !== nVal && nVal % this.step === 0) { this.val = nVal; this.valText.text = nVal.toString(); if (this.valueChangedHandler !== null) diff --git a/src/local_view/lview_layouter.ts b/src/local_view/lview_layouter.ts index 632db9db..015b0cab 100644 --- a/src/local_view/lview_layouter.ts +++ b/src/local_view/lview_layouter.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import dagre from 'dagre'; import { Edge } from './elements/edge'; @@ -15,7 +15,9 @@ export class LViewLayouter { g.setGraph({ ranksep: 100, }); - g.setDefaultEdgeLabel(() => { return {}; }); + g.setDefaultEdgeLabel(() => { + return {}; + }); graph.nodes.forEach((node: Node) => { if (node instanceof MapNode) { diff --git a/src/local_view/lview_parser.ts b/src/local_view/lview_parser.ts index 88026adf..0f156018 100644 --- a/src/local_view/lview_parser.ts +++ b/src/local_view/lview_parser.ts @@ -1,7 +1,7 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import $ from 'jquery'; -import { DagreSDFG, JsonSDFG } from '..'; +import { DagreGraph, JsonSDFG } from '..'; import { AccessNode, Edge, @@ -12,7 +12,7 @@ import { State, Tasklet, } from '../renderer/renderer_elements'; -import { sdfg_property_to_string, sdfg_range_elem_to_string } from '../utils/sdfg/display'; +import { sdfg_property_to_string } from '../utils/sdfg/display'; import { AccessMode, DataContainer, @@ -45,7 +45,7 @@ export class LViewParser { } private static parseMap( - elem: MapEntry, graph: Graph, state: State, sdfg: DagreSDFG, + elem: MapEntry, graph: Graph, state: State, sdfg: DagreGraph, symbolMap: Map, renderer?: LViewRenderer ): MapNode { const rRanges = elem.data.node.attributes.range.ranges; @@ -57,7 +57,7 @@ export class LViewParser { const start = this.parseSymbolic(rng.start, symbolMap); const end = this.parseSymbolic(rng.end, symbolMap); const step = this.parseSymbolic(rng.step, symbolMap); - + ranges.push({ itvar: rParams[i], start: start, @@ -65,7 +65,7 @@ export class LViewParser { step: step, }); } - + const innerGraph = new Graph(renderer); const mapScopeDict = state.data.state.scope_dict[elem.id]; if (mapScopeDict) { @@ -160,7 +160,7 @@ export class LViewParser { sdfgContainer.attributes.start_offset ?? 0, sdfgContainer.attributes.alignment ?? 0, storageType?.type, - strides, + strides ); graph.dataContainers.set(name, container); } else if (container.storage === undefined) { @@ -204,7 +204,9 @@ export class LViewParser { ); const ranges = attributes.other_subset ? attributes.other_subset.ranges : attributes.subset?.ranges; - const volume = this.parseSymbolic(attributes.num_accesses ?? 0, symbolMap); + const volume = this.parseSymbolic( + attributes.num_accesses ?? 0, symbolMap + ); if (dataContainer && ranges) { if (volume === 1) { const accessIdx = []; @@ -226,7 +228,7 @@ export class LViewParser { } private static parseTasklet( - graph: Graph, el: Tasklet, state: State, sdfg: DagreSDFG, + graph: Graph, el: Tasklet, state: State, sdfg: DagreGraph, symbolMap: Map, renderer?: LViewRenderer ): ComputationNode { const label = el.attributes().code?.string_data; @@ -264,7 +266,7 @@ export class LViewParser { private static parseEdge( graph: Graph, el: { name: string, v: string, w: string }, state: State, - sdfg: DagreSDFG, symbolMap: Map, + sdfg: DagreGraph, symbolMap: Map, renderer?: LViewRenderer ): Element | null { let src: SDFGNode = state.data.graph.node(el.v); @@ -287,33 +289,34 @@ export class LViewParser { edge.data.attributes.lview_edge = elem; return elem; } - + return null; } private static parseElement( - graph: Graph, el: SDFGElement, state: State, sdfg: DagreSDFG, + graph: Graph, el: SDFGElement, state: State, sdfg: DagreGraph, symbolMap: Map, renderer?: LViewRenderer ): Element | null { if (el instanceof SDFGNode) { - if (el instanceof AccessNode) + if (el instanceof AccessNode) { return this.parseAccessNode( el, graph, state, symbolMap, renderer ); - else if (el instanceof MapEntry) + } else if (el instanceof MapEntry) { return this.parseMap( el, graph, state, sdfg, symbolMap, renderer ); - else if (el instanceof Tasklet) + } else if (el instanceof Tasklet) { return this.parseTasklet( graph, el, state, sdfg, symbolMap, renderer ); + } } return null; } private static parseState( - state: State, sdfg: DagreSDFG, symbolMap: Map, + state: State, sdfg: DagreGraph, symbolMap: Map, renderer?: LViewRenderer ): Graph { const graph = new Graph(renderer); @@ -446,7 +449,7 @@ export class LViewParser { } public static async parseGraph( - sdfg: DagreSDFG, renderer?: LViewRenderer + sdfg: DagreGraph, renderer?: LViewRenderer ): Promise { const state = sdfg.node('0'); if (state) { diff --git a/src/local_view/lview_renderer.ts b/src/local_view/lview_renderer.ts index 1652f144..0f7de4fd 100644 --- a/src/local_view/lview_renderer.ts +++ b/src/local_view/lview_renderer.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { BarController, @@ -8,7 +8,7 @@ import { ChartData, Legend, LinearScale, - Tooltip + Tooltip, } from 'chart.js'; import annotationPlugin from 'chartjs-plugin-annotation'; import $ from 'jquery'; @@ -21,7 +21,12 @@ import { MemoryMovementEdge } from './elements/memory_movement_edge'; import { MemoryNode } from './elements/memory_node'; import { Graph } from './graph/graph'; import { AccessPatternOverlay } from './overlays/access_pattern_overlay'; -import { EdgeOverlay, NodeOverlay, NoEdgeOverlay, NoNodeOverlay } from './overlays/base_overlays'; +import { + EdgeOverlay, + NodeOverlay, + NoEdgeOverlay, + NoNodeOverlay, +} from './overlays/base_overlays'; import { CacheLineOverlay } from './overlays/cache_line_overlay'; import { PhysicalMovementOverlay } from './overlays/physical_movement_overlay'; import { ReuseDistanceOverlay } from './overlays/reuse_distance_overlay'; @@ -55,7 +60,7 @@ export class LViewRenderer { public constructor( protected sdfvInstance: SDFV, protected container: HTMLElement, - protected _graph?: Graph, + protected _graph?: Graph ) { this.initLocalViewSidebar(); @@ -194,7 +199,7 @@ export class LViewRenderer { inst.displayName, inst.value, cls === NoNodeOverlay, cls === NoNodeOverlay ); - if (cls == NoNodeOverlay) { + if (cls === NoNodeOverlay) { this.nOverlay = inst; inst.onSelect(); } @@ -212,7 +217,7 @@ export class LViewRenderer { inst.displayName, inst.value, cls === NoEdgeOverlay, cls === NoEdgeOverlay ); - if (cls == NoEdgeOverlay) { + if (cls === NoEdgeOverlay) { this.eOverlay = inst; inst.onSelect(); } @@ -429,15 +434,16 @@ export class LViewRenderer { }); g.nodes.forEach(node => { - if (node instanceof MemoryNode) + if (node instanceof MemoryNode) { node.applyToAll(undefined, t => { t.stackDistancesFlattened = []; t.stackDistances.clear(); t.coldMisses = 0; t.totalMisses = 0; }); - else if (node instanceof MapNode) + } else if (node instanceof MapNode) { this.graphClearCalculatedValue(node.innerGraph); + } }); } diff --git a/src/local_view/overlays/access_pattern_overlay.ts b/src/local_view/overlays/access_pattern_overlay.ts index b2251a00..74f78630 100644 --- a/src/local_view/overlays/access_pattern_overlay.ts +++ b/src/local_view/overlays/access_pattern_overlay.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import $ from 'jquery'; import { NodeOverlay } from './base_overlays'; diff --git a/src/local_view/overlays/base_overlays.ts b/src/local_view/overlays/base_overlays.ts index c1ae4fe2..848a662b 100644 --- a/src/local_view/overlays/base_overlays.ts +++ b/src/local_view/overlays/base_overlays.ts @@ -1,11 +1,11 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { LViewRenderer } from '../lview_renderer'; export abstract class BaseOverlay { public constructor( - public readonly renderer: LViewRenderer, + public readonly renderer: LViewRenderer ) { } diff --git a/src/local_view/overlays/cache_line_overlay.ts b/src/local_view/overlays/cache_line_overlay.ts index 92fe3db2..c422465e 100644 --- a/src/local_view/overlays/cache_line_overlay.ts +++ b/src/local_view/overlays/cache_line_overlay.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { NodeOverlay } from './base_overlays'; diff --git a/src/local_view/overlays/physical_movement_overlay.ts b/src/local_view/overlays/physical_movement_overlay.ts index 45299006..f38fe798 100644 --- a/src/local_view/overlays/physical_movement_overlay.ts +++ b/src/local_view/overlays/physical_movement_overlay.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { EdgeOverlay } from './base_overlays'; diff --git a/src/local_view/overlays/reuse_distance_overlay.ts b/src/local_view/overlays/reuse_distance_overlay.ts index 04c0955b..9042f049 100644 --- a/src/local_view/overlays/reuse_distance_overlay.ts +++ b/src/local_view/overlays/reuse_distance_overlay.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import $ from 'jquery'; import { NodeOverlay } from './base_overlays'; diff --git a/src/overlay_manager.ts b/src/overlay_manager.ts index eb9b6934..2891552b 100644 --- a/src/overlay_manager.ts +++ b/src/overlay_manager.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { MathNode, parse, SymbolNode } from 'mathjs'; import { Point2D, SymbolMap } from './index'; @@ -23,12 +23,14 @@ export class SymbolResolver { Object.keys(this.sdfg.attributes.symbols ?? []).forEach((s) => { if (this.sdfg.attributes.constants_prop !== undefined && Object.keys(this.sdfg.attributes.constants_prop).includes(s) && - this.sdfg.attributes.constants_prop[s][0]['type'] === 'Scalar') + this.sdfg.attributes.constants_prop[s][0]['type'] === + 'Scalar') { this.symbol_value_map[s] = this.sdfg.attributes.constants_prop[ s ][1]; - else + } else { this.symbol_value_map[s] = undefined; + } }); this.init_overlay_popup_dialogue(); diff --git a/src/overlays/avg_parallelism_overlay.ts b/src/overlays/avg_parallelism_overlay.ts index 231e9f75..84b95567 100644 --- a/src/overlays/avg_parallelism_overlay.ts +++ b/src/overlays/avg_parallelism_overlay.ts @@ -1,15 +1,24 @@ -// Copyright 2019-2023 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { DagreSDFG, Point2D, SimpleRect, SymbolMap } from '../index'; +import { + DagreGraph, + Point2D, + SimpleRect, + SymbolMap, + getGraphElementUUID, +} from '../index'; import { SDFGRenderer } from '../renderer/renderer'; import { + ControlFlowBlock, + ControlFlowRegion, Edge, NestedSDFG, SDFGElement, - SDFGNode + SDFGNode, + State, } from '../renderer/renderer_elements'; import { SDFV } from '../sdfv'; -import { getTempColorHslString, get_element_uuid } from '../utils/utils'; +import { getTempColorHslString } from '../utils/utils'; import { GenericSdfgOverlay, OverlayType } from './generic_sdfg_overlay'; export class AvgParallelismOverlay extends GenericSdfgOverlay { @@ -28,9 +37,7 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { } public clear_cached_avg_parallelism_values(): void { - this.renderer.for_all_elements(0, 0, 0, 0, ( - _type: string, _e: Event, obj: any - ) => { + this.renderer.doForAllGraphElements((_group, _info, obj) => { if (obj.data) { if (obj.data.avg_parallelism !== undefined) obj.data.avg_parallelism = undefined; @@ -43,13 +50,16 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { public calculate_avg_parallelism_node( node: SDFGNode, symbol_map: SymbolMap, avg_parallelism_values: number[] ): number | undefined { - const avg_parallelism_string = this.avg_parallelism_map[get_element_uuid(node)]; + const avg_parallelism_string = this.avg_parallelism_map[ + getGraphElementUUID(node) + ]; let avg_parallelism = undefined; - if (avg_parallelism_string !== undefined) - avg_parallelism = this.symbol_resolver.parse_symbol_expression( + if (avg_parallelism_string !== undefined) { + avg_parallelism = this.symbolResolver.parse_symbol_expression( avg_parallelism_string, symbol_map ); + } node.data.avg_parallelism_string = avg_parallelism_string; node.data.avg_parallelism = avg_parallelism; @@ -61,11 +71,13 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { } public calculate_avg_parallelism_graph( - g: DagreSDFG, symbol_map: SymbolMap, avg_parallelism_values: number[] + g: DagreGraph, symbol_map: SymbolMap, avg_parallelism_values: number[] ): void { g.nodes().forEach(v => { const state = g.node(v); - this.calculate_avg_parallelism_node(state, symbol_map, avg_parallelism_values); + this.calculate_avg_parallelism_node( + state, symbol_map, avg_parallelism_values + ); const state_graph = state.data.graph; if (state_graph) { state_graph.nodes().forEach((v: string) => { @@ -78,7 +90,7 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { // based on the mapping described on the node. Object.keys(mapping).forEach((symbol: string) => { nested_symbols_map[symbol] = - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( mapping[symbol], symbol_map ); @@ -111,14 +123,14 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { }); } - public recalculate_avg_parallelism_values(graph: DagreSDFG): void { + public recalculateAvgParallelismValues(graph: DagreGraph): void { this.heatmap_scale_center = 5; this.heatmap_hist_buckets = []; const avg_parallelism_values: number[] = []; this.calculate_avg_parallelism_graph( graph, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), avg_parallelism_values ); @@ -128,7 +140,9 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { avg_parallelism_values.push(0); } - public update_avg_parallelism_map(avg_parallelism_map: { [uuids: string]: any }): void { + public update_avg_parallelism_map( + avg_parallelism_map: { [uuids: string]: any } + ): void { this.avg_parallelism_map = avg_parallelism_map; this.refresh(); } @@ -137,40 +151,46 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { this.clear_cached_avg_parallelism_values(); const graph = this.renderer.get_graph(); if (graph) - this.recalculate_avg_parallelism_values(graph); + this.recalculateAvgParallelismValues(graph); this.renderer.draw_async(); } - public shade_node(node: SDFGNode, ctx: CanvasRenderingContext2D): void { - const avg_parallelism = node.data.avg_parallelism; - const avg_parallelism_string = node.data.avg_parallelism_string; + public shadeNode(node: SDFGNode, ctx: CanvasRenderingContext2D): void { + const avgParallelism = node.data.avg_parallelism; + const avgParallelismString = node.data.avg_parallelism_string; const mousepos = this.renderer.get_mousepos(); - if (avg_parallelism_string !== undefined && mousepos && + if (avgParallelismString !== undefined && mousepos && node.intersect(mousepos.x, mousepos.y)) { // Show the computed avg_parallelism value if applicable. - if (isNaN(avg_parallelism_string) && avg_parallelism !== undefined) + if (isNaN(avgParallelismString) && + avgParallelism !== undefined) { this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); - if (tt_cont) + if (tt_cont) { tt_cont.innerText = ( - 'Average Parallelism: ' + avg_parallelism_string + ' (' + avg_parallelism + ')' + 'Average Parallelism: ' + avgParallelismString + + ' (' + avgParallelism + ')' ); + } }); - else + } else { this.renderer.set_tooltip(() => { - const tt_cont = this.renderer.get_tooltip_container(); - if (tt_cont) - tt_cont.innerText = 'Average Parallelism: ' + avg_parallelism_string; + const ttCont = this.renderer.get_tooltip_container(); + if (ttCont) { + ttCont.innerText = 'Average Parallelism: ' + + avgParallelismString; + } }); + } } - if (avg_parallelism === undefined) { - // If the avg_parallelism can't be calculated, but there's an entry for this - // node's avg_parallelism, that means that there's an unresolved symbol. Shade - // the node grey to indicate that. - if (avg_parallelism_string !== undefined) { + if (avgParallelism === undefined) { + // If the avg_parallelism can't be calculated, but there's an entry + // for this node's avg_parallelism, that means that there's an + // unresolved symbol. Shade the node grey to indicate that. + if (avgParallelismString !== undefined) { node.shade(this.renderer, ctx, 'gray'); return; } else { @@ -179,66 +199,72 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { } // Only draw positive avg_parallelism. - if (avg_parallelism <= 0) + if (avgParallelism <= 0) return; // Calculate the severity color. - const color = getTempColorHslString(1 - this.get_severity_value(avg_parallelism)); + const color = getTempColorHslString( + 1 - this.getSeverityValue(avgParallelism) + ); node.shade(this.renderer, ctx, color); } - public recursively_shade_sdfg( - graph: DagreSDFG, + public recursivelyShadeCFG( + graph: DagreGraph, ctx: CanvasRenderingContext2D, ppp: number, - visible_rect: SimpleRect + visibleRect: SimpleRect ): void { // First go over visible states, skipping invisible ones. We only draw // something if the state is collapsed or we're zoomed out far enough. - // In that case, we draw the avg_parallelism calculated for the entire state. - // If it's expanded or zoomed in close enough, we traverse inside. + // In that case, we draw the avg_parallelism calculated for the entire + // state. If expanded or zoomed in close enough, we traverse inside. graph.nodes().forEach(v => { - const state = graph.node(v); + const block: ControlFlowBlock = graph.node(v); // If the node's invisible, we skip it. - if ((ctx as any).lod && !state.intersect( - visible_rect.x, visible_rect.y, - visible_rect.w, visible_rect.h + if ((ctx as any).lod && !block.intersect( + visibleRect.x, visibleRect.y, + visibleRect.w, visibleRect.h )) return; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - state.width / ppp <= SDFV.STATE_LOD)) || - state.data.state.attributes.is_collapsed) { - this.shade_node(state, ctx); - } else { - const state_graph = state.data.graph; - if (state_graph) { - state_graph.nodes().forEach((v: any) => { - const node = state_graph.node(v); + block.width / ppp <= SDFV.STATE_LOD)) || + block.attributes()?.is_collapsed) { + this.shadeNode(block, ctx); + } else if (block instanceof State) { + const stateGraph = block.data.graph; + if (stateGraph) { + stateGraph.nodes().forEach((v: any) => { + const node = stateGraph.node(v); // Skip the node if it's not visible. - if ((ctx as any).lod && !node.intersect(visible_rect.x, - visible_rect.y, visible_rect.w, visible_rect.h)) + if ((ctx as any).lod && !node.intersect(visibleRect.x, + visibleRect.y, visibleRect.w, visibleRect.h)) return; if (node.data.node.attributes.is_collapsed || ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) { - this.shade_node(node, ctx); + this.shadeNode(node, ctx); } else { if (node instanceof NestedSDFG && node.attributes().sdfg && node.attributes().sdfg.type !== 'SDFGShell') { - this.recursively_shade_sdfg( - node.data.graph, ctx, ppp, visible_rect + this.recursivelyShadeCFG( + node.data.graph, ctx, ppp, visibleRect ); } else { - this.shade_node(node, ctx); + this.shadeNode(node, ctx); } } }); } + } else if (block instanceof ControlFlowRegion) { + this.recursivelyShadeCFG( + block.data.graph, ctx, ppp, visibleRect + ); } }); } @@ -249,7 +275,7 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { const context = this.renderer.get_context(); const visible_rect = this.renderer.get_visible_rect(); if (graph && ppp !== undefined && context && visible_rect) - this.recursively_shade_sdfg(graph, context, ppp, visible_rect); + this.recursivelyShadeCFG(graph, context, ppp, visible_rect); } public on_mouse_event( @@ -265,18 +291,18 @@ export class AvgParallelismOverlay extends GenericSdfgOverlay { !(foreground_elem instanceof Edge)) { if (foreground_elem.data.avg_parallelism === undefined) { const avg_parallelism_string = this.avg_parallelism_map[ - get_element_uuid(foreground_elem) + getGraphElementUUID(foreground_elem) ]; if (avg_parallelism_string) { - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( avg_parallelism_string, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), true, () => { this.clear_cached_avg_parallelism_values(); const graph = this.renderer.get_graph(); if (graph) - this.recalculate_avg_parallelism_values(graph); + this.recalculateAvgParallelismValues(graph); } ); } diff --git a/src/overlays/depth_overlay.ts b/src/overlays/depth_overlay.ts index 7cdbe65c..955d6046 100644 --- a/src/overlays/depth_overlay.ts +++ b/src/overlays/depth_overlay.ts @@ -1,15 +1,21 @@ -// Copyright 2019-2023 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { DagreSDFG, Point2D, SimpleRect, SymbolMap } from '../index'; +import { + DagreGraph, + Point2D, + SimpleRect, + SymbolMap, + getGraphElementUUID, +} from '../index'; import { SDFGRenderer } from '../renderer/renderer'; import { Edge, NestedSDFG, SDFGElement, - SDFGNode + SDFGNode, } from '../renderer/renderer_elements'; import { SDFV } from '../sdfv'; -import { getTempColorHslString, get_element_uuid } from '../utils/utils'; +import { getTempColorHslString } from '../utils/utils'; import { GenericSdfgOverlay, OverlayType } from './generic_sdfg_overlay'; export class DepthOverlay extends GenericSdfgOverlay { @@ -28,9 +34,7 @@ export class DepthOverlay extends GenericSdfgOverlay { } public clear_cached_depth_values(): void { - this.renderer.for_all_elements(0, 0, 0, 0, ( - _type: string, _e: Event, obj: any - ) => { + this.renderer.doForAllGraphElements((_group, _info, obj: any) => { if (obj.data) { if (obj.data.depth !== undefined) obj.data.depth = undefined; @@ -43,13 +47,14 @@ export class DepthOverlay extends GenericSdfgOverlay { public calculate_depth_node( node: SDFGNode, symbol_map: SymbolMap, depth_values: number[] ): number | undefined { - const depth_string = this.depth_map[get_element_uuid(node)]; + const depth_string = this.depth_map[getGraphElementUUID(node)]; let depth = undefined; - if (depth_string !== undefined) - depth = this.symbol_resolver.parse_symbol_expression( + if (depth_string !== undefined) { + depth = this.symbolResolver.parse_symbol_expression( depth_string, symbol_map ); + } node.data.depth_string = depth_string; node.data.depth = depth; @@ -61,7 +66,7 @@ export class DepthOverlay extends GenericSdfgOverlay { } public calculate_depth_graph( - g: DagreSDFG, symbol_map: SymbolMap, depth_values: number[] + g: DagreGraph, symbol_map: SymbolMap, depth_values: number[] ): void { g.nodes().forEach(v => { const state = g.node(v); @@ -78,7 +83,7 @@ export class DepthOverlay extends GenericSdfgOverlay { // based on the mapping described on the node. Object.keys(mapping).forEach((symbol: string) => { nested_symbols_map[symbol] = - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( mapping[symbol], symbol_map ); @@ -111,14 +116,14 @@ export class DepthOverlay extends GenericSdfgOverlay { }); } - public recalculate_depth_values(graph: DagreSDFG): void { + public recalculate_depth_values(graph: DagreGraph): void { this.heatmap_scale_center = 5; this.heatmap_hist_buckets = []; const depth_values: number[] = []; this.calculate_depth_graph( graph, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), depth_values ); @@ -150,20 +155,22 @@ export class DepthOverlay extends GenericSdfgOverlay { if (depth_string !== undefined && mousepos && node.intersect(mousepos.x, mousepos.y)) { // Show the computed Depth value if applicable. - if (isNaN(depth_string) && depth !== undefined) + if (isNaN(depth_string) && depth !== undefined) { this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); - if (tt_cont) + if (tt_cont) { tt_cont.innerText = ( 'Depth: ' + depth_string + ' (' + depth + ')' ); + } }); - else + } else { this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); if (tt_cont) tt_cont.innerText = 'Depth: ' + depth_string; }); + } } if (depth === undefined) { @@ -183,13 +190,13 @@ export class DepthOverlay extends GenericSdfgOverlay { return; // Calculate the severity color. - const color = getTempColorHslString(this.get_severity_value(depth)); + const color = getTempColorHslString(this.getSeverityValue(depth)); node.shade(this.renderer, ctx, color); } public recursively_shade_sdfg( - graph: DagreSDFG, + graph: DagreGraph, ctx: CanvasRenderingContext2D, ppp: number, visible_rect: SimpleRect @@ -265,12 +272,12 @@ export class DepthOverlay extends GenericSdfgOverlay { !(foreground_elem instanceof Edge)) { if (foreground_elem.data.depth === undefined) { const depth_string = this.depth_map[ - get_element_uuid(foreground_elem) + getGraphElementUUID(foreground_elem) ]; if (depth_string) { - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( depth_string, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), true, () => { this.clear_cached_depth_values(); diff --git a/src/overlays/generic_sdfg_overlay.ts b/src/overlays/generic_sdfg_overlay.ts index 21f90b47..bd021e6c 100644 --- a/src/overlays/generic_sdfg_overlay.ts +++ b/src/overlays/generic_sdfg_overlay.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { log, mean, median } from 'mathjs'; import { Point2D } from '../index'; @@ -19,7 +19,7 @@ export class GenericSdfgOverlay { public static readonly type: OverlayType = OverlayType.BOTH; public readonly olClass: typeof GenericSdfgOverlay = GenericSdfgOverlay; - protected symbol_resolver: SymbolResolver; + protected symbolResolver: SymbolResolver; protected vscode: any; protected heatmap_scale_center: number; protected heatmap_hist_buckets: number[]; @@ -29,7 +29,7 @@ export class GenericSdfgOverlay { protected renderer: SDFGRenderer ) { this.overlay_manager = renderer.get_overlay_manager(); - this.symbol_resolver = this.overlay_manager.get_symbol_resolver(); + this.symbolResolver = this.overlay_manager.get_symbol_resolver(); this.vscode = typeof vscode !== 'undefined' && vscode; this.heatmap_scale_center = 5; this.heatmap_hist_buckets = []; @@ -73,7 +73,9 @@ export class GenericSdfgOverlay { for (let i = 0; i < n; i++) this.heatmap_hist_buckets.push(minval + (i * step)); } - this.heatmap_hist_buckets.sort((a, b) => { return a - b; }); + this.heatmap_hist_buckets.sort((a, b) => { + return a - b; + }); } break; case 'linear_interpolation': @@ -97,7 +99,7 @@ export class GenericSdfgOverlay { } } - public get_severity_value(val: number): number { + public getSeverityValue(val: number): number { let severity = 0; switch (this.overlay_manager.get_heatmap_scaling_method()) { diff --git a/src/overlays/logical_group_overlay.ts b/src/overlays/logical_group_overlay.ts index 98c0c6f0..90badcc9 100644 --- a/src/overlays/logical_group_overlay.ts +++ b/src/overlays/logical_group_overlay.ts @@ -1,6 +1,6 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { DagreSDFG, JsonSDFG, Point2D, SimpleRect } from '../index'; +import { DagreGraph, JsonSDFG, Point2D, SimpleRect } from '../index'; import { SDFGRenderer } from '../renderer/renderer'; import { NestedSDFG, @@ -34,15 +34,15 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { this.renderer.draw_async(); } - public shade_node( + public shadeNode( node: SDFGNode, groups: LogicalGroup[], ctx: CanvasRenderingContext2D ): void { - const all_groups: LogicalGroup[] = []; + const allGroups: LogicalGroup[] = []; if (node instanceof State) { groups.forEach(group => { if (group.states.includes(node.id)) { node.shade(this.renderer, ctx, group.color, 0.3); - all_groups.push(group); + allGroups.push(group); } }); } else { @@ -50,26 +50,26 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { group.nodes.forEach(n => { if (n[0] === node.parent_id && n[1] === node.id) { node.shade(this.renderer, ctx, group.color, 0.3); - all_groups.push(group); + allGroups.push(group); } }); }); } const mousepos = this.renderer.get_mousepos(); - if (all_groups.length > 0 && mousepos && + if (allGroups.length > 0 && mousepos && node.intersect(mousepos.x, mousepos.y)) { // Show the corresponding group. this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); if (tt_cont) { - if (all_groups.length === 1) { - tt_cont.innerText = 'Group: ' + all_groups[0].name; + if (allGroups.length === 1) { + tt_cont.innerText = 'Group: ' + allGroups[0].name; } else { let group_string = 'Groups: '; - all_groups.forEach((group, i) => { + allGroups.forEach((group, i) => { group_string += group.name; - if (i < all_groups.length - 1) + if (i < allGroups.length - 1) group_string += ', '; }); tt_cont.innerText = group_string; @@ -79,8 +79,8 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { } } - public recursivelyShadeSDFG( - sdfg: JsonSDFG, graph: DagreSDFG, ctx: CanvasRenderingContext2D, + public recursivelyShadeCFG( + sdfg: JsonSDFG, graph: DagreGraph, ctx: CanvasRenderingContext2D, ppp: number, visibleRect: SimpleRect ): void { // First go over visible states, skipping invisible ones. We only draw @@ -91,7 +91,7 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { if (sdfgGroups === undefined) return; - graph.nodes().forEach(v => { + graph?.nodes().forEach(v => { const block = graph.node(v); // If the node's invisible, we skip it. @@ -105,7 +105,7 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { block.width / ppp <= SDFV.STATE_LOD)) || block.attributes().is_collapsed ) { - this.shade_node(block, sdfgGroups, ctx); + this.shadeNode(block, sdfgGroups, ctx); } else { if (block.type() === SDFGElementType.SDFGState) { const stateGraph = block.data.graph; @@ -116,30 +116,30 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { // Skip the node if it's not visible. if ((ctx as any).lod && !node.intersect( visibleRect.x, - visibleRect.y, visibleRect.w, visibleRect.h) - ) + visibleRect.y, visibleRect.w, visibleRect.h + )) return; if (node.attributes().is_collapsed || ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) { - this.shade_node(node, sdfgGroups, ctx); + this.shadeNode(node, sdfgGroups, ctx); } else { if (node instanceof NestedSDFG && node.attributes().sdfg && node.attributes().sdfg.type !== 'SDFGShell' ) { - this.recursivelyShadeSDFG( + this.recursivelyShadeCFG( node.data.node.attributes.sdfg, node.data.graph, ctx, ppp, visibleRect ); } else { - this.shade_node(node, sdfgGroups, ctx); + this.shadeNode(node, sdfgGroups, ctx); } } }); } } else { - this.recursivelyShadeSDFG( + this.recursivelyShadeCFG( sdfg, block.data.graph, ctx, ppp, visibleRect ); } @@ -153,10 +153,11 @@ export class LogicalGroupOverlay extends GenericSdfgOverlay { const ppp = this.renderer.get_canvas_manager()?.points_per_pixel(); const context = this.renderer.get_context(); const visible_rect = this.renderer.get_visible_rect(); - if (graph && ppp !== undefined && context && visible_rect) - this.recursivelyShadeSDFG( + if (graph && ppp !== undefined && context && visible_rect) { + this.recursivelyShadeCFG( sdfg, graph, context, ppp, visible_rect ); + } } public on_mouse_event( diff --git a/src/overlays/memory_location_overlay.ts b/src/overlays/memory_location_overlay.ts index 7d492218..5cb2f23c 100644 --- a/src/overlays/memory_location_overlay.ts +++ b/src/overlays/memory_location_overlay.ts @@ -1,12 +1,15 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { DagreSDFG, Point2D, SimpleRect } from '../index'; +import { DagreGraph, Point2D, SimpleRect } from '../index'; import { SDFGRenderer } from '../renderer/renderer'; import { AccessNode, + ControlFlowBlock, + ControlFlowRegion, NestedSDFG, SDFGElement, - SDFGNode + SDFGNode, + State, } from '../renderer/renderer_elements'; import { SDFV } from '../sdfv'; import { KELLY_COLORS } from '../utils/utils'; @@ -83,7 +86,7 @@ const SCOPEDEFAULT_STORAGE = [ScheduleType.GPU_ThreadBlock, StorageType.Register], [ScheduleType.GPU_ThreadBlock_Dynamic, StorageType.Register], [ScheduleType.FPGA_Device, StorageType.FPGA_Global], - [ScheduleType.SVE_Map, StorageType.CPU_Heap] + [ScheduleType.SVE_Map, StorageType.CPU_Heap], ]); // Maps from ScheduleType to default ScheduleType for sub-scopes. @@ -102,7 +105,7 @@ const SCOPEDEFAULT_SCHEDULE = [ScheduleType.GPU_ThreadBlock, ScheduleType.Sequential], [ScheduleType.GPU_ThreadBlock_Dynamic, ScheduleType.Sequential], [ScheduleType.FPGA_Device, ScheduleType.FPGA_Device], - [ScheduleType.SVE_Map, ScheduleType.Sequential] + [ScheduleType.SVE_Map, ScheduleType.Sequential], ]); const STYPE_COLOR = new Map([ @@ -180,15 +183,17 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { let storageType = sdfgArray?.attributes?.storage; let originalType: StorageType | null = null; - if (storageType) { - if (storageType === StorageType.Default) { - const schedule = - MemoryLocationOverlay.recursiveFindScopeSchedule(node); - const derivedStorageType = SCOPEDEFAULT_STORAGE.get(schedule); - if (derivedStorageType) { - originalType = storageType; - storageType = derivedStorageType; - } + + if (!storageType) + storageType = StorageType.Default; + + if (storageType === StorageType.Default) { + const schedule = + MemoryLocationOverlay.recursiveFindScopeSchedule(node); + const derivedStorageType = SCOPEDEFAULT_STORAGE.get(schedule); + if (derivedStorageType) { + originalType = storageType; + storageType = derivedStorageType; } } return { @@ -204,12 +209,13 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { this.renderer.set_tooltip(() => { const ttContainer = this.renderer.get_tooltip_container(); if (ttContainer) { - if (storageType.originalType) + if (storageType.originalType) { ttContainer.innerHTML = 'Location: ' + storageType.originalType + ' → ' + storageType.type; - else + } else { ttContainer.innerHTML = 'Location: ' + storageType.type; + } } }); } @@ -219,32 +225,32 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { node.shade(this.renderer, ctx, '#' + color); } - public recursivelyShadeSdfg( - graph: DagreSDFG, + public recursivelyShadeCFG( + graph: DagreGraph, ctx: CanvasRenderingContext2D, ppp: number, visibleRect: SimpleRect ): void { - // First go over visible states, skipping invisible ones. We traverse - // inside to shade memory nodes wherever applicable. + // First go over visible control flow blocks, skipping invisible ones. + // We traverse inside to shade memory nodes wherever applicable. graph.nodes().forEach(v => { - const state = graph.node(v); + const block: ControlFlowBlock = graph.node(v); // If the node's invisible, we skip it. - if ((ctx as any).lod && !state.intersect( + if ((ctx as any).lod && !block.intersect( visibleRect.x, visibleRect.y, visibleRect.w, visibleRect.h )) return; if (((ctx as any).lod && (ppp >= SDFV.STATE_LOD || - state.width / ppp <= SDFV.STATE_LOD)) || - state.data.state.attributes.is_collapsed) { - // The state is collapsed or invisible, so we don't need to + block.width / ppp <= SDFV.STATE_LOD)) || + block.attributes()?.is_collapsed) { + // The block is collapsed or invisible, so we don't need to // traverse its insides. return; - } else { - const stateGraph = state.data.graph; + } else if (block instanceof State) { + const stateGraph = block.data.graph; if (stateGraph) { stateGraph.nodes().forEach((v: any) => { const node = stateGraph.node(v); @@ -257,7 +263,7 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { if (node instanceof NestedSDFG && node.attributes().sdfg && node.attributes().sdfg.type !== 'SDFGShell') { - this.recursivelyShadeSdfg( + this.recursivelyShadeCFG( node.data.graph, ctx, ppp, visibleRect ); } else if (node instanceof AccessNode) { @@ -265,6 +271,10 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { } }); } + } else if (block instanceof ControlFlowRegion) { + this.recursivelyShadeCFG( + block.data.graph, ctx, ppp, visibleRect + ); } }); } @@ -275,7 +285,7 @@ export class MemoryLocationOverlay extends GenericSdfgOverlay { const context = this.renderer.get_context(); const visibleRect = this.renderer.get_visible_rect(); if (graph && ppp !== undefined && context && visibleRect) - this.recursivelyShadeSdfg(graph, context, ppp, visibleRect); + this.recursivelyShadeCFG(graph, context, ppp, visibleRect); } public on_mouse_event( diff --git a/src/overlays/memory_volume_overlay.ts b/src/overlays/memory_volume_overlay.ts index c85de285..faf8e863 100644 --- a/src/overlays/memory_volume_overlay.ts +++ b/src/overlays/memory_volume_overlay.ts @@ -1,13 +1,15 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { DagreSDFG, Point2D, SimpleRect, SymbolMap } from '../index'; +import { DagreGraph, Point2D, SimpleRect, SymbolMap } from '../index'; import { SDFGRenderer } from '../renderer/renderer'; import { + ControlFlowBlock, + ControlFlowRegion, Edge, NestedSDFG, SDFGElement, SDFGNode, - State + State, } from '../renderer/renderer_elements'; import { SDFV } from '../sdfv'; import { getTempColorHslString } from '../utils/utils'; @@ -24,10 +26,8 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { this.refresh(); } - public clear_cached_volume_values(): void { - this.renderer.for_all_elements(0, 0, 0, 0, ( - type: string, e: MouseEvent, obj: any, - ) => { + public clearCachedVolumeValues(): void { + this.renderer.doForAllGraphElements((_group, info, obj: any) => { if (obj.data) { if (obj.data.volume !== undefined) obj.data.volume = undefined; @@ -35,92 +35,103 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { }); } - public calculate_volume_edge( + public calculateVolumeEdge( edge: Edge, - symbol_map: SymbolMap, - volume_values: number[] + symbolMap: SymbolMap, + volumes: number[] ): number | undefined { - let volume_string = undefined; + let volumeString = undefined; if (edge.data && edge.data.attributes) { - volume_string = edge.data.attributes.volume; - if (volume_string !== undefined) { - volume_string = volume_string.replace(/\*\*/g, '^'); - volume_string = volume_string.replace(/ceiling/g, 'ceil'); + volumeString = edge.data.attributes.volume; + if (volumeString !== undefined) { + volumeString = volumeString.replace(/\*\*/g, '^'); + volumeString = volumeString.replace(/ceiling/g, 'ceil'); } } let volume = undefined; - if (volume_string !== undefined) - volume = this.symbol_resolver.parse_symbol_expression( - volume_string, - symbol_map + if (volumeString !== undefined) { + volume = this.symbolResolver.parse_symbol_expression( + volumeString, + symbolMap ); + } edge.data.volume = volume; if (volume !== undefined && volume > 0) - volume_values.push(volume); + volumes.push(volume); return volume; } - public calculate_volume_graph( - g: DagreSDFG, - symbol_map: SymbolMap, - volume_values: number[] + public calculateVolumeGraph( + g: DagreGraph, + symbolMaps: SymbolMap, + volumes: number[] ): void { g.nodes().forEach((v: string) => { - const state = g.node(v); - const state_graph = state.data.graph; - if (state_graph) { - state_graph.edges().forEach((e: number) => { - const edge = state_graph.edge(e); - if (edge instanceof Edge) - this.calculate_volume_edge( - edge, - symbol_map, - volume_values - ); - }); - - state_graph.nodes().forEach((v: number) => { - const node = state_graph.node(v); - if (node instanceof NestedSDFG) { - const nested_symbols_map: SymbolMap = {}; - const mapping = node.data.node.attributes.symbol_mapping ?? {}; - // Translate the symbol mappings for the nested SDFG - // based on the mapping described on the node. - Object.keys(mapping).forEach((symbol) => { - nested_symbols_map[symbol] = - this.symbol_resolver.parse_symbol_expression( - mapping[symbol], - symbol_map - ); - }); - // Merge in the parent mappings. - Object.keys(symbol_map).forEach((symbol) => { - if (!(symbol in nested_symbols_map)) - nested_symbols_map[symbol] = symbol_map[symbol]; - }); - - this.calculate_volume_graph( - node.data.graph, - nested_symbols_map, - volume_values - ); - } - }); + const block: ControlFlowBlock = g.node(v); + if (block instanceof State) { + const stateGraph = block.data.graph; + if (stateGraph) { + stateGraph.edges().forEach((e: number) => { + const edge = stateGraph.edge(e); + if (edge instanceof Edge) { + this.calculateVolumeEdge( + edge, + symbolMaps, + volumes + ); + } + }); + + stateGraph.nodes().forEach((v: number) => { + const node = stateGraph.node(v); + if (node instanceof NestedSDFG) { + const nested_symbols_map: SymbolMap = {}; + const mapping = + node.data.node.attributes.symbol_mapping ?? {}; + // Translate the symbol mappings for the nested SDFG + // based on the mapping described on the node. + Object.keys(mapping).forEach((symbol) => { + nested_symbols_map[symbol] = + this.symbolResolver.parse_symbol_expression( + mapping[symbol], + symbolMaps + ); + }); + // Merge in the parent mappings. + Object.keys(symbolMaps).forEach((symbol) => { + if (!(symbol in nested_symbols_map)) { + nested_symbols_map[symbol] = + symbolMaps[symbol]; + } + }); + + this.calculateVolumeGraph( + node.data.graph, + nested_symbols_map, + volumes + ); + } + }); + } + } else if (block instanceof ControlFlowRegion) { + this.calculateVolumeGraph( + block.data.graph, symbolMaps, volumes + ); } }); } - public recalculate_volume_values(graph: DagreSDFG): void { + public recalculateVolumeValues(graph: DagreGraph): void { this.heatmap_scale_center = 5; this.heatmap_hist_buckets = []; const volume_values: number[] = []; - this.calculate_volume_graph( + this.calculateVolumeGraph( graph, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), volume_values ); @@ -131,15 +142,15 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { } public refresh(): void { - this.clear_cached_volume_values(); + this.clearCachedVolumeValues(); const graph = this.renderer.get_graph(); if (graph) - this.recalculate_volume_values(graph); + this.recalculateVolumeValues(graph); this.renderer.draw_async(); } - public shade_edge(edge: Edge, ctx: CanvasRenderingContext2D): void { + public shadeEdge(edge: Edge, ctx: CanvasRenderingContext2D): void { const volume = edge.data.volume; if (volume !== undefined) { // Only draw positive volumes. @@ -148,69 +159,76 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { // Calculate the severity color. const color = getTempColorHslString( - this.get_severity_value(volume) + this.getSeverityValue(volume) ); edge.shade(this.renderer, ctx, color); } } - public recursively_shade_sdfg( - graph: DagreSDFG, ctx: CanvasRenderingContext2D, ppp: number, - visible_rect: SimpleRect + public recursivelyShadeCFG( + graph: DagreGraph, ctx: CanvasRenderingContext2D, ppp: number, + visibleRect: SimpleRect ): void { graph.nodes().forEach(v => { - const state: State = graph.node(v); + const block: ControlFlowBlock = graph.node(v); // If we're zoomed out enough that the contents aren't visible, we // skip the state. if ((ctx as any).lod && ( - ppp >= SDFV.STATE_LOD || state.width / ppp < SDFV.STATE_LOD + ppp >= SDFV.STATE_LOD || block.width / ppp < SDFV.STATE_LOD )) return; // If the node's invisible, we skip it. - if ((ctx as any).lod && !state.intersect( - visible_rect.x, visible_rect.y, - visible_rect.w, visible_rect.h - )) + if ((ctx as any).lod && !block.intersect( + visibleRect.x, visibleRect.y, + visibleRect.w, visibleRect.h + ) || block.attributes()?.is_collapsed) return; - const state_graph = state.data.graph; - if (state_graph && !state.data.state.attributes.is_collapsed) { - state_graph.nodes().forEach((v: string) => { - const node: SDFGNode = state_graph.node(v); - - // Skip the node if it's not visible. - if ((ctx as any).lod && !node.intersect( - visible_rect.x, visible_rect.y, - visible_rect.w, visible_rect.h - )) - return; - - // If we're zoomed out enough that the node's contents - // aren't visible or the node is collapsed, we skip it. - if (node.data.node.attributes.is_collapsed || - ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) - return; - - if (node instanceof NestedSDFG && - node.attributes().sdfg && - node.attributes().sdfg.type !== 'SDFGShell') - this.recursively_shade_sdfg( - node.data.graph, ctx, ppp, visible_rect - ); - }); - - state_graph.edges().forEach((e: any) => { - const edge: Edge = state_graph.edge(e); - - if ((ctx as any).lod && !edge.intersect(visible_rect.x, - visible_rect.y, visible_rect.w, visible_rect.h)) - return; - - this.shade_edge(edge, ctx); - }); + if (block instanceof State) { + const state_graph = block.data.graph; + if (state_graph) { + state_graph.nodes().forEach((v: string) => { + const node: SDFGNode = state_graph.node(v); + + // Skip the node if it's not visible. + if ((ctx as any).lod && !node.intersect( + visibleRect.x, visibleRect.y, + visibleRect.w, visibleRect.h + )) + return; + + // If we're zoomed out enough that the node's contents + // aren't visible or the node is collapsed, we skip it. + if (node.data.node.attributes.is_collapsed || + ((ctx as any).lod && ppp >= SDFV.NODE_LOD)) + return; + + if (node instanceof NestedSDFG && + node.attributes().sdfg && + node.attributes().sdfg.type !== 'SDFGShell') { + this.recursivelyShadeCFG( + node.data.graph, ctx, ppp, visibleRect + ); + } + }); + + state_graph.edges().forEach((e: any) => { + const edge: Edge = state_graph.edge(e); + + if ((ctx as any).lod && !edge.intersect(visibleRect.x, + visibleRect.y, visibleRect.w, visibleRect.h)) + return; + + this.shadeEdge(edge, ctx); + }); + } + } else if (block instanceof ControlFlowRegion) { + this.recursivelyShadeCFG( + block.data.graph, ctx, ppp, visibleRect + ); } }); } @@ -221,7 +239,7 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { const context = this.renderer.get_context(); const visible_rect = this.renderer.get_visible_rect(); if (graph && ppp !== undefined && context && visible_rect) - this.recursively_shade_sdfg(graph, context, ppp, visible_rect); + this.recursivelyShadeCFG(graph, context, ppp, visible_rect); } public on_mouse_event( @@ -237,15 +255,15 @@ export class MemoryVolumeOverlay extends GenericSdfgOverlay { foreground_elem instanceof Edge) { if (foreground_elem.data.volume === undefined) { if (foreground_elem.data.attributes.volume) { - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( foreground_elem.data.attributes.volume, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), true, () => { const graph = this.renderer.get_graph(); if (graph) { - this.clear_cached_volume_values(); - this.recalculate_volume_values(graph); + this.clearCachedVolumeValues(); + this.recalculateVolumeValues(graph); } } ); diff --git a/src/overlays/operational_intensity_overlay.ts b/src/overlays/operational_intensity_overlay.ts index cca400cb..6cd7d4f3 100644 --- a/src/overlays/operational_intensity_overlay.ts +++ b/src/overlays/operational_intensity_overlay.ts @@ -1,15 +1,21 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { DagreSDFG, Point2D, SimpleRect, SymbolMap } from '../index'; +import { + DagreGraph, + Point2D, + SimpleRect, + SymbolMap, + getGraphElementUUID, +} from '../index'; import { SDFGRenderer } from '../renderer/renderer'; import { Edge, NestedSDFG, SDFGElement, - SDFGNode + SDFGNode, } from '../renderer/renderer_elements'; import { SDFV } from '../sdfv'; -import { getTempColorHslString, get_element_uuid } from '../utils/utils'; +import { getTempColorHslString } from '../utils/utils'; import { GenericSdfgOverlay, OverlayType } from './generic_sdfg_overlay'; export class OperationalIntensityOverlay extends GenericSdfgOverlay { @@ -29,9 +35,7 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { } public clear_cached_values(): void { - this.renderer.for_all_elements(0, 0, 0, 0, ( - type: string, e: MouseEvent, obj: any, - ) => { + this.renderer.doForAllGraphElements((_group, _info, obj) => { if (obj.data) { if (obj.data.volume !== undefined) obj.data.volume = undefined; @@ -51,12 +55,13 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { if (node.parent_id === undefined || node.parent_id === null) return; - const flops_string = this.flops_map[get_element_uuid(node)]; + const flops_string = this.flops_map[getGraphElementUUID(node)]; let flops = undefined; - if (flops_string !== undefined) - flops = this.symbol_resolver.parse_symbol_expression( + if (flops_string !== undefined) { + flops = this.symbolResolver.parse_symbol_expression( flops_string, symbol_map ); + } node.data.flops_string = flops_string; node.data.flops = flops; @@ -65,7 +70,7 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { const io_edges = []; for (const e of node.sdfg.nodes[node.parent_id].edges) { - if (e.src == node.id || e.dst == node.id) + if (e.src === node.id.toString() || e.dst === node.id.toString()) io_edges.push(e); } @@ -86,10 +91,11 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { volume = edge.attributes.data.volume; } - if (volume_string !== undefined) - volume = this.symbol_resolver.parse_symbol_expression( + if (volume_string !== undefined) { + volume = this.symbolResolver.parse_symbol_expression( volume_string, symbol_map ); + } edge.attributes.data.volume = volume; @@ -124,7 +130,7 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { } public calculate_opint_graph( - g: DagreSDFG, symbol_map: SymbolMap, flops_values: number[] + g: DagreGraph, symbol_map: SymbolMap, flops_values: number[] ): void { g.nodes().forEach(v => { const state = g.node(v); @@ -141,7 +147,7 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { // based on the mapping described on the node. Object.keys(mapping).forEach((symbol: string) => { nested_symbols_map[symbol] = - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( mapping[symbol], symbol_map ); @@ -174,14 +180,14 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { }); } - public recalculate_opint_values(graph: DagreSDFG): void { + public recalculate_opint_values(graph: DagreGraph): void { this.heatmap_scale_center = 5; this.heatmap_hist_buckets = []; const flops_values: number[] = []; this.calculate_opint_graph( graph, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), flops_values ); @@ -227,13 +233,13 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { return; // Calculate the severity color. - const color = getTempColorHslString(this.get_severity_value(opint)); + const color = getTempColorHslString(this.getSeverityValue(opint)); node.shade(this.renderer, ctx, color); } public recursively_shade_sdfg( - graph: DagreSDFG, + graph: DagreGraph, ctx: CanvasRenderingContext2D, ppp: number, visible_rect: SimpleRect @@ -309,12 +315,12 @@ export class OperationalIntensityOverlay extends GenericSdfgOverlay { !(foreground_elem instanceof Edge)) { if (foreground_elem.data.flops === undefined) { const flops_string = this.flops_map[ - get_element_uuid(foreground_elem) + getGraphElementUUID(foreground_elem) ]; if (flops_string) { - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( flops_string, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), true, () => { this.clear_cached_values(); diff --git a/src/overlays/runtime_micro_seconds_overlay.ts b/src/overlays/runtime_micro_seconds_overlay.ts index 2f18461d..bc22790b 100644 --- a/src/overlays/runtime_micro_seconds_overlay.ts +++ b/src/overlays/runtime_micro_seconds_overlay.ts @@ -1,15 +1,15 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { Node } from 'dagre'; -import { DagreSDFG, SimpleRect } from '../index'; +import { DagreGraph, SimpleRect, getGraphElementUUID } from '../index'; import { SDFGRenderer } from '../renderer/renderer'; import { NestedSDFG, SDFGNode } from '../renderer/renderer_elements'; import { SDFV } from '../sdfv'; -import { getTempColorHslString, get_element_uuid } from '../utils/utils'; +import { getTempColorHslString } from '../utils/utils'; import { GenericSdfgOverlay, OverlayType, - RuntimeReportOverlay + RuntimeReportOverlay, } from './generic_sdfg_overlay'; @@ -20,7 +20,7 @@ export class RuntimeMicroSecondsOverlay extends RuntimeReportOverlay { RuntimeMicroSecondsOverlay; protected criterium: string = 'mean'; - private runtime_map: { [uuids: string]: any } = {} + private runtime_map: { [uuids: string]: any } = {}; public constructor(renderer: SDFGRenderer) { super(renderer); @@ -66,7 +66,7 @@ export class RuntimeMicroSecondsOverlay extends RuntimeReportOverlay { } public shade_node(node: SDFGNode, ctx: CanvasRenderingContext2D): void { - const rt_summary = this.runtime_map[get_element_uuid(node)]; + const rt_summary = this.runtime_map[getGraphElementUUID(node)]; if (rt_summary === undefined) return; @@ -74,19 +74,19 @@ export class RuntimeMicroSecondsOverlay extends RuntimeReportOverlay { const mousepos = this.renderer.get_mousepos(); if (mousepos && node.intersect(mousepos.x, mousepos.y)) { // Show the measured runtime. - if (rt_summary['min'] === rt_summary['max']) + if (rt_summary['min'] === rt_summary['max']) { this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); - if (tt_cont) + if (tt_cont) { tt_cont.innerText = this.pretty_print_micros( rt_summary['min'] ); + } }); - - else + } else { this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); - if (tt_cont) + if (tt_cont) { tt_cont.innerText = ( 'Min: ' + this.pretty_print_micros(rt_summary['min']) + @@ -99,18 +99,20 @@ export class RuntimeMicroSecondsOverlay extends RuntimeReportOverlay { '\nCount: ' + rt_summary['count'] ); + } }); + } } // Calculate the severity color. const micros = rt_summary[this.criterium]; - const color = getTempColorHslString(this.get_severity_value(micros)); + const color = getTempColorHslString(this.getSeverityValue(micros)); node.shade(this.renderer, ctx, color); } public recursively_shade_sdfg( - graph: DagreSDFG, + graph: DagreGraph, ctx: CanvasRenderingContext2D, ppp: number, visible_rect: SimpleRect diff --git a/src/overlays/simulated_operational_intensity_overlay.ts b/src/overlays/simulated_operational_intensity_overlay.ts index 6c807116..b73d4301 100644 --- a/src/overlays/simulated_operational_intensity_overlay.ts +++ b/src/overlays/simulated_operational_intensity_overlay.ts @@ -1,21 +1,28 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { DagreSDFG, Point2D, SimpleRect, SymbolMap } from '../index'; +import { + DagreGraph, + Point2D, + SimpleRect, + SymbolMap, + getGraphElementUUID, +} from '../index'; import { SDFGRenderer } from '../renderer/renderer'; import { Edge, NestedSDFG, SDFGElement, - SDFGNode + SDFGNode, } from '../renderer/renderer_elements'; import { SDFV } from '../sdfv'; -import { getTempColorHslString, get_element_uuid } from '../utils/utils'; +import { getTempColorHslString } from '../utils/utils'; import { GenericSdfgOverlay, OverlayType } from './generic_sdfg_overlay'; export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { public static readonly type: OverlayType = OverlayType.NODE; - public readonly olClass: typeof GenericSdfgOverlay = SimulatedOperationalIntensityOverlay; + public readonly olClass: typeof GenericSdfgOverlay = + SimulatedOperationalIntensityOverlay; private op_in_map: { [uuids: string]: any } = {}; @@ -23,14 +30,13 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { super(renderer); this.renderer.emit( - 'backend_data_requested', 'op_in', 'SimulatedOperationalIntensityOverlay' + 'backend_data_requested', 'op_in', + 'SimulatedOperationalIntensityOverlay' ); } public clear_cached_op_in_values(): void { - this.renderer.for_all_elements(0, 0, 0, 0, ( - _type: string, _e: Event, obj: any - ) => { + this.renderer.doForAllGraphElements((_group, _info, obj) => { if (obj.data) { if (obj.data.op_in !== undefined) obj.data.op_in = undefined; @@ -43,14 +49,15 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { public calculate_op_in_node( node: SDFGNode, symbol_map: SymbolMap, op_in_values: number[] ): number | undefined { - const op_in_string = this.op_in_map[get_element_uuid(node)]; + const op_in_string = this.op_in_map[getGraphElementUUID(node)]; let op_in = undefined; - if (op_in_string !== undefined) - op_in = this.symbol_resolver.parse_symbol_expression( + if (op_in_string !== undefined) { + op_in = this.symbolResolver.parse_symbol_expression( op_in_string, symbol_map, false ); + } node.data.op_in_string = op_in_string; node.data.op_in = op_in; @@ -62,7 +69,7 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { } public calculate_op_in_graph( - g: DagreSDFG, symbol_map: SymbolMap, op_in_values: number[] + g: DagreGraph, symbol_map: SymbolMap, op_in_values: number[] ): void { g.nodes().forEach(v => { const state = g.node(v); @@ -79,7 +86,7 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { // based on the mapping described on the node. Object.keys(mapping).forEach((symbol: string) => { nested_symbols_map[symbol] = - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( mapping[symbol], symbol_map ); @@ -112,14 +119,14 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { }); } - public recalculate_op_in_values(graph: DagreSDFG): void { + public recalculate_op_in_values(graph: DagreGraph): void { this.heatmap_scale_center = 5; this.heatmap_hist_buckets = []; const op_in_values: number[] = []; this.calculate_op_in_graph( graph, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), op_in_values ); @@ -151,20 +158,25 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { if (op_in_string !== undefined && mousepos && node.intersect(mousepos.x, mousepos.y)) { // Show the computed op_in value if applicable. - if (isNaN(op_in_string) && op_in !== undefined) + if (isNaN(op_in_string) && op_in !== undefined) { this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); - if (tt_cont) + if (tt_cont) { tt_cont.innerText = ( - 'Operational Intensity: ' + op_in_string + ' (' + op_in + ')' + 'Operational Intensity: ' + op_in_string + ' (' + + op_in + ')' ); + } }); - else + } else { this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); - if (tt_cont) - tt_cont.innerText = 'Operational Intensity: ' + op_in_string; + if (tt_cont) { + tt_cont.innerText = 'Operational Intensity: ' + + op_in_string; + } }); + } } if (op_in === undefined) { @@ -184,13 +196,13 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { return; // Calculate the severity color. - const color = getTempColorHslString(1 - this.get_severity_value(op_in)); + const color = getTempColorHslString(1 - this.getSeverityValue(op_in)); node.shade(this.renderer, ctx, color); } public recursively_shade_sdfg( - graph: DagreSDFG, + graph: DagreGraph, ctx: CanvasRenderingContext2D, ppp: number, visible_rect: SimpleRect @@ -266,12 +278,12 @@ export class SimulatedOperationalIntensityOverlay extends GenericSdfgOverlay { !(foreground_elem instanceof Edge)) { if (foreground_elem.data.op_in === undefined) { const op_in_string = this.op_in_map[ - get_element_uuid(foreground_elem) + getGraphElementUUID(foreground_elem) ]; if (op_in_string) { - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( op_in_string, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), true, () => { this.clear_cached_op_in_values(); diff --git a/src/overlays/static_flops_overlay.ts b/src/overlays/static_flops_overlay.ts index e35d654f..b68326c8 100644 --- a/src/overlays/static_flops_overlay.ts +++ b/src/overlays/static_flops_overlay.ts @@ -1,15 +1,21 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { DagreSDFG, Point2D, SimpleRect, SymbolMap } from '../index'; +import { + DagreGraph, + Point2D, + SimpleRect, + SymbolMap, + getGraphElementUUID, +} from '../index'; import { SDFGRenderer } from '../renderer/renderer'; import { Edge, NestedSDFG, SDFGElement, - SDFGNode + SDFGNode, } from '../renderer/renderer_elements'; import { SDFV } from '../sdfv'; -import { getTempColorHslString, get_element_uuid } from '../utils/utils'; +import { getTempColorHslString } from '../utils/utils'; import { GenericSdfgOverlay, OverlayType } from './generic_sdfg_overlay'; export class StaticFlopsOverlay extends GenericSdfgOverlay { @@ -28,9 +34,7 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { } public clear_cached_flops_values(): void { - this.renderer.for_all_elements(0, 0, 0, 0, ( - _type: string, _e: Event, obj: any - ) => { + this.renderer.doForAllGraphElements((_group, _info, obj) => { if (obj.data) { if (obj.data.flops !== undefined) obj.data.flops = undefined; @@ -43,13 +47,14 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { public calculate_flops_node( node: SDFGNode, symbol_map: SymbolMap, flops_values: number[] ): number | undefined { - const flops_string = this.flops_map[get_element_uuid(node)]; + const flops_string = this.flops_map[getGraphElementUUID(node)]; let flops = undefined; - if (flops_string !== undefined) - flops = this.symbol_resolver.parse_symbol_expression( + if (flops_string !== undefined) { + flops = this.symbolResolver.parse_symbol_expression( flops_string, symbol_map ); + } node.data.flops_string = flops_string; node.data.flops = flops; @@ -61,7 +66,7 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { } public calculate_flops_graph( - g: DagreSDFG, symbol_map: SymbolMap, flops_values: number[] + g: DagreGraph, symbol_map: SymbolMap, flops_values: number[] ): void { g.nodes().forEach(v => { const state = g.node(v); @@ -78,7 +83,7 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { // based on the mapping described on the node. Object.keys(mapping).forEach((symbol: string) => { nested_symbols_map[symbol] = - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( mapping[symbol], symbol_map ); @@ -111,14 +116,14 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { }); } - public recalculate_flops_values(graph: DagreSDFG): void { + public recalculate_flops_values(graph: DagreGraph): void { this.heatmap_scale_center = 5; this.heatmap_hist_buckets = []; const flops_values: number[] = []; this.calculate_flops_graph( graph, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), flops_values ); @@ -150,20 +155,22 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { if (flops_string !== undefined && mousepos && node.intersect(mousepos.x, mousepos.y)) { // Show the computed FLOPS value if applicable. - if (isNaN(flops_string) && flops !== undefined) + if (isNaN(flops_string) && flops !== undefined) { this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); - if (tt_cont) + if (tt_cont) { tt_cont.innerText = ( 'FLOPS: ' + flops_string + ' (' + flops + ')' ); + } }); - else + } else { this.renderer.set_tooltip(() => { const tt_cont = this.renderer.get_tooltip_container(); if (tt_cont) tt_cont.innerText = 'FLOPS: ' + flops_string; }); + } } if (flops === undefined) { @@ -183,13 +190,13 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { return; // Calculate the severity color. - const color = getTempColorHslString(this.get_severity_value(flops)); + const color = getTempColorHslString(this.getSeverityValue(flops)); node.shade(this.renderer, ctx, color); } public recursively_shade_sdfg( - graph: DagreSDFG, + graph: DagreGraph, ctx: CanvasRenderingContext2D, ppp: number, visible_rect: SimpleRect @@ -265,12 +272,12 @@ export class StaticFlopsOverlay extends GenericSdfgOverlay { !(foreground_elem instanceof Edge)) { if (foreground_elem.data.flops === undefined) { const flops_string = this.flops_map[ - get_element_uuid(foreground_elem) + getGraphElementUUID(foreground_elem) ]; if (flops_string) { - this.symbol_resolver.parse_symbol_expression( + this.symbolResolver.parse_symbol_expression( flops_string, - this.symbol_resolver.get_symbol_value_map(), + this.symbolResolver.get_symbol_value_map(), true, () => { this.clear_cached_flops_values(); diff --git a/src/renderer/canvas_manager.ts b/src/renderer/canvas_manager.ts index 5fefced1..635d5b97 100644 --- a/src/renderer/canvas_manager.ts +++ b/src/renderer/canvas_manager.ts @@ -1,6 +1,13 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { Edge, EntryNode, SDFGElement, SDFGElementType, SDFGNode } from './renderer_elements'; +import { + ControlFlowBlock, + Edge, + EntryNode, + SDFGElement, + SDFGElementType, + SDFGNode, +} from './renderer_elements'; import { lerpMatrix } from '../utils/lerp_matrix'; import { updateEdgeBoundingBox } from '../utils/bounding_box'; import { @@ -8,7 +15,7 @@ import { initialize_positioning_info, } from '../utils/sdfg/sdfg_utils'; import { SDFGRenderer, CFGListType } from './renderer'; -import { DagreSDFG, intersectRect, Point2D } from '../index'; +import { DagreGraph, intersectRect, Point2D } from '../index'; const animation_duration = 1000; @@ -17,8 +24,10 @@ const animation_function = (t: number) => 1 - Math.pow(1 - t, 3); let _canvas_manager_counter = 0; +/** + * Manages translation and scaling of canvas rendering. + */ export class CanvasManager { - // Manages translation and scaling of canvas rendering private anim_id: number | null = null; private prev_time: number | null = null; @@ -74,12 +83,12 @@ export class CanvasManager { public alreadyAnimatingTo(new_transform: DOMMatrix): boolean { if (this.animation_target) { let result = true; - result = result && (this.animation_target.a == new_transform.a); - result = result && (this.animation_target.b == new_transform.b); - result = result && (this.animation_target.c == new_transform.c); - result = result && (this.animation_target.d == new_transform.d); - result = result && (this.animation_target.e == new_transform.e); - result = result && (this.animation_target.f == new_transform.f); + result = result && (this.animation_target.a === new_transform.a); + result = result && (this.animation_target.b === new_transform.b); + result = result && (this.animation_target.c === new_transform.c); + result = result && (this.animation_target.d === new_transform.d); + result = result && (this.animation_target.e === new_transform.e); + result = result && (this.animation_target.f === new_transform.f); return result; } else { return false; @@ -203,13 +212,12 @@ export class CanvasManager { } public removeDrawable(drawable: unknown): void { - this.drawables = this.drawables.filter(x => x != drawable); + this.drawables = this.drawables.filter(x => x !== drawable); } public clearDrawables(): void { - for (const x of this.drawables) { + for (const x of this.drawables) x.destroy(); - } this.drawables = []; this.indices = []; } @@ -220,8 +228,8 @@ export class CanvasManager { return true; const topleft = ctx.getImageData(0, 0, 1, 1).data; - if (topleft[0] != 0 || topleft[1] != 0 || topleft[2] != 0 || - topleft[3] != 255) + if (topleft[0] !== 0 || topleft[1] !== 0 || topleft[2] !== 0 || + topleft[3] !== 255) return false; const pixelBuffer = new Uint32Array( @@ -235,9 +243,8 @@ export class CanvasManager { public scale(diff: number, x: number = 0, y: number = 0): void { this.stopAnimation(); - if (this.request_scale || this.contention > 0) { + if (this.request_scale || this.contention > 0) return; - } this.contention++; this.request_scale = true; if (this.isBlank()) { @@ -265,7 +272,7 @@ export class CanvasManager { public set_view(rect: DOMRect, animate: boolean = false): void { const canvas_w = this.canvas.width; const canvas_h = this.canvas.height; - if (canvas_w == 0 || canvas_h == 0) + if (canvas_w === 0 || canvas_h === 0) return; let scale = 1, tx = 0, ty = 0; @@ -333,7 +340,7 @@ export class CanvasManager { el: SDFGElement, old_mousepos: Point2D, new_mousepos: Point2D, - entire_graph: DagreSDFG, + entire_graph: DagreGraph, cfg_list: CFGListType, state_parent_list: any[], drag_start: any, @@ -348,22 +355,22 @@ export class CanvasManager { const in_edges: any[] = []; // Find the parent graph in the list of available SDFGs - let parent_graph = cfg_list[el.sdfg.cfg_list_id]; + let parent_graph = cfg_list[el.cfg!.cfg_list_id].graph; let parent_element: SDFGElement | null = null; if ( entire_graph !== parent_graph && - (el.data.state || el.data.type == 'InterstateEdge') + (el.data.state || el.data.type === 'InterstateEdge') ) { // If the parent graph and the entire SDFG shown are not the same, // we're currently in a nested SDFG. If we're also moving a state, // this means that its parent element is found in the list of // parents to states (state_parent_list) - parent_element = state_parent_list[el.sdfg.cfg_list_id]; + parent_element = state_parent_list[el.cfg!.cfg_list_id]; } else if (el.parent_id !== null && parent_graph) { // If the parent_id isn't null and there is a parent graph, we can // look up the parent node via the element's parent_id - parent_element = parent_graph.node(el.parent_id); + parent_element = parent_graph.node(el.parent_id.toString()); // If our parent element is a state, we want the state's graph if (parent_element && parent_element.data.state) parent_graph = parent_element.data.graph; @@ -371,10 +378,10 @@ export class CanvasManager { if (parent_graph && !(el instanceof Edge)) { // Find all the edges connected to the moving node - parent_graph.outEdges(el.id).forEach((edge_id: number) => { + parent_graph.outEdges(el.id.toString())?.forEach(edge_id => { out_edges.push(parent_graph.edge(edge_id)); }); - parent_graph.inEdges(el.id).forEach((edge_id: number) => { + parent_graph.inEdges(el.id.toString())?.forEach(edge_id => { in_edges.push(parent_graph.edge(edge_id)); }); } @@ -397,7 +404,7 @@ export class CanvasManager { el.get_points().forEach((p, i) => { // Only allow dragging if the memlet has more than two // points - if (i == 0 || i == el.get_points().length - 1) + if (i === 0 || i === el.get_points().length - 1) return; const ddx = p.x - drag_start.cx; const ddy = p.y - drag_start.cy; @@ -445,37 +452,33 @@ export class CanvasManager { const target_x = points[pt].x + dx; const target_y = points[pt].y + dy; if (target_x <= min_x || - new_mousepos.x <= parent_left_border) { + new_mousepos.x <= parent_left_border) dx = min_x - points[pt].x; - } else if (target_x >= max_x || - new_mousepos.x >= parent_right_border) { + else if (target_x >= max_x || + new_mousepos.x >= parent_right_border) dx = max_x - points[pt].x; - } if (target_y <= min_y || - new_mousepos.y <= parent_top_border) { + new_mousepos.y <= parent_top_border) dy = min_y - points[pt].y; - } else if (target_y >= max_y || - new_mousepos.y >= parent_bottom_border) { + else if (target_y >= max_y || + new_mousepos.y >= parent_bottom_border) dy = max_y - points[pt].y; - } } } else { const target_x = el.x + dx; const target_y = el.y + dy; if (target_x <= min_x || - new_mousepos.x <= parent_left_border) { + new_mousepos.x <= parent_left_border) dx = min_x - el.x; - } else if (target_x >= max_x || - new_mousepos.x >= parent_right_border) { + else if (target_x >= max_x || + new_mousepos.x >= parent_right_border) dx = max_x - el.x; - } if (target_y <= min_y || - new_mousepos.y <= parent_top_border) { + new_mousepos.y <= parent_top_border) dy = min_y - el.y; - } else if (target_y >= max_y || - new_mousepos.y >= parent_bottom_border) { + else if (target_y >= max_y || + new_mousepos.y >= parent_bottom_border) dy = max_y - el.y; - } } } @@ -499,15 +502,14 @@ export class CanvasManager { if (update_position_info) { if (!position.points) { position.points = Array(points.length); - for (let i = 0; i < points.length; i++) { - position.points[i] = {dx: 0, dy: 0}; - } + for (let i = 0; i < points.length; i++) + position.points[i] = { dx: 0, dy: 0 }; } position.points[pt].dx += dx; position.points[pt].dy += dy; } - } else if (pt == -2) { + } else if (pt === -2) { // Don't update first and last point (the connectors) for (let i = 1; i < points.length - 1; i++) { points[i].x += dx; @@ -520,7 +522,7 @@ export class CanvasManager { position.points[i].dy += dy; } } - } else if (pt == -3 && edge_dpoints) { + } else if (pt === -3 && edge_dpoints) { for (let i = 1; i < points.length - 1; i++) { points[i].x += edge_dpoints[i].dx; points[i].y += edge_dpoints[i].dy; @@ -530,27 +532,50 @@ export class CanvasManager { return; } - // Move a node together with its connectors if it has any - function move_node_and_connectors(node: SDFGNode) { + // Move a node together with its connectors if it has any. + function moveNode(node: SDFGNode | ControlFlowBlock) { node.x += dx; node.y += dy; - if (node.data.node && - node.data.node.type === SDFGElementType.NestedSDFG) - translate_recursive(node.data.graph); - if (node.in_connectors) - node.in_connectors.forEach(c => { - c.x += dx; - c.y += dy; + if (node instanceof SDFGNode) { + if (node.data.node && + node.data.node.type === SDFGElementType.NestedSDFG) + translateRecursive(node.data.graph); + if (node.in_connectors) { + node.in_connectors.forEach(c => { + c.x += dx; + c.y += dy; + }); + } + if (node.out_connectors) { + node.out_connectors.forEach(c => { + c.x += dx; + c.y += dy; + }); + } + } else if (!node.attributes().is_collapsed) { + // We're moving a control flow block, move all its contents too. + const nGraph = node.data.graph; + nGraph.nodes().forEach((node_id: string) => { + const nNode = nGraph.node(node_id); + moveNode(nNode); }); - if (node.out_connectors) - node.out_connectors.forEach(c => { - c.x += dx; - c.y += dy; + + // Drag all the edges along + nGraph.edges().forEach((edge_id: number) => { + const edge = nGraph.edge(edge_id); + edge.x += dx; + edge.y += dy; + edge.points.forEach((point: Point2D) => { + point.x += dx; + point.y += dy; + }); + updateEdgeBoundingBox(edge); }); + } } // Allow recursive translation of nested SDFGs - function translate_recursive(ng: DagreSDFG) { + function translateRecursive(ng: DagreGraph) { ng.nodes().forEach((state_id: string) => { const state = ng.node(state_id); state.x += dx; @@ -559,7 +584,7 @@ export class CanvasManager { if (g) { g.nodes().forEach((node_id: string) => { const node = g.node(node_id); - move_node_and_connectors(node); + moveNode(node); }); g.edges().forEach((edge_id: number) => { @@ -586,10 +611,9 @@ export class CanvasManager { }); } - // Move the node - move_node_and_connectors(el); + moveNode(el); - // Store movement information in element (for relayouting) + // Store movement information in element (for relayouting). if (update_position_info) { let position = getPositioningInfo(el); if (!position) @@ -599,7 +623,7 @@ export class CanvasManager { position.dy += dy; // Store movement information if EntryNode for other nodes of the - // same scope + // same scope. if (el instanceof EntryNode && el.data.node.attributes.is_collapsed) { if (!position.scope_dx) { @@ -612,27 +636,6 @@ export class CanvasManager { } } - if (el.data.state && !el.data.state.attributes.is_collapsed) { - // We're moving a state, move all its contained elements - const graph = el.data.graph; - graph.nodes().forEach((node_id: string) => { - const node = graph.node(node_id); - move_node_and_connectors(node); - }); - - // Drag all the edges along - graph.edges().forEach((edge_id: number) => { - const edge = graph.edge(edge_id); - edge.x += dx; - edge.y += dy; - edge.points.forEach((point: Point2D) => { - point.x += dx; - point.y += dy; - }); - updateEdgeBoundingBox(edge); - }); - } - // Move the connected edges along with the element out_edges.forEach((edge: Edge) => { const points = edge.points; @@ -656,7 +659,7 @@ export class CanvasManager { // Also update destination point of edge if (edge.dst_connector !== null) { const e = parent_element?.data?.state?.edges[edge.id]; - const dst_el = parent_graph.node(e?.dst); + const dst_el = parent_graph?.node(e?.dst); if (dst_el) { for (let i = 0; i < dst_el.in_connectors.length; i++) { const dst_name = dst_el.in_connectors[i].data.name; @@ -693,7 +696,7 @@ export class CanvasManager { // Also update source point of edge if (edge.src_connector !== null) { const e = parent_element?.data?.state?.edges[edge.id]; - const src_el = parent_graph.node(e?.src); + const src_el = parent_graph?.node(e?.src); if (src_el) { for (let i = 0; i < src_el.out_connectors.length; i++) { const out_name = src_el.out_connectors[i].data.name; @@ -737,9 +740,8 @@ export class CanvasManager { } public animation_step(now: number): void { - if (this.animation === null) { + if (this.animation === null) return; - } if (this.animation_start === null) { this.animation_start = now; @@ -790,9 +792,8 @@ export class CanvasManager { this.renderer.draw(dt); this.contention -= 1; - if (this.animation_end !== null && now < this.animation_end) { + if (this.animation_end !== null && now < this.animation_end) this.draw_async(); - } } public draw_async(): void { diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts index d88422e7..7f838f1b 100644 --- a/src/renderer/renderer.ts +++ b/src/renderer/renderer.ts @@ -1,15 +1,17 @@ -// Copyright 2019-2023 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import $ from 'jquery'; import dagre from 'dagre'; import EventEmitter from 'events'; import { - DagreSDFG, + DagreGraph, GenericSdfgOverlay, JsonSDFG, JsonSDFGBlock, + JsonSDFGControlFlowRegion, JsonSDFGEdge, + JsonSDFGElement, JsonSDFGNode, JsonSDFGState, MemoryLocationOverlay, @@ -19,7 +21,7 @@ import { SDFVTooltipFunc, SimpleRect, checkCompatSave, - stringify_sdfg + stringify_sdfg, } from '../index'; import { SMLayouter } from '../layouter/state_machine/sm_layouter'; import { LViewLayouter } from '../local_view/lview_layouter'; @@ -31,35 +33,34 @@ import { SDFV, reload_file } from '../sdfv'; import { boundingBox, calculateBoundingBox, - calculateEdgeBoundingBox + calculateEdgeBoundingBox, } from '../utils/bounding_box'; import { sdfg_property_to_string } from '../utils/sdfg/display'; +import { memletTreeComplete } from '../utils/sdfg/memlet_trees'; import { - check_and_redirect_edge, deletePositioningInfo, delete_sdfg_nodes, - delete_sdfg_states, find_exit_for_entry, find_graph_element_by_uuid, - find_root_sdfg, getPositioningInfo, get_uuid_graph_element + check_and_redirect_edge, deletePositioningInfo, deleteSDFGNodes, + deleteCFGBlocks, findExitForEntry, findGraphElementByUUID, + getPositioningInfo, getGraphElementUUID, findRootCFG, } from '../utils/sdfg/sdfg_utils'; -import { - memlet_tree_complete, - traverseSDFGScopes -} from '../utils/sdfg/traversal'; +import { traverseSDFGScopes } from '../utils/sdfg/traversal'; import { SDFVSettings } from '../utils/sdfv_settings'; import { deepCopy, intersectRect, showErrorModal } from '../utils/utils'; import { CanvasManager } from './canvas_manager'; import { AccessNode, Connector, + ControlFlowBlock, + ControlFlowRegion, Edge, EntryNode, InterstateEdge, LoopRegion, Memlet, NestedSDFG, SDFG, SDFGElement, SDFGElementType, SDFGElements, SDFGNode, - ControlFlowRegion, State, Tasklet, drawSDFG, offset_sdfg, - offset_state + offset_state, } from './renderer_elements'; // External, non-typescript libraries which are presented as previously loaded @@ -70,9 +71,48 @@ declare const canvas2pdf: any; // Some global functions and variables which are only accessible within VSCode: declare const vscode: any | null; -type SDFGElementGroup = 'states' | 'nodes' | 'edges' | 'isedges'; +type SDFGElementGroup = ('states' | 'nodes' | 'edges' | 'isedges' | + 'connectors' | 'controlFlowRegions' | + 'controlFlowBlocks'); +interface SDFGElementInfo { + sdfg: JsonSDFG, + id: number, + cfgId: number, + stateId: number, + connector?: number, + conntype?: string, +} + +interface GraphElementInfo extends SDFGElementInfo { + graph: DagreGraph, + obj?: SDFGElement, +} + +interface JsonSDFGElementInfo extends SDFGElementInfo { + graph: JsonSDFGControlFlowRegion, + obj?: JsonSDFGElement, +} + +type GraphElemFunction = ( + elementGroup: SDFGElementGroup, + elementInfo: GraphElementInfo, + element: SDFGElement, +) => any; + +type JsonSDFGElemFunction = ( + elementGroup: SDFGElementGroup, + elementInfo: JsonSDFGElementInfo, + element: JsonSDFGElement, +) => any; + // If type is explicitly set, dagre typecheck fails with integer node ids -export type CFGListType = any[];//{ [key: number]: DagreSDFG }; +//export type CFGListType = any[];//{ [key: number]: DagreGraph }; +export type CFGListType = { + [id: string]: { + jsonObj: JsonSDFGControlFlowRegion, + graph: DagreGraph | null, + } +}; function check_valid_add_position( type: SDFGElementType | null, @@ -114,6 +154,7 @@ export interface SDFGRendererEvent { ) => void; } +/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ export interface SDFGRenderer { on( @@ -126,12 +167,13 @@ export interface SDFGRenderer { } +/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ export class SDFGRenderer extends EventEmitter { - protected cfg_list: any = {}; - protected graph: DagreSDFG | null = null; - // Parent-pointing SDFG tree. - protected sdfg_tree: { [key: number]: number } = {}; + protected cfgList: CFGListType = {}; + protected graph: DagreGraph | null = null; + // Parent-pointing CFG tree. + protected cfgTree: { [key: number]: number } = {}; // List of all state's parent elements. protected state_parent_list: any = {}; protected in_vscode: boolean = false; @@ -150,6 +192,7 @@ export class SDFGRenderer extends EventEmitter { protected bgcolor: string | null = null; protected visible_rect: SimpleRect | null = null; protected static cssProps: { [key: string]: string } = {}; + public static rendered_elements_count: number = 0; // Toolbar related fields. protected toolbar: JQuery | null = null; @@ -231,9 +274,9 @@ export class SDFGRenderer extends EventEmitter { this.init_elements(user_transform, background, mode_buttons); - this.set_sdfg(sdfg, false); + this.setSDFG(sdfg, false); - this.all_memlet_trees_sdfg = memlet_tree_complete(this.sdfg); + this.all_memlet_trees_sdfg = memletTreeComplete(this.sdfg); this.update_fast_memlet_lookup(); @@ -352,10 +395,11 @@ export class SDFGRenderer extends EventEmitter { this.movemode_btn.classList.add('selected'); if (this.interaction_info_box) this.interaction_info_box.style.display = 'block'; - if (this.interaction_info_text) + if (this.interaction_info_text) { this.interaction_info_text.innerHTML = 'Middle Mouse: Pan view
' + 'Right Click: Reset position'; + } break; case 'select': if (this.selectmode_btn) @@ -363,14 +407,15 @@ export class SDFGRenderer extends EventEmitter { if (this.interaction_info_box) this.interaction_info_box.style.display = 'block'; if (this.interaction_info_text) { - if (this.ctrl_key_selection) + if (this.ctrl_key_selection) { this.interaction_info_text.innerHTML = 'Middle Mouse: Pan view'; - else + } else { this.interaction_info_text.innerHTML = 'Shift: Add to selection
' + 'Ctrl: Remove from selection
' + 'Middle Mouse: Pan view'; + } } break; case 'add': @@ -378,16 +423,17 @@ export class SDFGRenderer extends EventEmitter { this.interaction_info_box.style.display = 'block'; if (this.interaction_info_text) { if (this.add_type === 'Edge') { - if (this.add_edge_start) + if (this.add_edge_start) { this.interaction_info_text.innerHTML = 'Left Click: Select second element (to)
' + 'Middle Mouse: Pan view
' + 'Right Click / Esc: Abort'; - else + } else { this.interaction_info_text.innerHTML = 'Left Click: Select first element (from)
' + 'Middle Mouse: Pan view
' + 'Right Click / Esc: Abort'; + } } else { this.interaction_info_text.innerHTML = 'Left Click: Place element
' + @@ -412,7 +458,6 @@ export class SDFGRenderer extends EventEmitter { background: string | null, mode_buttons: ModeButtons | undefined | null ): void { - this.canvas = document.createElement('canvas'); this.canvas.classList.add('sdfg_canvas'); if (background) @@ -464,7 +509,7 @@ export class SDFGRenderer extends EventEmitter { position: 'absolute', top: '10px', left: '10px', - } + }, }); this.container.appendChild(this.toolbar[0]); @@ -608,11 +653,10 @@ export class SDFGRenderer extends EventEmitter { html: 'unfold_less', title: 'Collapse next level (Shift+click to collapse all)', click: (e: MouseEvent) => { - if (e.shiftKey) { - this.collapse_all(); - } else { + if (e.shiftKey) + this.collapseAll(); + else this.collapseNextLevel(); - } }, }).appendTo(this.toolbar); @@ -622,11 +666,10 @@ export class SDFGRenderer extends EventEmitter { html: 'unfold_more', title: 'Expand next level (Shift+click to expand all)', click: (e: MouseEvent) => { - if (e.shiftKey) { - this.expand_all(); - } else { + if (e.shiftKey) + this.expandAll(); + else this.expandNextLevel(); - } }, }).appendTo(this.toolbar); @@ -690,7 +733,7 @@ export class SDFGRenderer extends EventEmitter { } // Enter pan mode - if (this.panmode_btn) + if (this.panmode_btn) { this.panmode_btn.onclick = () => { this.mouse_mode = 'pan'; this.add_type = null; @@ -699,6 +742,7 @@ export class SDFGRenderer extends EventEmitter { this.add_edge_start_conn = null; this.update_toggle_buttons(); }; + } // Enter object moving mode if (this.movemode_btn) { @@ -723,7 +767,7 @@ export class SDFGRenderer extends EventEmitter { } // Enter box selection mode - if (this.selectmode_btn) + if (this.selectmode_btn) { this.selectmode_btn.onclick = ( _: MouseEvent, ctrl_click: boolean | undefined = undefined ): void => { @@ -742,10 +786,11 @@ export class SDFGRenderer extends EventEmitter { ); this.update_toggle_buttons(); }; + } // React to ctrl and shift key presses - document.addEventListener('keydown', (e) => this.on_key_event(e)); - document.addEventListener('keyup', (e) => this.on_key_event(e)); + document.addEventListener('keydown', (e) => this.onKeyEvent(e)); + document.addEventListener('keyup', (e) => this.onKeyEvent(e)); document.addEventListener('visibilitychange', () => { this.clear_key_events(); }); @@ -760,7 +805,7 @@ export class SDFGRenderer extends EventEmitter { html: 'content_cut', title: 'Filter selection (cutout)', click: () => { - this.cutout_selection(); + this.cutoutSelection(); }, }).appendTo(this.toolbar); @@ -857,8 +902,9 @@ export class SDFGRenderer extends EventEmitter { this.bgcolor = window.getComputedStyle(this.canvas).backgroundColor; // Create the initial SDFG layout - // Loading animation already started in the file_read_complete function in sdfv.ts - // to also include the JSON parsing step. + // Loading animation already started in the file_read_complete function + // in sdfv.ts to also include the JSON parsing step. + this.updateCFGList(); this.relayout(); // Set mouse event handlers @@ -973,37 +1019,56 @@ export class SDFGRenderer extends EventEmitter { this.canvas_manager?.draw_async(); } - public set_sdfg(new_sdfg: JsonSDFG, layout: boolean = true): void { + public updateCFGList() { + // Update SDFG metadata + this.cfgTree = {}; + this.cfgList = {}; + this.cfgList[0] = { + jsonObj: this.sdfg, + graph: null, + }; + + this.doForAllSDFGElements( + (_oGroup, oInfo, obj) => { + const cfgId = (obj as JsonSDFGControlFlowRegion).cfg_list_id; + if (obj.type === SDFGElementType.NestedSDFG && + obj.attributes.sdfg) { + this.cfgTree[obj.attributes.sdfg.cfg_list_id] = + oInfo.sdfg.cfg_list_id; + } else if (cfgId !== undefined && cfgId >= 0) { + this.cfgTree[cfgId] = oInfo.cfgId; + this.cfgList[cfgId] = { + jsonObj: obj as JsonSDFGControlFlowRegion, + graph: null, + }; + } + } + ); + } + + public setSDFG(new_sdfg: JsonSDFG, layout: boolean = true): void { this.sdfg = new_sdfg; + // Update info box + if (this.selected_elements.length === 1) { + const uuid = getGraphElementUUID(this.selected_elements[0]); + if (this.graph) { + this.sdfv_instance.fill_info( + findGraphElementByUUID(this.cfgList, this.cfgTree, uuid) + ); + } + } + if (layout) { + this.updateCFGList(); + this.add_loading_animation(); setTimeout(() => { this.relayout(); }, 10); - - this.draw_async(); - } - // Update info box - if (this.selected_elements.length === 1) { - const uuid = get_uuid_graph_element(this.selected_elements[0]); - if (this.graph) - this.sdfv_instance.fill_info( - find_graph_element_by_uuid(this.graph, uuid).element - ); + this.draw_async(); } - - // Update SDFG metadata - this.sdfg_tree = {}; - this.for_all_sdfg_elements( - (otype: SDFGElementGroup, odict: any, obj: any) => { - if (obj.type === SDFGElementType.NestedSDFG && - obj.attributes.sdfg) - this.sdfg_tree[obj.attributes.sdfg.cfg_list_id] = - odict.sdfg.cfg_list_id; - } - ); } // Set mouse events (e.g., click, drag, zoom) @@ -1026,8 +1091,16 @@ export class SDFGRenderer extends EventEmitter { // Mouse handler event types for (const evtype of [ - 'mousedown', 'mousemove', 'mouseup', 'touchstart', 'touchmove', - 'touchend', 'wheel', 'click', 'dblclick', 'contextmenu' + 'mousedown', + 'mousemove', + 'mouseup', + 'touchstart', + 'touchmove', + 'touchend', + 'wheel', + 'click', + 'dblclick', + 'contextmenu', ]) { canvas?.addEventListener(evtype, x => { const cancelled = this.on_mouse_event( @@ -1058,9 +1131,8 @@ export class SDFGRenderer extends EventEmitter { this.all_memlet_trees = []; for (const tree of this.all_memlet_trees_sdfg) { const s = new Set(); - for (const edge of tree) { + for (const edge of tree) s.add(edge.attributes.data.edge); - } this.all_memlet_trees.push(s); } } @@ -1069,29 +1141,31 @@ export class SDFGRenderer extends EventEmitter { // Appends a div of class "loader" to task-info-field // and task-info-field-settings divs. public add_loading_animation() { - const info_field = document.getElementById('task-info-field'); if (info_field && info_field.innerHTML === '') { - const loaderDiv = document.createElement("div"); - loaderDiv.classList.add("loader"); + const loaderDiv = document.createElement('div'); + loaderDiv.classList.add('loader'); info_field.appendChild(loaderDiv); } - const info_field_settings = document.getElementById('task-info-field-settings'); + const info_field_settings = document.getElementById( + 'task-info-field-settings' + ); if (info_field_settings && info_field_settings.innerHTML === '') { - const loaderDiv = document.createElement("div"); - loaderDiv.classList.add("loader"); + const loaderDiv = document.createElement('div'); + loaderDiv.classList.add('loader'); info_field_settings.appendChild(loaderDiv); } } // Re-layout graph and nested graphs - public relayout(): DagreSDFG { + public relayout(): DagreGraph { if (!this.ctx) throw new Error('No context found while performing layouting'); - this.cfg_list = {}; + for (const cfgId in this.cfgList) + this.cfgList[cfgId].graph = null; this.graph = relayoutStateMachine( - this.ctx, this.sdfg, this.sdfg, this.cfg_list, + this.ctx, this.sdfg, this.sdfg, this.cfgList, this.state_parent_list, !SDFVSettings.showAccessNodes, undefined ); this.onresize(); @@ -1111,13 +1185,13 @@ export class SDFGRenderer extends EventEmitter { // Remove loading animation const info_field = document.getElementById('task-info-field'); - if (info_field) { - info_field.innerHTML = ""; - } - const info_field_settings = document.getElementById('task-info-field-settings'); - if (info_field_settings) { - info_field_settings.innerHTML = ""; - } + if (info_field) + info_field.innerHTML = ''; + const info_field_settings = document.getElementById( + 'task-info-field-settings' + ); + if (info_field_settings) + info_field_settings.innerHTML = ''; return this.graph; } @@ -1141,9 +1215,8 @@ export class SDFGRenderer extends EventEmitter { scope_dx += sp.scope_dx; scope_dy += sp.scope_dy; } - if (scope_entry_node) { + if (scope_entry_node) addScopeMovement(scope_entry_node); - } } } @@ -1162,12 +1235,13 @@ export class SDFGRenderer extends EventEmitter { if (dx || dy) { // Move the element - if (this.graph) + if (this.graph) { this.canvas_manager?.translate_element( node, { x: node.x, y: node.y }, { x: node.x + dx, y: node.y + dy }, this.graph, - this.cfg_list, this.state_parent_list, undefined, false + this.cfgList, this.state_parent_list, undefined, false ); + } } // Move edges (outgoing only) @@ -1196,13 +1270,14 @@ export class SDFGRenderer extends EventEmitter { } if (final_pos_d) { // Move the element - if (this.graph) + if (this.graph) { this.canvas_manager?.translate_element( edge, { x: 0, y: 0 }, - { x: 0, y: 0 }, this.graph, this.cfg_list, + { x: 0, y: 0 }, this.graph, this.cfgList, this.state_parent_list, undefined, false, false, final_pos_d ); + } } }); return true; @@ -1224,11 +1299,12 @@ export class SDFGRenderer extends EventEmitter { } let paddingAbs = 0; - if (padding > 0 && this.canvas) + if (padding > 0 && this.canvas) { paddingAbs = Math.min( (this.canvas.width / 100) * padding, (this.canvas.height / 100) * padding ); + } const bb = boundingBox(elements, paddingAbs); this.canvas_manager?.set_view(bb, animate); @@ -1267,47 +1343,56 @@ export class SDFGRenderer extends EventEmitter { return; function recursiveCollapse( - scopeNode: NestedSDFG | EntryNode | State, - parent: DagreSDFG + collapsible: NestedSDFG | EntryNode | ControlFlowBlock, + parentElement: SDFGElement | null, + graph: DagreGraph ): boolean { - if (scopeNode.attributes().is_collapsed) + if (collapsible.attributes().is_collapsed) return false; let collapsedSomething = false; - const scopeNodes = []; - let nParent = parent; - if (scopeNode instanceof NestedSDFG) { - for (const nid of scopeNode.data.graph.nodes()) - scopeNodes.push(scopeNode.data.graph.node(nid)); - nParent = scopeNode.data.graph; - } else if (scopeNode instanceof State) { - const scopeNodeIds = scopeNode.data.state.scope_dict[-1]; + const collapsibles = []; + const nParent = collapsible; + let nGraph = graph; + if (collapsible instanceof NestedSDFG || + collapsible instanceof ControlFlowRegion) { + for (const nid of collapsible.data.graph.nodes()) + collapsibles.push(collapsible.data.graph.node(nid)); + nGraph = collapsible.data.graph; + } else if (collapsible instanceof State) { + const scopeNodeIds = collapsible.data.state.scope_dict[-1]; for (const nid of scopeNodeIds) - scopeNodes.push(scopeNode.data.graph.node(nid)); - nParent = scopeNode.data.graph; + collapsibles.push(collapsible.data.graph.node(nid)); + nGraph = collapsible.data.graph; } else { - const parentState = scopeNode.sdfg.nodes[scopeNode.parent_id!]; - const scopeNodeIds = parentState.scope_dict[scopeNode.id]; - for (const nid of scopeNodeIds) - scopeNodes.push(parent.node(nid.toString())); + if (parentElement && parentElement instanceof State) { + const scopeNodeIds = parentElement.data.state.scope_dict[ + collapsible.id + ]; + for (const nid of scopeNodeIds) + collapsibles.push(graph.node(nid.toString())); + } } - for (const node of scopeNodes) { + for (const node of collapsibles) { if (node instanceof NestedSDFG || node instanceof State || - node instanceof EntryNode) { - const recursiveRes = recursiveCollapse(node, nParent); + node instanceof EntryNode || + node instanceof ControlFlowRegion) { + const recursiveRes = recursiveCollapse( + node, nParent, nGraph + ); collapsedSomething ||= recursiveRes; } } if (!collapsedSomething) - scopeNode.attributes().is_collapsed = true; + collapsible.attributes().is_collapsed = true; return true; } let collapsed = false; for (const sId of this.graph.nodes()) { const state = this.graph.node(sId); - const res = recursiveCollapse(state, this.graph); + const res = recursiveCollapse(state, null, this.graph); collapsed ||= res; } @@ -1315,7 +1400,7 @@ export class SDFGRenderer extends EventEmitter { this.emit('collapse_state_changed', false, true); this.add_loading_animation(); - // Use timeout function with low delay to force the browser + // Use timeout function with low delay to force the browser // to reload the dom with the above loader element. setTimeout(() => { this.relayout(); @@ -1325,9 +1410,9 @@ export class SDFGRenderer extends EventEmitter { } } - public collapse_all(): void { - this.for_all_sdfg_elements( - (_t: SDFGElementGroup, _d: any, obj: any) => { + public collapseAll(): void { + this.doForAllSDFGElements( + (_t, _d, obj) => { if ('is_collapsed' in obj.attributes && !obj.type.endsWith('Exit')) obj.attributes.is_collapsed = true; @@ -1337,7 +1422,7 @@ export class SDFGRenderer extends EventEmitter { this.emit('collapse_state_changed', true, true); this.add_loading_animation(); - // Use timeout function with low delay to force the browser + // Use timeout function with low delay to force the browser // to reload the dom with the above loader element. setTimeout(() => { this.relayout(); @@ -1351,7 +1436,7 @@ export class SDFGRenderer extends EventEmitter { return; traverseSDFGScopes( - this.graph, (node: SDFGNode, _: DagreSDFG) => { + this.graph, (node: SDFGNode, _: DagreGraph) => { if(node.attributes().is_collapsed) { node.attributes().is_collapsed = false; return false; @@ -1363,7 +1448,7 @@ export class SDFGRenderer extends EventEmitter { this.emit('collapse_state_changed', false, true); this.add_loading_animation(); - // Use timeout function with low delay to force the browser + // Use timeout function with low delay to force the browser // to reload the dom with the above loader element. setTimeout(() => { this.relayout(); @@ -1372,9 +1457,9 @@ export class SDFGRenderer extends EventEmitter { this.draw_async(); } - public expand_all(): void { - this.for_all_sdfg_elements( - (_t: SDFGElementGroup, _d: any, obj: any) => { + public expandAll(): void { + this.doForAllSDFGElements( + (_t, _d, obj) => { if ('is_collapsed' in obj.attributes && !obj.type.endsWith('Exit')) obj.attributes.is_collapsed = false; @@ -1384,7 +1469,7 @@ export class SDFGRenderer extends EventEmitter { this.emit('collapse_state_changed', false, true); this.add_loading_animation(); - // Use timeout function with low delay to force the browser + // Use timeout function with low delay to force the browser // to reload the dom with the above loader element. setTimeout(() => { this.relayout(); @@ -1394,8 +1479,8 @@ export class SDFGRenderer extends EventEmitter { } public reset_positions(): void { - this.for_all_sdfg_elements( - (_t: SDFGElementGroup, _d: any, obj: any) => { + this.doForAllSDFGElements( + (_t, _d, obj) => { deletePositioningInfo(obj); } ); @@ -1403,12 +1488,12 @@ export class SDFGRenderer extends EventEmitter { this.emit('element_position_changed', 'reset'); this.add_loading_animation(); - // Use timeout function with low delay to force the browser + // Use timeout function with low delay to force the browser // to reload the dom with the above loader element. setTimeout(() => { this.relayout(); }, 10); - + this.draw_async(); } @@ -1454,14 +1539,13 @@ export class SDFGRenderer extends EventEmitter { } public save_as_pdf(save_all = false): void { - this.add_loading_animation(); - // Use setTimeout to force browser to update the DOM with the above loading animation + // Use setTimeout to force browser to update the DOM with the above + // loading animation. setTimeout(() => { - const stream = blobStream(); - + // Compute document size const curx = this.canvas_manager?.mapPixelToCoordsX(0); const cury = this.canvas_manager?.mapPixelToCoordsY(0); @@ -1490,19 +1574,17 @@ export class SDFGRenderer extends EventEmitter { const curh = (endy ? endy : 0) - (cury ? cury : 0); size = [curw, curh]; } - - const ctx = new canvas2pdf.PdfContext(stream, { - size: size - }); + + const ctx = new canvas2pdf.PdfContext(stream, { size: size }); const oldctx = this.ctx; this.ctx = ctx; - - // Necessary for "what you see is what you get" in the exported pdf file + + // Necessary for "what you see is what you get" in the exported pdf + // file. if (!save_all && (oldctx as any).lod) { // User wants to save the view "as is" with details hidden (this.ctx as any).lod = true; - } - else { + } else { // User wants to save all details in the view (this.ctx as any).lod = false; } @@ -1510,23 +1592,25 @@ export class SDFGRenderer extends EventEmitter { // Center on saved region if (!save_all) this.ctx?.translate(-(curx ? curx : 0), -(cury ? cury : 0)); - + this.draw_async(); ctx.stream.on('finish', () => { const name = this.sdfg.attributes.name; - this.save(name + '.pdf', ctx.stream.toBlobURL('application/pdf')); + this.save( + name + '.pdf', ctx.stream.toBlobURL('application/pdf') + ); this.ctx = oldctx; this.draw_async(); // Remove loading animation const info_field = document.getElementById('task-info-field'); - if (info_field) { - info_field.innerHTML = ""; - } - const info_field_settings = document.getElementById('task-info-field-settings'); - if (info_field_settings) { - info_field_settings.innerHTML = ""; - } + if (info_field) + info_field.innerHTML = ''; + const info_field_settings = document.getElementById( + 'task-info-field-settings' + ); + if (info_field_settings) + info_field_settings.innerHTML = ''; }); }, 10); } @@ -1627,7 +1711,7 @@ export class SDFGRenderer extends EventEmitter { targetHeight = Math.floor(this.canvas.height * maxPercentage); if (targetWidth > this.canvas.width * maxPercentage) targetWidth = Math.floor(this.canvas.width * maxPercentage); - + // Prevent forced style reflow if nothing changed // Can save about 0.5ms of computation if (this.minimap_canvas.height !== targetHeight) { @@ -1665,7 +1749,7 @@ export class SDFGRenderer extends EventEmitter { // Don't draw Interstate edges in the minimap: // Small optimization thats can save ~1ms in computation - // The performance problem comes from the edges and their + // The performance problem comes from the edges and their // labels which are also drawn. // this.graph.edges().forEach(x => { @@ -1729,7 +1813,7 @@ export class SDFGRenderer extends EventEmitter { x: curx ? curx : 0, y: cury ? cury : 0, w: curw, - h: curh + h: curh, }; this.on_pre_draw(); @@ -1835,12 +1919,13 @@ export class SDFGRenderer extends EventEmitter { el_id = error.edge_id; } const sdfg_id = error.sdfg_id ?? 0; - const offending_element = find_graph_element_by_uuid( - this.graph, sdfg_id + '/' + state_id + '/' + el_id + '/-1' + const problemElem = findGraphElementByUUID( + this.cfgList, this.cfgTree, + sdfg_id + '/' + state_id + '/' + el_id + '/-1' ); - if (offending_element) { - if (offending_element.element) - this.zoom_to_view([offending_element.element]); + if (problemElem) { + if (problemElem && problemElem instanceof SDFGElement) + this.zoom_to_view([problemElem]); else this.zoom_to_view([]); @@ -1871,10 +1956,10 @@ export class SDFGRenderer extends EventEmitter { this.draw_async(); } - public visible_elements(): { + public getVisibleElements(): { type: string, - state_id: number, - sdfg_id: number, + stateId: number, + cfgId: number, id: number, }[] { if (!this.canvas_manager) @@ -1895,31 +1980,34 @@ export class SDFGRenderer extends EventEmitter { const elements: any[] = []; this.doForIntersectedElements( curx, cury, curw, curh, - (type: any, e: any, _obj: any) => { - const state_id = e.state ? Number(e.state) : -1; - let el_type = 'other'; - if (type === 'nodes') - el_type = 'node'; - else if (type === 'states') - el_type = 'state'; - else if (type === 'edges') - el_type = 'edge'; - else if (type === 'isedges') - el_type = 'isedge'; - else if (type === 'connectors') - el_type = 'connector'; + (group, objInfo, _obj) => { + let elType = 'other'; + if (group === 'nodes') + elType = 'node'; + else if (group === 'states') + elType = 'state'; + else if (group === 'edges') + elType = 'edge'; + else if (group === 'isedges') + elType = 'isedge'; + else if (group === 'connectors') + elType = 'connector'; + else if (group === 'controlFlowRegions') + elType = 'controlFlowRegion'; + else if (group === 'controlFlowBlocks') + elType = 'controlFlowBlock'; elements.push({ - type: el_type, - sdfg_id: Number(e.sdfg_id), - state_id: state_id, - id: Number(e.id), + type: elType, + cfgId: objInfo.cfgId, + stateId: objInfo.stateId, + id: objInfo.id, }); } ); return elements; } - public doForVisibleElements(func: CallableFunction): void { + public doForVisibleElements(func: GraphElemFunction): void { if (!this.canvas_manager) return; @@ -1942,53 +2030,71 @@ export class SDFGRenderer extends EventEmitter { // selection, rendering, localized transformations, etc. // The output is a dictionary of lists of dictionaries. The top-level keys // are: - // states, nodes, connectors, edges, isedges (interstate edges). + // states, controlFlowRegions, controlFlowBlocks, nodes, connectors, edges, + // isedges (interstate edges). // For example: // { // 'states': [{sdfg: sdfg_name, state: 1}, ...], - // 'nodes': [sdfg: sdfg_name, state: 1, node: 5], + // 'nodes': [{sdfg: sdfg_name, state: 1, node: 5}, ...], // 'edges': [], // 'isedges': [], // 'connectors': [], + // 'controlFlowRegions': [], + // 'controlFlowBlocks': [], // } - public elements_in_rect(x: number, y: number, w: number, h: number): any { + public elementsInRect( + x: number, y: number, w: number, h: number + ): { [key: string]: GraphElementInfo[] } { const elements: any = { - states: [], nodes: [], connectors: [], - edges: [], isedges: [] + states: [], + nodes: [], + connectors: [], + edges: [], + isedges: [], + controlFlowRegions: [], + controlFlowBlocks: [], }; this.doForIntersectedElements( - x, y, w, h, (type: string, e: any, obj: any) => { - e.obj = obj; - elements[type].push(e); + x, y, w, h, (group, objInfo, obj) => { + objInfo.obj = obj; + elements[group].push(objInfo); } ); return elements; } public doForIntersectedElements( - x: number, y: number, w: number, h: number, func: CallableFunction + x: number, y: number, w: number, h: number, func: GraphElemFunction ): void { if (!this.graph) return; // Traverse nested SDFGs recursively. - function traverseRecursive( - g: DagreSDFG, sdfgName: string, sdfgId: number + function doRecursive( + g: DagreGraph, cfg: JsonSDFGControlFlowRegion, sdfg: JsonSDFG ): void { - g.nodes().forEach((blockId: string) => { - const block: dagre.Node = g.node(blockId); + g.nodes().forEach((blockIdString: string) => { + const block: ControlFlowBlock = g.node(blockIdString); if (!block) return; + const blockId = Number(blockIdString); if (block.intersect(x, y, w, h)) { - // States - func( - 'states', - { - sdfg: sdfgName, sdfg_id: sdfgId, id: blockId - }, - block - ); + const elemInfo = { + sdfg: sdfg, + graph: g, + id: blockId, + cfgId: cfg.cfg_list_id, + stateId: -1, + }; + let elemGroup: SDFGElementGroup; + if (block instanceof State) + elemGroup = 'states'; + else if (block instanceof ControlFlowRegion) + elemGroup = 'controlFlowRegions'; + else + elemGroup = 'controlFlowBlocks'; + func(elemGroup, elemInfo, block); if (block.attributes().is_collapsed) return; @@ -1997,16 +2103,20 @@ export class SDFGRenderer extends EventEmitter { if (!ng) return; - if (block.type() === SDFGElementType.SDFGState) { - ng.nodes().forEach((node_id: string) => { - const node = ng.node(node_id); + if (block instanceof State) { + ng.nodes().forEach((nodeIdString: string) => { + const node = ng.node(nodeIdString); + const nodeId = Number(nodeIdString); if (node.intersect(x, y, w, h)) { // Selected nodes func( 'nodes', { - sdfg: sdfgName, sdfg_id: sdfgId, - state: blockId, id: node_id + sdfg: sdfg, + graph: ng, + id: nodeId, + cfgId: cfg.cfg_list_id, + stateId: blockId, }, node ); @@ -2014,40 +2124,48 @@ export class SDFGRenderer extends EventEmitter { // If nested SDFG, traverse recursively if (node.data.node.type === SDFGElementType.NestedSDFG && - node.attributes().sdfg) - traverseRecursive( - node.data.graph, - node.attributes().sdfg.attributes.name, - node.attributes().sdfg.cfg_list_id - ); + node.attributes().sdfg) { + const nsdfg = node.attributes().sdfg; + doRecursive(node.data.graph, nsdfg, nsdfg); + } } // Connectors node.in_connectors.forEach( (c: Connector, i: number) => { - if (c.intersect(x, y, w, h)) + if (c.intersect(x, y, w, h)) { func( 'connectors', { - sdfg: sdfgName, sdfg_id: sdfgId, - state: blockId, node: node_id, - connector: i, conntype: 'in' + sdfg: sdfg, + graph: ng, + id: nodeId, + cfgId: cfg.cfg_list_id, + stateId: blockId, + connector: i, + conntype: 'in', }, c ); + } } ); node.out_connectors.forEach( (c: Connector, i: number) => { - if (c.intersect(x, y, w, h)) + if (c.intersect(x, y, w, h)) { func( 'connectors', { - sdfg: sdfgName, sdfg_id: sdfgId, - state: blockId, node: node_id, - connector: i, conntype: 'out' + sdfg: sdfg, + graph: ng, + id: nodeId, + cfgId: cfg.cfg_list_id, + stateId: blockId, + connector: i, + conntype: 'out', }, c ); + } } ); }); @@ -2059,27 +2177,36 @@ export class SDFGRenderer extends EventEmitter { func( 'edges', { - sdfg: sdfgName, sdfg_id: sdfgId, - state: blockId, id: edge.id + sdfg: sdfg, + graph: g, + id: edge.id, + cfgId: cfg.cfg_list_id, + stateId: blockId, }, edge ); } }); } else { - traverseRecursive(block.data.graph, sdfgName, sdfgId); + doRecursive( + block.data.graph, block.data.block, sdfg + ); } } }); // Selected inter-state edges g.edges().forEach(isedge_id => { - const isedge = g.edge(isedge_id); + const isedge = g.edge(isedge_id) as InterstateEdge; if (isedge.intersect(x, y, w, h)) { func( 'isedges', { - sdfg: sdfgName, sdfg_id: sdfgId, id: isedge.id + sdfg: sdfg, + graph: g, + id: isedge.id, + cfgId: cfg.cfg_list_id, + stateId: -1, }, isedge ); @@ -2088,138 +2215,241 @@ export class SDFGRenderer extends EventEmitter { } // Start with top-level SDFG. - traverseRecursive( - this.graph, this.sdfg.attributes.name, this.sdfg.cfg_list_id - ); + doRecursive(this.graph, this.sdfg, this.sdfg); } - public for_all_sdfg_elements(func: CallableFunction): void { + public doForAllSDFGElements(func: JsonSDFGElemFunction): void { // Traverse nested SDFGs recursively - function traverse_recursive(sdfg: JsonSDFG) { - sdfg.nodes.forEach((state: JsonSDFGState, state_id: number) => { - // States - func('states', { sdfg: sdfg, id: state_id }, state); - - state.nodes.forEach((node: JsonSDFGNode, node_id: number) => { - // Nodes + function doRecursive(cfg: JsonSDFGControlFlowRegion, sdfg: JsonSDFG) { + cfg.nodes.forEach((block: JsonSDFGBlock, blockId: number) => { + if (block.type === SDFGElementType.SDFGState) { func( - 'nodes', - { - sdfg: sdfg, state: state_id, id: node_id - }, - node + 'states', { + sdfg: sdfg, + graph: cfg, + id: blockId, + cfgId: cfg.cfg_list_id, + stateId: -1, + }, block ); - // If nested SDFG, traverse recursively - if (node.type === SDFGElementType.NestedSDFG && - node.attributes.sdfg) - traverse_recursive(node.attributes.sdfg); - }); + const state: JsonSDFGState = block as JsonSDFGState; + state.nodes.forEach((node: JsonSDFGNode, nId: number) => { + // Nodes + func( + 'nodes', + { + sdfg: sdfg, + graph: cfg, + id: nId, + cfgId: cfg.cfg_list_id, + stateId: blockId, + }, + node + ); - // Edges - state.edges.forEach((edge: JsonSDFGEdge, edge_id: number) => { - func( - 'edges', - { - sdfg: sdfg, state: state_id, id: edge_id - }, - edge + // If nested SDFG, traverse recursively + if (node.type === SDFGElementType.NestedSDFG && + node.attributes.sdfg) { + doRecursive( + node.attributes.sdfg, node.attributes.sdfg + ); + } + }); + + // Edges + state.edges.forEach( + (edge: JsonSDFGEdge, edgeId: number) => { + func( + 'edges', + { + sdfg: sdfg, + graph: cfg, + id: edgeId, + cfgId: cfg.cfg_list_id, + stateId: blockId, + }, + edge + ); + } ); - }); + } else { + // Control flow region. + func('controlFlowRegions', { + sdfg: sdfg, + graph: cfg, + id: blockId, + cfgId: cfg.cfg_list_id, + stateId: -1, + }, block); + doRecursive(block as JsonSDFGControlFlowRegion, sdfg); + } }); // Selected inter-state edges - sdfg.edges.forEach((isedge: JsonSDFGEdge, isedge_id: number) => { - func('isedges', { sdfg: sdfg, id: isedge_id }, isedge); + cfg.edges.forEach((isedge: JsonSDFGEdge, isEdgeId: number) => { + func('isedges', { + sdfg: sdfg, + graph: cfg, + id: isEdgeId, + cfgId: cfg.cfg_list_id, + stateId: -1, + }, isedge); }); } // Start with top-level SDFG - traverse_recursive(this.sdfg); + doRecursive(this.sdfg, this.sdfg); } - public for_all_elements( - x: number, y: number, w: number, h: number, func: CallableFunction - ): void { + public doForAllGraphElements(func: GraphElemFunction): void { // Traverse nested SDFGs recursively - function traverse_recursive(g: DagreSDFG | null, sdfg_name: string) { - g?.nodes().forEach(state_id => { - const state: State = g.node(state_id); - if (!state) - return; - - // States - func( - 'states', - { - sdfg: sdfg_name, id: state_id, graph: g - }, - state - ); - - if (state.data.state.attributes.is_collapsed) + function doRecursive( + g: DagreGraph | null, cfg: JsonSDFGControlFlowRegion, sdfg: JsonSDFG + ) { + g?.nodes().forEach(blockIdString => { + const block: ControlFlowBlock = g.node(blockIdString); + if (!block) return; + const blockId = Number(blockIdString); - const ng = state.data.graph; - if (!ng) - return; - ng.nodes().forEach((node_id: string) => { - const node = ng.node(node_id); - // Selected nodes + if (block instanceof State) { + // States func( - 'nodes', + 'states', { - sdfg: sdfg_name, state: state_id, id: node_id, - graph: ng + sdfg: sdfg, + graph: g, + id: blockId, + cfgId: cfg.cfg_list_id, + stateId: -1, }, - node + block ); - // If nested SDFG, traverse recursively - if (node.data.node.type === SDFGElementType.NestedSDFG) - traverse_recursive( - node.data.graph, - node.data.node.attributes.sdfg.attributes.name + if (block.data.state.attributes.is_collapsed) + return; + + const ng = block.data.graph; + if (!ng) + return; + ng.nodes().forEach((nodeIdString: string) => { + const node = ng.node(nodeIdString); + const nodeId = Number(nodeIdString); + // Selected nodes + func( + 'nodes', + { + sdfg: sdfg, + graph: ng, + id: nodeId, + cfgId: cfg.cfg_list_id, + stateId: blockId, + }, + node ); - // Connectors - node.in_connectors.forEach((c: Connector, i: number) => { - func('connectors', { - sdfg: sdfg_name, state: state_id, node: node_id, - connector: i, conntype: 'in', graph: ng - }, c + // If nested SDFG, traverse recursively + if (node.data.node.type === + SDFGElementType.NestedSDFG) { + doRecursive( + node.data.graph, + node.data.node.attributes.sdfg, + node.data.node.attributes.sdfg + ); + } + + // Connectors + node.in_connectors.forEach( + (c: Connector, i: number) => { + func( + 'connectors', { + sdfg: sdfg, + graph: ng, + id: nodeId, + cfgId: cfg.cfg_list_id, + stateId: blockId, + connector: i, + conntype: 'in', + }, c + ); + } ); - }); - node.out_connectors.forEach((c: Connector, i: number) => { - func('connectors', { - sdfg: sdfg_name, state: state_id, node: node_id, - connector: i, conntype: 'out', graph: ng - }, c + node.out_connectors.forEach( + (c: Connector, i: number) => { + func( + 'connectors', { + sdfg: sdfg, + graph: ng, + id: nodeId, + cfgId: cfg.cfg_list_id, + stateId: blockId, + connector: i, + conntype: 'out', + }, c + ); + } ); }); - }); - // Selected edges - ng.edges().forEach((edge_id: number) => { - const edge = ng.edge(edge_id); + // Selected edges + ng.edges().forEach((edge_id: number) => { + const edge = ng.edge(edge_id); + func( + 'edges', + { + sdfg: sdfg, + graph: ng, + id: edge.id, + cfgId: cfg.cfg_list_id, + stateId: blockId, + }, + edge + ); + }); + } else if (block instanceof ControlFlowRegion) { + // Control Flow Regions. func( - 'edges', + 'controlFlowRegions', { - sdfg: sdfg_name, state: state_id, id: edge.id, - graph: ng + sdfg: sdfg, + graph: g, + id: blockId, + cfgId: cfg.cfg_list_id, + stateId: -1, }, - edge + block ); - }); + const ng = block.data.graph; + if (ng) + doRecursive(ng, block.data.block, sdfg); + } else { + // Other (unknown) control flow blocks. + func( + 'controlFlowBlocks', + { + sdfg: sdfg, + graph: g, + id: blockId, + cfgId: cfg.cfg_list_id, + stateId: -1, + }, + block + ); + } }); // Selected inter-state edges g?.edges().forEach(isedge_id => { - const isedge = g.edge(isedge_id); + const isedge = g.edge(isedge_id) as InterstateEdge; func( 'isedges', { - sdfg: sdfg_name, id: isedge.id, graph: g + sdfg: sdfg, + graph: g, + id: isedge.id, + cfgId: cfg.cfg_list_id, + stateId: -1, }, isedge ); @@ -2227,13 +2457,14 @@ export class SDFGRenderer extends EventEmitter { } // Start with top-level SDFG - traverse_recursive(this.graph, this.sdfg.attributes.name); + doRecursive(this.graph, this.sdfg, this.sdfg); } - public get_nested_memlet_tree(edge: Edge): Set { - for (const tree of this.all_memlet_trees) + public getNestedMemletTree(edge: Edge): Set { + for (const tree of this.all_memlet_trees) { if (tree.has(edge)) return tree; + } return new Set(); } @@ -2241,16 +2472,19 @@ export class SDFGRenderer extends EventEmitter { mouse_pos_x: number, mouse_pos_y: number ): any { // Find all elements under the cursor. - const elements = this.elements_in_rect(mouse_pos_x, mouse_pos_y, 0, 0); + const elements = this.elementsInRect(mouse_pos_x, mouse_pos_y, 0, 0); const clicked_states = elements.states; const clicked_nodes = elements.nodes; const clicked_edges = elements.edges; const clicked_interstate_edges = elements.isedges; const clicked_connectors = elements.connectors; + const clicked_cfg_regions = elements.controlFlowRegions; + const clicked_cfg_blocks = elements.controlFlowBlocks; const total_elements = clicked_states.length + clicked_nodes.length + clicked_edges.length + clicked_interstate_edges.length + - clicked_connectors.length; + clicked_connectors.length + clicked_cfg_regions.length + + clicked_cfg_blocks.length; let foreground_elem = null, foreground_surface = -1; let foreground_connector = null; @@ -2260,11 +2494,14 @@ export class SDFGRenderer extends EventEmitter { clicked_states, clicked_interstate_edges, clicked_nodes, - clicked_edges + clicked_edges, + clicked_cfg_regions, + clicked_cfg_blocks, ]; for (const category of categories) { for (let i = 0; i < category.length; i++) { - const s = category[i].obj.width * category[i].obj.height; + const obj = category[i].obj; + const s = obj!.width * obj!.height; if (foreground_surface < 0 || s < foreground_surface) { foreground_surface = s; foreground_elem = category[i].obj; @@ -2273,7 +2510,7 @@ export class SDFGRenderer extends EventEmitter { } for (const c of clicked_connectors) { - const s = c.obj.width * c.obj.height; + const s = c.obj!.width * c.obj!.height; if (foreground_surface < 0 || s < foreground_surface) { foreground_surface = s; foreground_connector = c.obj; @@ -2293,7 +2530,7 @@ export class SDFGRenderer extends EventEmitter { this.update_toggle_buttons(); } - public on_key_event(event: KeyboardEvent): boolean { + public onKeyEvent(event: KeyboardEvent): boolean { // Prevent handling of the event if the event is designed for something // other than the body, like an input element. if (event.target !== document.body) @@ -2330,25 +2567,37 @@ export class SDFGRenderer extends EventEmitter { for (const e of this.selected_elements) { if (e instanceof Connector) { continue; - } else if (e instanceof Edge) { - if (e.parent_id === null) - e.sdfg.edges = e.sdfg.edges.filter( + } else if (e instanceof Memlet) { + const state: JsonSDFGState = e.parentElem?.data.state; + if (state) { + state.edges = state.edges.filter( (_, ind: number) => ind !== e.id ); - else { - const state: JsonSDFGState = e.sdfg.nodes[e.parent_id]; - state.edges = state.edges.filter( + } + } else if (e instanceof InterstateEdge) { + if (!e.parentElem || + (e.parentElem && e.parentElem instanceof SDFG)) { + e.sdfg.edges = e.sdfg.edges.filter( (_, ind: number) => ind !== e.id ); + } else { + const tGraph = e.parentElem.data.block; + tGraph.edges = tGraph.edges.filter( + (_: any, ind: number) => ind !== e.id + ); } - } else if (e instanceof State) { - delete_sdfg_states(e.sdfg, [e.id]); + } else if (e instanceof ControlFlowBlock) { + if (e.parentElem && + e.parentElem instanceof ControlFlowRegion) + deleteCFGBlocks(e.parentElem.data.block, [e.id]); + else + deleteCFGBlocks(e.sdfg, [e.id]); } else { - delete_sdfg_nodes(e.sdfg, e.parent_id!, [e.id]); + deleteSDFGNodes(e.sdfg, e.parent_id!, [e.id]); } } this.deselect(); - this.set_sdfg(this.sdfg); + this.setSDFG(this.sdfg); this.emit('graph_edited'); } @@ -2369,16 +2618,18 @@ export class SDFGRenderer extends EventEmitter { } // Checks if pan mouse movement is in the bounds of the graph. - // Takes the current visible_rect as input and computes if its center is - // within the graph bounds. The pan mouse movement (movX, movY) is + // Takes the current visible_rect as input and computes if its center is + // within the graph bounds. The pan mouse movement (movX, movY) is // corrected accordingly to have a smooth view pan blocking. - // Returns: corrected movement x/y coordinates to input into this.canvas_manager?.translate() - public pan_movement_in_bounds(visible_rect: SimpleRect, movX: number, movY: number) { - + // Returns: corrected movement x/y coordinates to input into + // this.canvas_manager?.translate() + public pan_movement_in_bounds( + visible_rect: SimpleRect, movX: number, movY: number + ) { const visible_rectCenter = { x: (visible_rect.x + (visible_rect.w / 2)), - y: (visible_rect.y + (visible_rect.h / 2)) - } + y: (visible_rect.y + (visible_rect.h / 2)), + }; const graphLimits = { minX: 0, @@ -2392,35 +2643,30 @@ export class SDFGRenderer extends EventEmitter { let outofboundsX = 0; let outofboundsY = 0; - if (visible_rectCenter.x < graphLimits.minX) { + if (visible_rectCenter.x < graphLimits.minX) outofboundsX = -1; - } - else if (visible_rectCenter.x > graphLimits.maxX) { + else if (visible_rectCenter.x > graphLimits.maxX) outofboundsX = 1; - } - if (visible_rectCenter.y < graphLimits.minY) { + + if (visible_rectCenter.y < graphLimits.minY) outofboundsY = -1; - } - else if (visible_rectCenter.y > graphLimits.maxY) { + else if (visible_rectCenter.y > graphLimits.maxY) outofboundsY = 1; - } // Take uncorrected mouse event movement as default - let correctedMovement = { + const correctedMovement = { x: movX, - y: movY - } + y: movY, + }; // Correct mouse movement if necessary - if ((outofboundsX === -1 && correctedMovement.x > 0) || - (outofboundsX === 1 && correctedMovement.x < 0)) { + if ((outofboundsX === -1 && correctedMovement.x > 0) || + (outofboundsX === 1 && correctedMovement.x < 0)) correctedMovement.x = 0; - } - if ((outofboundsY === -1 && correctedMovement.y > 0) || - (outofboundsY === 1 && correctedMovement.y < 0)) { + if ((outofboundsY === -1 && correctedMovement.y > 0) || + (outofboundsY === 1 && correctedMovement.y < 0)) correctedMovement.y = 0; - } - + return correctedMovement; } @@ -2436,7 +2682,7 @@ export class SDFGRenderer extends EventEmitter { return false; if (this.ctrl_key_selection || this.shift_key_movement) - this.on_key_event(event); + this.onKeyEvent(event); let dirty = false; // Whether to redraw at the end // Whether the set of visible or selected elements changed @@ -2460,7 +2706,7 @@ export class SDFGRenderer extends EventEmitter { const old_mousepos = this.mousepos; this.mousepos = { x: comp_x_func(event), - y: comp_y_func(event) + y: comp_y_func(event), }; this.realmousepos = { x: event.clientX, y: event.clientY }; @@ -2498,7 +2744,7 @@ export class SDFGRenderer extends EventEmitter { // Do not move element individually if it is // moved together with its parent state const state_parent = - this.cfg_list[list_id].node( + this.cfgList[list_id].graph?.node( el.parent_id!.toString() ); if (state_parent && @@ -2515,15 +2761,16 @@ export class SDFGRenderer extends EventEmitter { const move_entire_edge = elements_to_move.length > 1; for (const el of elements_to_move) { - if (old_mousepos) + if (old_mousepos) { this.canvas_manager?.translate_element( el, old_mousepos, this.mousepos, - this.graph, this.cfg_list, + this.graph, this.cfgList, this.state_parent_list, this.drag_start, true, move_entire_edge ); + } } dirty = true; @@ -2553,12 +2800,10 @@ export class SDFGRenderer extends EventEmitter { // Mark for redraw dirty = true; } else { - // Mouse move in panning mode if (this.visible_rect) { - // Check if mouse panning is in bounds (near graph) - // and restrict/correct it + // and restrict/correct it. const correctedMovement = this.pan_movement_in_bounds( this.visible_rect, event.movementX, event.movementY ); @@ -2570,15 +2815,13 @@ export class SDFGRenderer extends EventEmitter { // Mark for redraw dirty = true; } - } } else if (this.drag_start && event.buttons & 4) { // Pan the view with the middle mouse button this.dragging = true; if (this.visible_rect) { - // Check if mouse panning is in bounds (near graph) - // and restrict/correct it + // and restrict/correct it. const correctedMovement = this.pan_movement_in_bounds( this.visible_rect, event.movementX, event.movementY ); @@ -2601,12 +2844,17 @@ export class SDFGRenderer extends EventEmitter { this.drag_start = event; } else if (event.touches.length === 1) { // Move/drag if (this.visible_rect) { - - const movX = event.touches[0].clientX - this.drag_start.touches[0].clientX; - const movY = event.touches[0].clientY - this.drag_start.touches[0].clientY; + const movX = ( + event.touches[0].clientX - + this.drag_start.touches[0].clientX + ); + const movY = ( + event.touches[0].clientY - + this.drag_start.touches[0].clientY + ); // Check if panning is in bounds (near graph) - // and restrict/correct it + // and restrict/correct it. const correctedMovement = this.pan_movement_in_bounds( this.visible_rect, movX, movY ); @@ -2640,13 +2888,12 @@ export class SDFGRenderer extends EventEmitter { const newCenter = [(x1 + x2) / 2.0, (y1 + y2) / 2.0]; if (this.visible_rect) { - // First, translate according to movement of center point const movX = newCenter[0] - oldCenter[0]; const movY = newCenter[1] - oldCenter[1]; // Check if movement is in bounds (near graph) - // and restrict/correct it + // and restrict/correct it. const correctedMovement = this.pan_movement_in_bounds( this.visible_rect, movX, movY ); @@ -2679,7 +2926,7 @@ export class SDFGRenderer extends EventEmitter { const movY = -event.deltaY; // Check if scroll is in bounds (near graph) - // and restrict/correct it + // and restrict/correct it. const correctedMovement = this.pan_movement_in_bounds( this.visible_rect, movX, movY ); @@ -2742,9 +2989,9 @@ export class SDFGRenderer extends EventEmitter { } else { // Hovering over an element while not in any specific mode. if ((foreground_elem.data.state && - foreground_elem.data.state.attributes.is_collapsed) || + foreground_elem.data.state.attributes.is_collapsed) || (foreground_elem.data.node && - foreground_elem.data.node.attributes.is_collapsed)) { + foreground_elem.data.node.attributes.is_collapsed)) { // This is a collapsed node or state, show with the // cursor shape that this can be expanded. this.canvas.style.cursor = 'alias'; @@ -2759,35 +3006,35 @@ export class SDFGRenderer extends EventEmitter { this.tooltip = null; - // Only do highlighting re-computation if view is close enough to actually see the - // highlights. Done by points-per-pixel metric using SDFV.NODE_LOD as the threshold. - // Hence, the highlights only update/become visible if there are nodes visible to hover over. - // This creatly reduces CPU utilization when moving/hovering the mouse over large graphs. + // Only do highlighting re-computation if view is close enough to + // actually see the highlights. Done by points-per-pixel metric using + // SDFV.NODE_LOD as the threshold. Hence, the highlights only + // update/become visible if there are nodes visible to hover over. This + // creatly reduces CPU utilization when moving/hovering the mouse over + // large graphs. if (this.canvas_manager) { const ppp = this.canvas_manager.points_per_pixel(); if (ppp < SDFV.NODE_LOD) { - // Global change boolean. Determines if repaint necessary. let highlighting_changed = false; // Mark hovered and highlighted elements. this.doForVisibleElements( - (type: any, e: any, obj: any) => { + (group, objInfo, obj) => { const intersected = obj.intersect( this.mousepos!.x, this.mousepos!.y, 0, 0 ); - // Local change boolean, for each visible element checked. - // Prevents recursion if nothing changed. + // Local change boolean, for each visible element + // checked. Prevents recursion if nothing changed. let hover_changed = false; - + // Change hover status if (intersected && !obj.hovered) { obj.hovered = true; highlighting_changed = true; hover_changed = true; - } - else if (!intersected && obj.hovered) { + } else if (!intersected && obj.hovered) { obj.hovered = false; highlighting_changed = true; hover_changed = true; @@ -2796,136 +3043,132 @@ export class SDFGRenderer extends EventEmitter { // Highlight all edges of the memlet tree if (obj instanceof Edge && obj.parent_id !== null) { if (obj.hovered && hover_changed) { - const tree = this.get_nested_memlet_tree(obj); + const tree = this.getNestedMemletTree(obj); tree.forEach(te => { - if (te !== obj && te !== undefined) { + if (te !== obj && te !== undefined) te.highlighted = true; - } }); - } - else if (!obj.hovered && hover_changed) { - const tree = this.get_nested_memlet_tree(obj); + } else if (!obj.hovered && hover_changed) { + const tree = this.getNestedMemletTree(obj); tree.forEach(te => { - if (te !== obj && te !== undefined) { + if (te !== obj && te !== undefined) te.highlighted = false; - } }); } } - - // Highlight all access nodes with the same name in the same - // nested sdfg + + // Highlight all access nodes with the same name in the + // same nested sdfg. if (obj instanceof AccessNode) { if (obj.hovered && hover_changed) { traverseSDFGScopes( - this.cfg_list[obj.sdfg.cfg_list_id], + this.cfgList[obj.sdfg.cfg_list_id].graph!, (node: any) => { - // If node is a state, then visit sub-scope + // If node is a state, then visit + // sub-scope. if (node instanceof State) return true; if (node instanceof AccessNode && - node.data.node.label === obj.data.node.label) { + node.data.node.label === + obj.data.node.label) node.highlighted = true; - } // No need to visit sub-scope return false; } ); - } - else if (!obj.hovered && hover_changed) { + } else if (!obj.hovered && hover_changed) { traverseSDFGScopes( - this.cfg_list[obj.sdfg.cfg_list_id], + this.cfgList[obj.sdfg.cfg_list_id].graph!, (node: any) => { - // If node is a state, then visit sub-scope + // If node is a state, then visit + // sub-scope. if (node instanceof State) return true; if (node instanceof AccessNode && - node.data.node.label === obj.data.node.label) { + node.data.node.label === + obj.data.node.label) node.highlighted = false; - } // No need to visit sub-scope return false; } ); } } - + if (obj instanceof Connector) { - // Highlight all access nodes with the same name as the - // hovered connector in the nested sdfg + // Highlight all access nodes with the same name as + // the hovered connector in the nested sdfg. if (obj.hovered && hover_changed) { - if (e.graph) { - const nested_graph = - e.graph.node(obj.parent_id).data.graph; - if (nested_graph) { - traverseSDFGScopes(nested_graph, (node: any) => { - // If node is a state, then visit sub-scope - if (node instanceof State) { - return true; - } - if (node instanceof AccessNode && - node.data.node.label === obj.label()) { - node.highlighted = true; - } - // No need to visit sub-scope - return false; - }); - } + const nGraph = obj.parentElem?.data.graph; + if (nGraph) { + traverseSDFGScopes(nGraph, (node: any) => { + // If node is a state, then visit + // sub-scope. + if (node instanceof State || + node instanceof ControlFlowRegion) + return true; + + if (node instanceof AccessNode && + node.data.node.label === + obj.label()) + node.highlighted = true; + // No need to visit sub-scope + return false; + }); } - } - else if (!obj.hovered && hover_changed) { - if (e.graph) { - const nested_graph = - e.graph.node(obj.parent_id).data.graph; - if (nested_graph) { - traverseSDFGScopes(nested_graph, (node: any) => { - // If node is a state, then visit sub-scope - if (node instanceof State) { - return true; - } - if (node instanceof AccessNode && - node.data.node.label === obj.label()) { - node.highlighted = false; - } - // No need to visit sub-scope - return false; - }); - } + } else if (!obj.hovered && hover_changed) { + const nGraph = obj.parentElem?.data.graph; + if (nGraph) { + traverseSDFGScopes(nGraph, (node: any) => { + // If node is a state, then visit + // sub-scope. + if (node instanceof State || + node instanceof ControlFlowRegion) + return true; + + if (node instanceof AccessNode && + node.data.node.label === + obj.label()) + node.highlighted = false; + // No need to visit sub-scope + return false; + }); } } - - // Similarly, highlight any identifiers in a connector's - // tasklet, if applicable. + + // Similarly, highlight any identifiers in a + // connector's tasklet, if applicable. if (obj.hovered && hover_changed) { - if (obj.linkedElem && obj.linkedElem instanceof Tasklet) { + if (obj.linkedElem && obj.linkedElem instanceof + Tasklet) { if (obj.connectorType === 'in') { - for (const token of obj.linkedElem.inputTokens) { - if (token.token === obj.data.name) { + for (const token of + obj.linkedElem.inputTokens) { + if (token.token === obj.data.name) token.highlighted = true; - } } } else { - for (const token of obj.linkedElem.outputTokens) { - if (token.token === obj.data.name) { + for (const token of + obj.linkedElem.outputTokens) { + if (token.token === obj.data.name) token.highlighted = true; - } } } } - } - else if (!obj.hovered && hover_changed) { - if (obj.linkedElem && obj.linkedElem instanceof Tasklet) { + } else if (!obj.hovered && hover_changed) { + if (obj.linkedElem && obj.linkedElem instanceof + Tasklet) { if (obj.connectorType === 'in') { - for (const token of obj.linkedElem.inputTokens) { - if (token.token === obj.data.name) { + for (const token of + obj.linkedElem.inputTokens) { + if (token.token === obj.data.name) token.highlighted = false; - } } } else { - for (const token of obj.linkedElem.outputTokens) { - if (token.token === obj.data.name) { + for (const token of + obj.linkedElem.outputTokens) { + if (token.token === obj.data.name) token.highlighted = false; - } } } } @@ -2934,10 +3177,8 @@ export class SDFGRenderer extends EventEmitter { } ); - if (highlighting_changed) { + if (highlighting_changed) dirty = true; - } - } } @@ -2957,26 +3198,32 @@ export class SDFGRenderer extends EventEmitter { if (evtype === 'dblclick') { const sdfg = (foreground_elem ? foreground_elem.sdfg : null); let sdfg_elem = null; - if (foreground_elem instanceof State) + if (foreground_elem instanceof State) { sdfg_elem = foreground_elem.data.state; - else if (foreground_elem instanceof ControlFlowRegion) + } else if (foreground_elem instanceof ControlFlowRegion) { sdfg_elem = foreground_elem.data.block; - else if (foreground_elem instanceof SDFGNode) { + } else if (foreground_elem instanceof SDFGNode) { sdfg_elem = foreground_elem.data.node; // If a scope exit node, use entry instead if (sdfg_elem.type.endsWith('Exit') && - foreground_elem.parent_id !== null) + foreground_elem.parent_id !== null) { sdfg_elem = sdfg.nodes[foreground_elem.parent_id].nodes[ sdfg_elem.scope_entry ]; - } else + } + } else { sdfg_elem = null; + } // Toggle collapsed state - if (sdfg_elem && 'is_collapsed' in sdfg_elem.attributes) { - sdfg_elem.attributes.is_collapsed = - !sdfg_elem.attributes.is_collapsed; + if (foreground_elem.COLLAPSIBLE) { + if ('is_collapsed' in sdfg_elem.attributes) { + sdfg_elem.attributes.is_collapsed = + !sdfg_elem.attributes.is_collapsed; + } else { + sdfg_elem.attributes['is_collapsed'] = true; + } this.emit('collapse_state_changed'); @@ -3012,7 +3259,7 @@ export class SDFGRenderer extends EventEmitter { const w = end_x - start_x; const h = end_y - start_y; this.doForIntersectedElements(start_x, start_y, w, h, - (type: any, e: any, obj: any) => { + (_group, _objInfo, obj) => { if (obj.contained_in(start_x, start_y, w, h)) elements_in_selection.push(obj); }); @@ -3043,9 +3290,8 @@ export class SDFGRenderer extends EventEmitter { multi_selection_changed = true; } - if (this.mouse_mode === 'move') { + if (this.mouse_mode === 'move') this.emit('element_position_changed', 'manual_move'); - } } else { if (this.mouse_mode === 'add') { if (check_valid_add_position( @@ -3059,11 +3305,11 @@ export class SDFGRenderer extends EventEmitter { this.emit( 'add_element', this.add_type, - get_uuid_graph_element( + getGraphElementUUID( foreground_elem ), undefined, - get_uuid_graph_element(start), + getGraphElementUUID(start), this.add_edge_start_conn ? this.add_edge_start_conn.data.name : undefined, @@ -3082,27 +3328,28 @@ export class SDFGRenderer extends EventEmitter { this.emit( 'add_element', this.add_type, - get_uuid_graph_element( + getGraphElementUUID( foreground_elem ), this.add_mode_lib || undefined ); } else { this.add_position = this.mousepos; - if (this.add_type) + if (this.add_type) { this.emit( 'add_element', this.add_type, - get_uuid_graph_element( + getGraphElementUUID( foreground_elem ) ); + } } if (!event.ctrlKey && !( - this.add_type === SDFGElementType.Edge && - this.add_edge_start - )) { + this.add_type === SDFGElementType.Edge && + this.add_edge_start + )) { // Cancel add mode. if (this.panmode_btn?.onclick) this.panmode_btn.onclick(event); @@ -3192,7 +3439,7 @@ export class SDFGRenderer extends EventEmitter { ) { new_points[j] = { dx: - position.points[j].dx, - dy: - position.points[j].dy + dy: - position.points[j].dy, }; // Reset the point movement position.points[j].dx = 0; @@ -3202,7 +3449,7 @@ export class SDFGRenderer extends EventEmitter { // Move it to original position this.canvas_manager?.translate_element( edge_el, { x: 0, y: 0 }, { x: 0, y: 0 }, - this.graph, this.cfg_list, + this.graph, this.cfgList, this.state_parent_list, undefined, false, false, new_points ); @@ -3224,7 +3471,7 @@ export class SDFGRenderer extends EventEmitter { this.canvas_manager?.translate_element( el, { x: el.x, y: el.y }, { x: new_x, y: new_y }, this.graph, - this.cfg_list, this.state_parent_list, + this.cfgList, this.state_parent_list, undefined, false, false, undefined ); @@ -3248,13 +3495,11 @@ export class SDFGRenderer extends EventEmitter { this.relayout(); }, 10); } - + this.draw_async(); - if (element_moved) { + if (element_moved) this.emit('element_position_changed', 'manual_move'); - } - } else if (this.mouse_mode === 'add') { // Cancel add mode if (this.panmode_btn?.onclick) @@ -3285,10 +3530,8 @@ export class SDFGRenderer extends EventEmitter { dirty = dirty || ol_manager_dirty; } - if (dirty) { - + if (dirty) this.draw_async(); - } if (element_focus_changed || selection_changed) this.emit('selection_changed', multi_selection_changed); @@ -3332,7 +3575,15 @@ export class SDFGRenderer extends EventEmitter { return this.sdfg; } - public get_graph(): DagreSDFG | null { + public getCFGList(): CFGListType { + return this.cfgList; + } + + public getCFGTree(): { [key: number]: number} { + return this.cfgTree; + } + + public get_graph(): DagreGraph | null { return this.graph; } @@ -3427,7 +3678,7 @@ export class SDFGRenderer extends EventEmitter { // Transition to the local view by first cutting out the selection. try { - this.cutout_selection(true); + this.cutoutSelection(true); const lRenderer = new LViewRenderer(this.sdfv_instance, this.container); const lGraph = await LViewParser.parseGraph(this.graph, lRenderer); @@ -3454,15 +3705,14 @@ export class SDFGRenderer extends EventEmitter { this.sdfv_instance.setLocalViewRenderer(lRenderer); } } catch (e) { - if (e instanceof LViewGraphParseError) { + if (e instanceof LViewGraphParseError) showErrorModal(e.message); - } else { + else throw e; - } } } - public cutout_selection(_suppressSave: boolean = false): void { + public cutoutSelection(_suppressSave: boolean = false): void { /* Rule set for creating a cutout subgraph: * Edges are selected according to the subgraph nodes - all edges * between subgraph nodes are preserved. @@ -3472,73 +3722,124 @@ export class SDFGRenderer extends EventEmitter { * nodes from two states), the parents will be preserved. */ // Collect nodes and states - const sdfgs: Set = new Set(); - const cfg_list: { [key: string]: JsonSDFG } = {}; - const states: { [key: string]: Array } = {}; - const nodes: { [key: string]: Array } = {}; + const cfgs: Set = new Set(); + const blocks: { [key: string]: Set } = {}; + const nodes: { [key: string]: Set } = {}; + + function addCutoutNode(cfgId: number, node: SDFGNode): void { + const stateId = node.parent_id ?? -1; + const stateUUID: string = JSON.stringify([cfgId, stateId]); + if (stateUUID in nodes) + nodes[stateUUID].add(node.id); + else + nodes[stateUUID] = new Set([node.id]); + blocks[cfgId].add(stateId); + } + + function addCutoutState(cfgId: number, state: State): void { + // Add all nodes from the state to the filter. + const uuid: string = JSON.stringify([cfgId, state.id]); + nodes[uuid] = new Set([...state.data.state.nodes.keys()]); + blocks[cfgId].add(state.id); + } + + function addCutoutCFG(cfgId: number, cfgNode: ControlFlowRegion): void { + // Add all contents of the CFG. + const cfg: JsonSDFGControlFlowRegion = cfgNode.data.block; + const ownCfgId = cfg.cfg_list_id; + cfgs.add(ownCfgId); + if (!(ownCfgId in blocks)) + blocks[ownCfgId] = new Set(); + + if (cfgNode.data.graph) { + for (const blockId of cfgNode.data.block.nodes.keys()) { + const block = cfgNode.data.graph.node(blockId); + if (block instanceof ControlFlowRegion) { + const nCfgId = block.data.block.cfg_list_id; + cfgs.add(nCfgId); + addCutoutCFG(ownCfgId, block); + } else { + addCutoutState(ownCfgId, block); + } + } + } else { + for (const blockId of cfgNode.data.block.nodes.keys()) + blocks[ownCfgId].add(blockId); + } + + blocks[cfgId].add(cfgNode.id); + } + for (const elem of this.selected_elements) { // Ignore edges and connectors if (elem instanceof Edge || elem instanceof Connector) continue; - const sdfg_id = elem.sdfg.cfg_list_id; - cfg_list[sdfg_id] = elem.sdfg; - sdfgs.add(sdfg_id); - let state_id: number = -1; - if (elem.parent_id !== null) { - const state_uid: string = JSON.stringify( - [sdfg_id, elem.parent_id] - ); - if (state_uid in nodes) - nodes[state_uid].push(elem.id); - else - nodes[state_uid] = [elem.id]; - state_id = elem.parent_id; - } else { - // Add all nodes from state - const state_uid: string = JSON.stringify([sdfg_id, elem.id]); - nodes[state_uid] = [...elem.data.state.nodes.keys()]; - state_id = elem.id; - } - // Register state - if (sdfg_id in states) - states[sdfg_id].push(state_id); + + const cfg = elem.cfg!; + const cfgId = cfg.cfg_list_id; + cfgs.add(cfgId); + if (!(cfgId in blocks)) + blocks[cfgId] = new Set(); + + if (elem instanceof ControlFlowRegion) + addCutoutCFG(cfgId, elem); + else if (elem instanceof State) + addCutoutState(cfgId, elem); else - states[sdfg_id] = [state_id]; + addCutoutNode(cfgId, elem); } // Clear selection and redraw this.deselect(); - if (Object.keys(nodes).length === 0) { // Nothing to cut out + if (Object.keys(nodes).length + Object.keys(blocks).length === 0) { + // Nothing to cut out this.draw_async(); return; } // Find root SDFG and root state (if possible) - const root_sdfg_id = find_root_sdfg(sdfgs, this.sdfg_tree); - if (root_sdfg_id !== null) { - const root_sdfg = cfg_list[root_sdfg_id]; + const rootCFGId = findRootCFG(cfgs, this.cfgTree, this.cfgList, false); + const rootSDFGId = findRootCFG( + cfgs, this.cfgTree, this.cfgList, true + ); + const needToFlatten = rootSDFGId !== rootCFGId; + if (rootSDFGId !== null && rootCFGId !== null) { + const rootSDFG = this.cfgList[rootSDFGId].jsonObj; + const rootCFG = this.cfgList[rootCFGId].jsonObj; + if (rootSDFG.type !== 'SDFG') + throw Error('Cutout needs root CFG of type SDFG'); // For every participating state, filter out irrelevant nodes and // memlets. for (const nkey of Object.keys(nodes)) { - const [sdfg_id, state_id] = JSON.parse(nkey); - const sdfg = cfg_list[sdfg_id]; - delete_sdfg_nodes(sdfg, state_id, nodes[nkey], true); + const [cfgId, stateId] = JSON.parse(nkey); + const cfg = this.cfgList[cfgId].jsonObj; + deleteSDFGNodes( + cfg, stateId, Array.from(nodes[nkey].values()), true + ); } - // For every participating SDFG, filter out irrelevant states and + // For every participating CFG, filter out irrelevant states and // interstate edges. - for (const sdfg_id of Object.keys(states)) { - const sdfg = cfg_list[sdfg_id]; - delete_sdfg_states(sdfg, states[sdfg_id], true); + for (const cfgId of Object.keys(blocks)) { + const cfg = this.cfgList[cfgId].jsonObj; + deleteCFGBlocks(cfg, Array.from(blocks[cfgId].values()), true); + } + + // Ensure that the cutout contains only what is being cut out of + // the target root CFG. The root SDFG is used to piggyback in the + // necessary SDFG information. + if (needToFlatten) { + rootSDFG.nodes = rootCFG.nodes; + rootSDFG.edges = rootCFG.edges; } // Set root SDFG as the new SDFG - this.set_sdfg(root_sdfg); + this.setSDFG(rootSDFG as JsonSDFG); } - } + } @@ -3551,10 +3852,11 @@ function calculateNodeSize( label = node.label; if (SDFVSettings.showDataDescriptorSizes) { const nodedesc = sdfg.attributes._arrays[label]; - if (nodedesc && nodedesc.attributes.shape) + if (nodedesc && nodedesc.attributes.shape) { label = ' ' + sdfg_property_to_string( nodedesc.attributes.shape ); + } } break; default: @@ -3608,22 +3910,19 @@ function calculateNodeSize( return size; } -type StateMachineType = { - nodes: JsonSDFGBlock[]; - edges: JsonSDFGEdge[]; -}; - function relayoutStateMachine( - ctx: CanvasRenderingContext2D, stateMachine: StateMachineType, - sdfg: JsonSDFG, sdfgList: CFGListType, stateParentList: any[], + ctx: CanvasRenderingContext2D, stateMachine: JsonSDFGControlFlowRegion, + sdfg: JsonSDFG, cfgList: CFGListType, stateParentList: any[], omitAccessNodes: boolean, parent?: SDFGElement -): DagreSDFG { +): DagreGraph { const BLOCK_MARGIN = 3 * SDFV.LINEHEIGHT; // Layout the state machine as a dagre graph. - const g: DagreSDFG = new dagre.graphlib.Graph(); + const g: DagreGraph = new dagre.graphlib.Graph(); g.setGraph({}); - g.setDefaultEdgeLabel(() => { return {}; }); + g.setDefaultEdgeLabel(() => { + return {}; + }); if (!parent) parent = new SDFG(sdfg); @@ -3643,7 +3942,8 @@ function relayoutStateMachine( const btype = block.type === SDFGElementType.SDFGState ? 'State' : block.type; const blockElem = new SDFGElements[btype]( - { layout: { width: 0, height: 0 } }, block.id, sdfg, null, parent + { layout: { width: 0, height: 0 } }, block.id, sdfg, stateMachine, + null, parent ); if (block.type === SDFGElementType.SDFGState || block.type === SDFGElementType.ContinueState || @@ -3683,7 +3983,7 @@ function relayoutStateMachine( } } else { blockGraph = relayoutSDFGBlock( - ctx, block, sdfg, sdfgList, stateParentList, omitAccessNodes, + ctx, block, sdfg, cfgList, stateParentList, omitAccessNodes, blockElem ); if (blockGraph) @@ -3713,8 +4013,8 @@ function relayoutStateMachine( for (let id = 0; id < stateMachine.edges.length; id++) { const edge = stateMachine.edges[id]; g.setEdge(edge.src, edge.dst, new InterstateEdge( - edge.attributes.data, id, sdfg, parent.id, parent, edge.src, - edge.dst + edge.attributes.data, id, sdfg, stateMachine, parent.id, parent, + edge.src, edge.dst )); } @@ -3768,7 +4068,7 @@ function relayoutStateMachine( if (block.type === SDFGElementType.SDFGState) { offset_state(block as JsonSDFGState, gBlock, { x: topleft.x + BLOCK_MARGIN, - y: topleft.y + BLOCK_MARGIN + y: topleft.y + BLOCK_MARGIN, }); } else { // Base spacing for the inside. @@ -3794,19 +4094,19 @@ function relayoutStateMachine( (g as any).width = bb.width; (g as any).height = bb.height; - // Add SDFG to global store. - sdfgList[sdfg.cfg_list_id] = g; + // Add CFG graph to global store. + cfgList[stateMachine.cfg_list_id].graph = g; return g; } function relayoutSDFGState( ctx: CanvasRenderingContext2D, state: JsonSDFGState, - sdfg: JsonSDFG, sdfgList: JsonSDFG[], stateParentList: any[], + sdfg: JsonSDFG, sdfgList: CFGListType, stateParentList: any[], omitAccessNodes: boolean, parent: State -): DagreSDFG | null { +): DagreGraph | null { // layout the sdfg block as a dagre graph. - const g: DagreSDFG = new dagre.graphlib.Graph({ multigraph: true }); + const g: DagreGraph = new dagre.graphlib.Graph({ multigraph: true }); // Set layout options and a simpler algorithm for large graphs. const layoutOptions: any = { ranksep: 30 }; @@ -3816,7 +4116,9 @@ function relayoutSDFGState( g.setGraph(layoutOptions); // Set an object for the graph label. - g.setDefaultEdgeLabel(() => { return {}; }); + g.setDefaultEdgeLabel(() => { + return {}; + }); // Add nodes to the graph. The first argument is the node id. The // second is metadata about the node (label, width, height), @@ -3843,16 +4145,18 @@ function relayoutSDFGState( node.attributes.layout = {}; // Set connectors prior to computing node size - node.attributes.layout.in_connectors = node.attributes.in_connectors ?? []; + node.attributes.layout.in_connectors = + node.attributes.in_connectors ?? []; if ('is_collapsed' in node.attributes && node.attributes.is_collapsed && node.type !== SDFGElementType.NestedSDFG && - node.type !== SDFGElementType.ExternalNestedSDFG) - node.attributes.layout.out_connectors = find_exit_for_entry( + node.type !== SDFGElementType.ExternalNestedSDFG) { + node.attributes.layout.out_connectors = findExitForEntry( state.nodes, node )?.attributes.out_connectors ?? []; - else + } else { node.attributes.layout.out_connectors = node.attributes.out_connectors ?? []; + } const nodeSize = calculateNodeSize(sdfg, node, ctx); node.attributes.layout.width = nodeSize.width; @@ -3884,7 +4188,8 @@ function relayoutSDFGState( // Dynamically create node type. const obj = new SDFGElements[node.type]( - { node: node, graph: nestedGraph }, node.id, sdfg, state.id, parent + { node: node, graph: nestedGraph }, node.id, sdfg, parent.cfg, + state.id, parent ); // If it's a nested SDFG, we need to record the node as all of its @@ -3902,7 +4207,9 @@ function relayoutSDFGState( else conns = Object.keys(node.attributes.layout.in_connectors); for (const cname of conns) { - const conn = new Connector({ name: cname }, i, sdfg, node.id); + const conn = new Connector( + { name: cname }, i, sdfg, parent.cfg, node.id, obj + ); conn.connectorType = 'in'; conn.linkedElem = obj; obj.in_connectors.push(conn); @@ -3916,7 +4223,9 @@ function relayoutSDFGState( else conns = Object.keys(node.attributes.layout.out_connectors); for (const cname of conns) { - const conn = new Connector({ name: cname }, i, sdfg, node.id); + const conn = new Connector( + { name: cname }, i, sdfg, parent.cfg, node.id, obj + ); conn.connectorType = 'out'; conn.linkedElem = obj; obj.out_connectors.push(conn); @@ -3981,7 +4290,9 @@ function relayoutSDFGState( if (!edge) return; - const e = new Memlet(edge.attributes.data, id, sdfg, state.id); + const e = new Memlet( + edge.attributes.data, id, sdfg, parent.cfg, state.id, parent + ); edge.attributes.data.edge = e; (e as any).src_connector = edge.src_connector; (e as any).dst_connector = edge.dst_connector; @@ -4007,7 +4318,8 @@ function relayoutSDFGState( const redirectedEdge = check_and_redirect_edge( shortCutEdge, drawnNodes, state ); - if (!redirectedEdge) return; + if (!redirectedEdge) + return; // Abort if shortcut edge already exists. const edges = g.outEdges(redirectedEdge.src); @@ -4017,9 +4329,8 @@ function relayoutSDFGState( state.edges[ parseInt(oe.name) ].dst_connector === e.dst_connector - ) { + ) return; - } } } @@ -4030,7 +4341,7 @@ function relayoutSDFGState( const edgeId = state.edges.length - 1; const newShortCutEdge = new Memlet( deepCopy(redirectedEdge.attributes.data), edgeId, sdfg, - state.id + parent.cfg, state.id ); (newShortCutEdge as any).src_connector = redirectedEdge.src_connector; @@ -4059,10 +4370,9 @@ function relayoutSDFGState( // Offset nested SDFG. if (node.type === SDFGElementType.NestedSDFG && node.attributes.sdfg) { - offset_sdfg(node.attributes.sdfg, gnode.data.graph, { x: topleft.x + SDFV.LINEHEIGHT, - y: topleft.y + SDFV.LINEHEIGHT + y: topleft.y + SDFV.LINEHEIGHT, }); } // Write back layout information. @@ -4097,12 +4407,13 @@ function relayoutSDFGState( state.edges.forEach((edge: JsonSDFGEdge, id: number) => { const nedge = check_and_redirect_edge(edge, drawnNodes, state); - if (!nedge) return; + if (!nedge) + return; edge = nedge; const gedge = g.edge(edge.src, edge.dst, id.toString()); if (!gedge || (omitAccessNodes && - gedge.data.attributes.shortcut === false - || !omitAccessNodes && gedge.data.attributes.shortcut)) { + gedge.data.attributes.shortcut === false || + !omitAccessNodes && gedge.data.attributes.shortcut)) { // If access nodes omitted, don't draw non-shortcut edges and // vice versa. return; @@ -4177,15 +4488,15 @@ function relayoutSDFGState( function relayoutSDFGBlock( ctx: CanvasRenderingContext2D, block: JsonSDFGBlock, - sdfg: JsonSDFG, sdfgList: JsonSDFG[], stateParentList: any[], + sdfg: JsonSDFG, sdfgList: CFGListType, stateParentList: any[], omitAccessNodes: boolean, parent: SDFGElement -): DagreSDFG | null { +): DagreGraph | null { switch (block.type) { case SDFGElementType.LoopRegion: case SDFGElementType.ControlFlowRegion: return relayoutStateMachine( - ctx, block as StateMachineType, sdfg, sdfgList, stateParentList, - omitAccessNodes, parent + ctx, block as JsonSDFGControlFlowRegion, sdfg, sdfgList, + stateParentList, omitAccessNodes, parent ); case SDFGElementType.SDFGState: case SDFGElementType.BasicBlock: diff --git a/src/renderer/renderer_elements.ts b/src/renderer/renderer_elements.ts index 85a4ba81..77d0615a 100644 --- a/src/renderer/renderer_elements.ts +++ b/src/renderer/renderer_elements.ts @@ -1,14 +1,15 @@ -// Copyright 2019-2023 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { - DagreSDFG, + DagreGraph, JsonSDFG, JsonSDFGBlock, + JsonSDFGControlFlowRegion, JsonSDFGEdge, JsonSDFGNode, JsonSDFGState, Point2D, - SimpleRect + SimpleRect, } from '../index'; import { SDFV } from '../sdfv'; import { editor } from 'monaco-editor'; @@ -47,6 +48,10 @@ export enum SDFGElementType { export class SDFGElement { + public get COLLAPSIBLE(): boolean { + return false; + } + public in_connectors: Connector[] = []; public out_connectors: Connector[] = []; @@ -65,8 +70,9 @@ export class SDFGElement { public data: any, public id: number, public sdfg: JsonSDFG, + public cfg: JsonSDFGControlFlowRegion | null, public parent_id: number | null = null, - public parentElem?: SDFGElement, + public parentElem?: SDFGElement ) { this.set_layout(); } @@ -142,16 +148,17 @@ export class SDFGElement { return 'black'; if (this.selected) { - if (this.hovered) + if (this.hovered) { return this.getCssProperty( renderer, '--color-selected-hovered' ); - else if (this.highlighted) + } else if (this.highlighted) { return this.getCssProperty( renderer, '--color-selected-highlighted' ); - else + } else { return this.getCssProperty(renderer, '--color-selected'); + } } else { if (this.hovered) return this.getCssProperty(renderer, '--color-hovered'); @@ -166,7 +173,7 @@ export class SDFGElement { public intersect( x: number, y: number, w: number = 0, h: number = 0 ): boolean { - if (w == 0 || h == 0) { // Point-element intersection + if (w === 0 || h === 0) { // Point-element intersection return (x >= this.x - this.width / 2.0) && (x <= this.x + this.width / 2.0) && (y >= this.y - this.height / 2.0) && @@ -206,13 +213,14 @@ export class SDFGElement { ): string { return renderer.getCssProperty(propertyName); } + } // SDFG as an element (to support properties) export class SDFG extends SDFGElement { public constructor(sdfg: JsonSDFG) { - super(sdfg, -1, sdfg); + super(sdfg, -1, sdfg, null); } public set_layout(): void { @@ -229,9 +237,14 @@ export class SDFGShell extends SDFG { } export class ControlFlowBlock extends SDFGElement { + + public get COLLAPSIBLE(): boolean { + return true; + } + } -export class BasicBlock extends SDFGElement { +export class BasicBlock extends ControlFlowBlock { } export class ControlFlowRegion extends ControlFlowBlock { @@ -246,7 +259,7 @@ export class ControlFlowRegion extends ControlFlowBlock { const visibleRect = renderer.get_visible_rect(); let clamped; - if (visibleRect) + if (visibleRect) { clamped = { x: Math.max(topleft.x, visibleRect.x), y: Math.max(topleft.y, visibleRect.y), @@ -259,7 +272,7 @@ export class ControlFlowRegion extends ControlFlowBlock { w: 0, h: 0, }; - else + } else { clamped = { x: topleft.x, y: topleft.y, @@ -268,13 +281,19 @@ export class ControlFlowRegion extends ControlFlowBlock { w: 0, h: 0, }; + } clamped.w = clamped.x2 - clamped.x; clamped.h = clamped.y2 - clamped.y; - if (!(ctx as any).lod) + if (!(ctx as any).lod) { clamped = { - x: topleft.x, y: topleft.y, x2: 0, y2: 0, - w: this.width, h: this.height + x: topleft.x, + y: topleft.y, + x2: 0, + y2: 0, + w: this.width, + h: this.height, }; + } // Draw the region's background below everything and stroke the border. ctx.fillStyle = this.getCssProperty( @@ -287,9 +306,8 @@ export class ControlFlowRegion extends ControlFlowBlock { // Only draw line if close enough. const ppp = renderer.get_canvas_manager()?.points_per_pixel(); - if (!(ctx as any).lod || (ppp && ppp < SDFV.NODE_LOD)) { + if (!(ctx as any).lod || (ppp && ppp < SDFV.NODE_LOD)) ctx.strokeRect(clamped.x, clamped.y, clamped.w, clamped.h); - } ctx.fillStyle = this.getCssProperty( renderer, '--control-flow-region-foreground-color' @@ -297,15 +315,14 @@ export class ControlFlowRegion extends ControlFlowBlock { if (visibleRect && visibleRect.x <= topleft.x && visibleRect.y <= topleft.y + SDFV.LINEHEIGHT && - SDFVSettings.showStateNames) - + SDFVSettings.showStateNames) { if (!too_far_away_for_text(renderer, ctx)) { - ctx.fillText( this.label(), topleft.x + LoopRegion.META_LABEL_MARGIN, topleft.y + SDFV.LINEHEIGHT ); } + } // If this state is selected or hovered if (!(ctx as any).lod || (ppp && ppp < SDFV.NODE_LOD)) { @@ -399,7 +416,7 @@ export class State extends BasicBlock { const topleft = this.topleft(); const visible_rect = renderer.get_visible_rect(); let clamped; - if (visible_rect) + if (visible_rect) { clamped = { x: Math.max(topleft.x, visible_rect.x), y: Math.max(topleft.y, visible_rect.y), @@ -412,7 +429,7 @@ export class State extends BasicBlock { w: 0, h: 0, }; - else + } else { clamped = { x: topleft.x, y: topleft.y, @@ -421,13 +438,19 @@ export class State extends BasicBlock { w: 0, h: 0, }; + } clamped.w = clamped.x2 - clamped.x; clamped.h = clamped.y2 - clamped.y; - if (!(ctx as any).lod) + if (!(ctx as any).lod) { clamped = { - x: topleft.x, y: topleft.y, x2: 0, y2: 0, - w: this.width, h: this.height + x: topleft.x, + y: topleft.y, + x2: 0, + y2: 0, + w: this.width, + h: this.height, }; + } ctx.fillStyle = this.getCssProperty( renderer, '--state-background-color' @@ -440,10 +463,11 @@ export class State extends BasicBlock { if (visible_rect && visible_rect.x <= topleft.x && visible_rect.y <= topleft.y + SDFV.LINEHEIGHT && SDFVSettings.showStateNames) { - if (!too_far_away_for_text(renderer, ctx)) { - ctx.fillText(this.label(), topleft.x, topleft.y + SDFV.LINEHEIGHT); - } + ctx.fillText( + this.label(), topleft.x, topleft.y + SDFV.LINEHEIGHT + ); + } } // If this state is selected or hovered @@ -580,7 +604,7 @@ export class LoopRegion extends ControlFlowRegion { const visibleRect = renderer.get_visible_rect(); let clamped; - if (visibleRect) + if (visibleRect) { clamped = { x: Math.max(topleft.x, visibleRect.x), y: Math.max(topleft.y, visibleRect.y), @@ -593,7 +617,7 @@ export class LoopRegion extends ControlFlowRegion { w: 0, h: 0, }; - else + } else { clamped = { x: topleft.x, y: topleft.y, @@ -602,13 +626,19 @@ export class LoopRegion extends ControlFlowRegion { w: 0, h: 0, }; + } clamped.w = clamped.x2 - clamped.x; clamped.h = clamped.y2 - clamped.y; - if (!(ctx as any).lod) + if (!(ctx as any).lod) { clamped = { - x: topleft.x, y: topleft.y, x2: 0, y2: 0, - w: this.width, h: this.height + x: topleft.x, + y: topleft.y, + x2: 0, + y2: 0, + w: this.width, + h: this.height, }; + } // Draw the loop background below everything and stroke the border. ctx.fillStyle = this.getCssProperty( @@ -621,9 +651,8 @@ export class LoopRegion extends ControlFlowRegion { // Only draw line if close enough. const ppp = renderer.get_canvas_manager()?.points_per_pixel(); - if (!(ctx as any).lod || (ppp && ppp < SDFV.NODE_LOD)) { + if (!(ctx as any).lod || (ppp && ppp < SDFV.NODE_LOD)) ctx.strokeRect(clamped.x, clamped.y, clamped.w, clamped.h); - } ctx.fillStyle = this.getCssProperty( renderer, '--loop-foreground-color' @@ -643,9 +672,9 @@ export class LoopRegion extends ControlFlowRegion { ctx.stroke(); if (!too_far_away_for_text(renderer, ctx)) { - ctx.font = LoopRegion.LOOP_STATEMENT_FONT; - const initStatement = this.attributes().init_statement?.string_data; + const initStatement = + this.attributes().init_statement?.string_data; const initTextY = ( (topleft.y + (LoopRegion.INIT_SPACING / 2)) + (SDFV.LINEHEIGHT / 2) @@ -655,7 +684,7 @@ export class LoopRegion extends ControlFlowRegion { const initTextX = this.x - (initTextMetrics.width / 2); ctx.fillText(initStatement, initTextX, initTextY); } - + ctx.font = oldFont; ctx.fillText( 'init', topleft.x + LoopRegion.META_LABEL_MARGIN, initTextY @@ -685,7 +714,6 @@ export class LoopRegion extends ControlFlowRegion { if (!too_far_away_for_text(renderer, ctx)) { - ctx.font = LoopRegion.LOOP_STATEMENT_FONT; const condStatement = this.attributes().loop_condition?.string_data; const condTextY = ( @@ -716,7 +744,6 @@ export class LoopRegion extends ControlFlowRegion { if (!too_far_away_for_text(renderer, ctx)) { - ctx.font = LoopRegion.LOOP_STATEMENT_FONT; const updateStatement = this.attributes().update_statement.string_data; @@ -740,15 +767,14 @@ export class LoopRegion extends ControlFlowRegion { if (visibleRect && visibleRect.x <= topleft.x && visibleRect.y <= topleft.y + SDFV.LINEHEIGHT && - SDFVSettings.showStateNames) - + SDFVSettings.showStateNames) { if (!too_far_away_for_text(renderer, ctx)) { - ctx.fillText( this.label(), topleft.x + LoopRegion.META_LABEL_MARGIN, topleft.y + topSpacing + SDFV.LINEHEIGHT ); } + } // If this state is selected or hovered if (!(ctx as any).lod || (ppp && ppp < SDFV.NODE_LOD)) { @@ -795,7 +821,7 @@ export class SDFGNode extends SDFGElement { const topleft = this.topleft(); const visible_rect = renderer.get_visible_rect(); let clamped; - if (visible_rect) + if (visible_rect) { clamped = { x: Math.max(topleft.x, visible_rect.x), y: Math.max(topleft.y, visible_rect.y), @@ -808,7 +834,7 @@ export class SDFGNode extends SDFGElement { w: 0, h: 0, }; - else + } else { clamped = { x: topleft.x, y: topleft.y, @@ -817,13 +843,19 @@ export class SDFGNode extends SDFGElement { w: 0, h: 0, }; + } clamped.w = clamped.x2 - clamped.x; clamped.h = clamped.y2 - clamped.y; - if (!(ctx as any).lod) + if (!(ctx as any).lod) { clamped = { - x: topleft.x, y: topleft.y, x2: 0, y2: 0, - w: this.width, h: this.height + x: topleft.x, + y: topleft.y, + x2: 0, + y2: 0, + w: this.width, + h: this.height, }; + } ctx.fillStyle = this.getCssProperty(renderer, bgstyle); ctx.fillRect(clamped.x, clamped.y, clamped.w, clamped.h); @@ -840,20 +872,21 @@ export class SDFGNode extends SDFGElement { } } if (this.label()) { - if (!too_far_away_for_text(renderer, ctx)) { - ctx.fillStyle = this.getCssProperty(renderer, fgstyle); const textw = ctx.measureText(this.label()).width; - if (!visible_rect) + if (!visible_rect) { ctx.fillText( - this.label(), this.x - textw / 2, this.y + SDFV.LINEHEIGHT / 4 + this.label(), this.x - textw / 2, + this.y + SDFV.LINEHEIGHT / 4 ); - else if (visible_rect && visible_rect.x <= topleft.x && - visible_rect.y <= topleft.y + SDFV.LINEHEIGHT) + } else if (visible_rect && visible_rect.x <= topleft.x && + visible_rect.y <= topleft.y + SDFV.LINEHEIGHT) { ctx.fillText( - this.label(), this.x - textw / 2, this.y + SDFV.LINEHEIGHT / 4 + this.label(), this.x - textw / 2, + this.y + SDFV.LINEHEIGHT / 4 ); + } } } } @@ -1039,9 +1072,8 @@ export abstract class Edge extends SDFGElement { x: number, y: number, w: number = 0, h: number = 0 ): boolean { // First, check bounding box - if (!super.intersect(x, y, w, h)) { + if (!super.intersect(x, y, w, h)) return false; - } // Then (if point), check distance from line if (w === 0 || h === 0) { @@ -1053,15 +1085,14 @@ export abstract class Edge extends SDFGElement { return true; } return false; - } - else { - // It is a rectangle. - // Check if any of the rectangles, spanned by pairs of points of the line, - // intersect the input rectangle. - // This is needed for long Interstate edges that have a huge bounding box and - // intersect almost always with the viewport even if they are not visible. - // This is only an approximation to detect if a line is in the viewport and - // could be made more accurate at the cost of more computation. + } else { + // It is a rectangle. Check if any of the rectangles, spanned by + // pairs of points of the line, intersect the input rectangle. + // This is needed for long Interstate edges that have a huge + // bounding box and intersect almost always with the viewport even + // if they are not visible. This is only an approximation to detect + // if a line is in the viewport and could be made more accurate at + // the cost of more computation. for (let i = 0; i < this.points.length - 1; i++) { const linepoint_0 = this.points[i]; const linepoint_1 = this.points[i + 1]; @@ -1070,14 +1101,13 @@ export abstract class Edge extends SDFGElement { x: Math.min(linepoint_0.x, linepoint_1.x), y: Math.min(linepoint_0.y, linepoint_1.y), w: Math.abs(linepoint_1.x - linepoint_0.x), - h: Math.abs(linepoint_1.y - linepoint_0.y) - } + h: Math.abs(linepoint_1.y - linepoint_0.y), + }; // Check if the two rectangles intersect if (r.x + r.w >= x && r.x <= x+w && - r.y + r.h >= y && r.y <= y+h) { - return true; - } + r.y + r.h >= y && r.y <= y+h) + return true; } return false; } @@ -1094,7 +1124,6 @@ export class Memlet extends Edge { // Straight line can be drawn ctx.lineTo(this.points[1].x, this.points[1].y); } else { - let i; if (SDFVSettings.curvedEdges) { for (i = 1; i < this.points.length - 2; i++) { @@ -1106,14 +1135,11 @@ export class Memlet extends Edge { } ctx.quadraticCurveTo(this.points[i].x, this.points[i].y, this.points[i + 1].x, this.points[i + 1].y); - } - else { + } else { // Straight lines - for (i = 1; i < this.points.length; i++) { + for (i = 1; i < this.points.length; i++) ctx.lineTo(this.points[i].x, this.points[i].y); - } } - } } @@ -1150,17 +1176,19 @@ export class Memlet extends Edge { // Show anchor points for moving if (this.selected && renderer.get_mouse_mode() === 'move') { let i; - for (i = 1; i < this.points.length - 1; i++) + for (i = 1; i < this.points.length - 1; i++) { ctx.strokeRect( this.points[i].x - 5, this.points[i].y - 5, 8, 8 ); + } } - if (!skipArrow) + if (!skipArrow) { this.drawArrow( ctx, this.points[this.points.length - 2], this.points[this.points.length - 1], 3 ); + } } public tooltip( @@ -1182,30 +1210,34 @@ export class Memlet extends Edge { let contents = attr.data; contents += sdfg_property_to_string(attr.subset, dsettings); - if (attr.other_subset) + if (attr.other_subset) { contents += ' -> ' + sdfg_property_to_string( attr.other_subset, dsettings ); + } - if (attr.wcr) + if (attr.wcr) { contents += '
CR: ' + sdfg_property_to_string( attr.wcr, dsettings ) + ''; + } let num_accesses = null; - if (attr.volume) + if (attr.volume) { num_accesses = sdfg_property_to_string(attr.volume, dsettings); - else + } else { num_accesses = sdfg_property_to_string( attr.num_accesses, dsettings ); + } if (attr.dynamic) { - if (num_accesses === '0' || num_accesses === '-1') + if (num_accesses === '0' || num_accesses === '-1') { num_accesses = 'Dynamic (unbounded)'; - else + } else { num_accesses = 'Dynamic (up to ' + num_accesses + ')'; + } } else if (num_accesses === '-1') { num_accesses = 'Dynamic (unbounded)'; } @@ -1228,19 +1260,20 @@ export class InterstateEdge extends Edge { data: any, id: number, sdfg: JsonSDFG, + cfg: JsonSDFGControlFlowRegion, parent_id: number | null = null, parentElem?: SDFGElement, public readonly src?: string, - public readonly dst?: string, + public readonly dst?: string ) { - super(data, id, sdfg, parent_id, parentElem); + super(data, id, sdfg, cfg, parent_id, parentElem); } public create_arrow_line(ctx: CanvasRenderingContext2D): void { // Draw intersate edges with bezier curves through the arrow points. ctx.moveTo(this.points[0].x, this.points[0].y); let i; - + if (SDFVSettings.curvedEdges) { let lastX = this.points[0].x; let lastY = this.points[0].y; @@ -1254,14 +1287,11 @@ export class InterstateEdge extends Edge { lastX = this.points[i].x; lastY = this.points[i].y; } - } - else { + } else { // Straight lines - for (i = 1; i < this.points.length; i++) { + for (i = 1; i < this.points.length; i++) ctx.lineTo(this.points[i].x, this.points[i].y); - } } - } protected drawArrow( @@ -1320,10 +1350,11 @@ export class InterstateEdge extends Edge { // Show anchor points for moving if (this.selected && renderer.get_mouse_mode() === 'move') { let i; - for (i = 1; i < this.points.length - 1; i++) + for (i = 1; i < this.points.length - 1; i++) { ctx.strokeRect( this.points[i].x - 5, this.points[i].y - 5, 8, 8 ); + } } this.drawArrow( @@ -1380,12 +1411,12 @@ export class InterstateEdge extends Edge { Math.abs(labelMetrics.actualBoundingBoxRight); let label_height = Math.abs(labelMetrics.actualBoundingBoxDescent) + Math.abs(labelMetrics.actualBoundingBoxAscent); - + // In case of canvas2pdf context, that only has width and height // as TextMetrics properties - if (label_width != label_width) + if (label_width !== label_width) label_width = (labelMetrics as any).width; - if (label_height != label_height) + if (label_height !== label_height) label_height = (labelMetrics as any).height; labelWs.push(label_width); @@ -1503,8 +1534,10 @@ export class Connector extends SDFGElement { this.custom_label = null; } else if (!edge) { ctx.stroke(); - fillColor = this.getCssProperty(renderer, '--node-missing-background-color'); - this.custom_label = "No edge connected"; + fillColor = this.getCssProperty( + renderer, '--node-missing-background-color' + ); + this.custom_label = 'No edge connected'; } else { ctx.stroke(); fillColor = this.getCssProperty( @@ -1527,7 +1560,8 @@ export class Connector extends SDFGElement { } ctx.fill(); - if (this.strokeStyle(renderer) !== this.getCssProperty(renderer, '--color-default')) + if (this.strokeStyle(renderer) !== + this.getCssProperty(renderer, '--color-default')) renderer.set_tooltip((c) => this.tooltip(c)); } @@ -1572,18 +1606,17 @@ export class AccessNode extends SDFGNode { const name = this.data.node.attributes.data; const nodedesc = this.sdfg.attributes._arrays[name]; // Streams have dashed edges - if (nodedesc && nodedesc.type === 'Stream') { + if (nodedesc && nodedesc.type === 'Stream') ctx.setLineDash([5, 3]); - } else { + else ctx.setLineDash([1, 0]); - } // Non-transient (external) data is thicker - if (nodedesc && nodedesc.attributes.transient === true) { + if (nodedesc && nodedesc.attributes.transient === true) ctx.lineWidth = 1.0; - } else { + else ctx.lineWidth = 3.0; - } + ctx.stroke(); ctx.lineWidth = 1.0; ctx.setLineDash([1, 0]); @@ -1627,14 +1660,14 @@ export class AccessNode extends SDFGNode { ctx.fillStyle = this.getCssProperty( renderer, '--node-missing-foreground-color' ); - if (this.strokeStyle(renderer) !== this.getCssProperty(renderer, '--color-default')) + if (this.strokeStyle(renderer) !== + this.getCssProperty(renderer, '--color-default')) renderer.set_tooltip((c) => this.tooltip(c)); } // If we are far away, don't show the text - if (too_far_away_for_text(renderer, ctx)) { + if (too_far_away_for_text(renderer, ctx)) return; - } const textmetrics = ctx.measureText(this.label()); ctx.fillText( @@ -1691,6 +1724,10 @@ export class AccessNode extends SDFGNode { export class ScopeNode extends SDFGNode { + public get COLLAPSIBLE(): boolean { + return true; + } + private cached_far_label: string | null = null; private cached_close_label: string | null = null; @@ -1751,9 +1788,8 @@ export class ScopeNode extends SDFGNode { ); // If we are far away, don't show the text - if (too_far_away_for_text(renderer, ctx)) { + if (too_far_away_for_text(renderer, ctx)) return; - } drawAdaptiveText( ctx, renderer, this.far_label(renderer), @@ -1762,17 +1798,18 @@ export class ScopeNode extends SDFGNode { SDFV.SCOPE_LOD ); - if (SDFVSettings.showMapSchedules) + if (SDFVSettings.showMapSchedules) { drawAdaptiveText( ctx, renderer, '', this.schedule_label(), this.x, this.y, this.width, this.height, SDFV.SCOPE_LOD, SDFV.DEFAULT_MAX_FONTSIZE, 0.7, SDFV.DEFAULT_FAR_FONT_MULTIPLIER, true, TextVAlign.BOTTOM, TextHAlign.RIGHT, { - bottom: 2.0, - right: this.height, - } + bottom: 2.0, + right: this.height, + } ); + } } public shade( @@ -1786,13 +1823,14 @@ export class ScopeNode extends SDFGNode { ctx.globalAlpha = alpha; ctx.fillStyle = color; - if (this.data.node.attributes.is_collapsed) + if (this.data.node.attributes.is_collapsed) { drawHexagon(ctx, this.x, this.y, this.width, this.height, { x: 0, y: 0, }); - else + } else { drawTrapezoid(ctx, this.topleft(), this, this.scopeend()); + } ctx.fill(); // Restore the previous style properties. @@ -1847,10 +1885,11 @@ export class ScopeNode extends SDFGNode { attrs.num_pes ?? 1, renderer.view_settings() ); } else { - for (let i = 0; i < attrs.params.length; ++i) + for (let i = 0; i < attrs.params.length; ++i) { result += sdfg_range_elem_to_string( attrs.range.ranges[i], renderer.view_settings() ) + ', '; + } // Remove trailing comma result = result.substring(0, result.length - 2); } @@ -1874,9 +1913,9 @@ export class ScopeNode extends SDFGNode { const entry = this.parentElem?.data.state.nodes[ this.data.node.scope_entry ]; - if (entry !== undefined) + if (entry !== undefined) { attrs = entry.attributes; - else { + } else { this.cached_close_label = 'MISSING ENTRY NODE'; return 'MISSING ENTRY NODE'; } @@ -1998,10 +2037,11 @@ export class Tasklet extends SDFGNode { public data: any, public id: number, public sdfg: JsonSDFG, + public cfg: JsonSDFGControlFlowRegion, public parent_id: number | null = null, - public parentElem?: SDFGElement, + public parentElem?: SDFGElement ) { - super(data, id, sdfg, parent_id, parentElem); + super(data, id, sdfg, cfg, parent_id, parentElem); this.highlightCode(); } @@ -2182,9 +2222,8 @@ export class Tasklet extends SDFGNode { ); // If we are far away, don't show the text - if (too_far_away_for_text(renderer, ctx)) { + if (too_far_away_for_text(renderer, ctx)) return; - } const ppp = canvas_manager.points_per_pixel(); if (!(ctx as any).lod || ppp < SDFV.TASKLET_LOD) { @@ -2245,13 +2284,14 @@ export class Reduce extends SDFGNode { if ((ctx as any).pdf) draw_shape(); ctx.fill(); - + if (!too_far_away_for_text(renderer, ctx)) { - ctx.fillStyle = this.getCssProperty( renderer, '--node-foreground-color' ); - const far_label = this.label().substring(4, this.label().indexOf(',')); + const far_label = this.label().substring( + 4, this.label().indexOf(',') + ); drawAdaptiveText( ctx, renderer, far_label, this.label(), this.x, this.y - this.height * 0.2, @@ -2290,6 +2330,10 @@ export class Reduce extends SDFGNode { export class NestedSDFG extends SDFGNode { + public get COLLAPSIBLE(): boolean { + return true; + } + public draw( renderer: SDFGRenderer, ctx: CanvasRenderingContext2D, mousepos?: Point2D @@ -2309,16 +2353,16 @@ export class NestedSDFG extends SDFGNode { renderer, '--node-background-color' ); // PDFs do not support stroke and fill on the same object - if ((ctx as any).pdf) + if ((ctx as any).pdf) { drawOctagon( ctx, { x: topleft.x + 2.5, y: topleft.y + 2.5 }, this.width - 5, this.height - 5 ); + } ctx.fill(); if (!too_far_away_for_text(renderer, ctx)) { - ctx.fillStyle = this.getCssProperty( renderer, '--node-foreground-color' ); @@ -2345,7 +2389,6 @@ export class NestedSDFG extends SDFGNode { } else { // Expanded, but no SDFG present or loaded yet. if (!too_far_away_for_text(renderer, ctx)) { - const errColor = this.getCssProperty( renderer, '--node-missing-background-color' ); @@ -2461,10 +2504,9 @@ export class LibraryNode extends SDFGNode { ); // If we are far away, don't show the text - if (too_far_away_for_text(renderer, ctx)) { + if (too_far_away_for_text(renderer, ctx)) return; - } - + const textw = ctx.measureText(this.label()).width; ctx.fillText( this.label(), this.x - textw / 2, this.y + SDFV.LINEHEIGHT / 4 @@ -2494,19 +2536,19 @@ export class LibraryNode extends SDFGNode { ////////////////////////////////////////////////////// -// Checks if graph is zoomed out far (defined by SDFV.TEXT_LOD), using Points-per-Pixel -// Used before ctx.fillText calls to only draw text when zoomed in close enough -function too_far_away_for_text(renderer: SDFGRenderer, ctx: CanvasRenderingContext2D): boolean { - +// Checks if graph is zoomed out far (defined by SDFV.TEXT_LOD), using +// Points-per-Pixel. Used before ctx.fillText calls to only draw text when +// zoomed in close enough. +function too_far_away_for_text( + renderer: SDFGRenderer, ctx: CanvasRenderingContext2D +): boolean { const canvas_manager = renderer.get_canvas_manager(); const ppp = canvas_manager?.points_per_pixel(); if (ppp) { - if ((ctx as any).lod && ppp > SDFV.TEXT_LOD) { + if ((ctx as any).lod && ppp > SDFV.TEXT_LOD) return true; - } - else { + else return false; - } } return false; @@ -2531,7 +2573,7 @@ function too_far_away_for_text(renderer: SDFGRenderer, ctx: CanvasRenderingConte * @param color Default edge color to use. */ function batchedDrawEdges( - renderer: SDFGRenderer, graph: DagreSDFG, ctx: CanvasRenderingContext2D, + renderer: SDFGRenderer, graph: DagreGraph, ctx: CanvasRenderingContext2D, visible_rect?: SimpleRect, mousepos?: Point2D, color: string = '--color-default', labelled: boolean = false @@ -2578,6 +2620,7 @@ function batchedDrawEdges( labelEdges.push(edge); edge.create_arrow_line(ctx); + // SDFGRenderer.rendered_elements_count++; }); ctx.setLineDash([1, 0]); ctx.fillStyle = ctx.strokeStyle = renderer.getCssProperty(color); @@ -2587,10 +2630,12 @@ function batchedDrawEdges( const canvas_manager = renderer.get_canvas_manager(); const ppp = canvas_manager?.points_per_pixel(); if (!(ctx as any).lod || (ppp && ppp < SDFV.ARROW_LOD)) { - arrowEdges.forEach(e => { e.drawArrow( - ctx, e.points[e.points.length - 2], e.points[e.points.length - 1], 3 + ctx, + e.points[e.points.length - 2], + e.points[e.points.length - 1], + 3 ); }); } @@ -2612,7 +2657,7 @@ function batchedDrawEdges( } export function drawStateContents( - stateGraph: DagreSDFG, ctx: CanvasRenderingContext2D, + stateGraph: DagreGraph, ctx: CanvasRenderingContext2D, renderer: SDFGRenderer, ppp: number, lod?: boolean, visibleRect?: SimpleRect, mousePos?: Point2D ): void { @@ -2630,12 +2675,14 @@ export function drawStateContents( ) < SDFV.STATE_LOD) { node.simple_draw(renderer, ctx, mousePos); node.debug_draw(renderer, ctx); + // SDFGRenderer.rendered_elements_count++; continue; } } else { if (lod && ppp > SDFV.NODE_LOD) { node.simple_draw(renderer, ctx, mousePos); node.debug_draw(renderer, ctx); + // SDFGRenderer.rendered_elements_count++; continue; } } @@ -2645,41 +2692,40 @@ export function drawStateContents( // Only draw connectors when close enough to see them if (!lod || ppp < SDFV.CONNECTOR_LOD) { - node.in_connectors.forEach((c: Connector) => { - - // Only draw connectors if actually visible. This is needed for large - // nodes in the background like NestedSDFGs, that are visible, but their - // connectors are actually not. + // Only draw connectors if actually visible. This is needed for + // large nodes in the background like NestedSDFGs, that are + // visible, but their connectors are actually not. if (visibleRect && !c.intersect( - visibleRect.x, visibleRect.y, visibleRect.w, visibleRect.h)) { + visibleRect.x, visibleRect.y, + visibleRect.w, visibleRect.h + )) return; - } let edge: Edge | null = null; stateGraph.inEdges(nodeId)?.forEach((e) => { const eobj = stateGraph.edge(e); - if (eobj.dst_connector == c.data.name) + if (eobj.dst_connector === c.data.name) edge = eobj as any; }); - + c.draw(renderer, ctx, mousePos, edge); c.debug_draw(renderer, ctx); }); node.out_connectors.forEach((c: Connector) => { - if (visibleRect && !c.intersect( - visibleRect.x, visibleRect.y, visibleRect.w, visibleRect.h)) { + visibleRect.x, visibleRect.y, + visibleRect.w, visibleRect.h + )) return; - } let edge: Edge | null = null; stateGraph.outEdges(nodeId)?.forEach((e) => { const eobj = stateGraph.edge(e); - if (eobj.src_connector == c.data.name) + if (eobj.src_connector === c.data.name) edge = eobj as any; }); - + c.draw(renderer, ctx, mousePos, edge); c.debug_draw(renderer, ctx); }); @@ -2696,12 +2742,11 @@ export function drawStateContents( } export function drawStateMachine( - stateMachineGraph: DagreSDFG, ctx: CanvasRenderingContext2D, + stateMachineGraph: DagreGraph, ctx: CanvasRenderingContext2D, renderer: SDFGRenderer, ppp: number, lod?: boolean, visibleRect?: SimpleRect, mousePos?: Point2D ): void { if (!lod || ppp < SDFV.EDGE_LOD) { - batchedDrawEdges( renderer, stateMachineGraph, ctx, visibleRect, mousePos, '--interstate-edge-color', SDFVSettings.alwaysOnISEdgeLabels @@ -2714,10 +2759,9 @@ export function drawStateMachine( // Skip invisible states. if (lod && visibleRect && !block.intersect( visibleRect.x, visibleRect.y, visibleRect.w, visibleRect.h - )) { - continue; - } - + )) + continue; + const blockppp = Math.sqrt(block.width * block.height) / ppp; if (lod && blockppp < SDFV.STATE_LOD) { block.simple_draw(renderer, ctx, mousePos); @@ -2727,6 +2771,7 @@ export function drawStateMachine( block.draw(renderer, ctx, mousePos); block.debug_draw(renderer, ctx); + // SDFGRenderer.rendered_elements_count++; const ng = block.data.graph; if (!block.attributes().is_collapsed && ng) { @@ -2745,7 +2790,7 @@ export function drawStateMachine( // Draw an entire SDFG. export function drawSDFG( - renderer: SDFGRenderer, ctx: CanvasRenderingContext2D, g: DagreSDFG, + renderer: SDFGRenderer, ctx: CanvasRenderingContext2D, g: DagreGraph, mousePos?: Point2D ): void { const cManager = renderer.get_canvas_manager(); @@ -2754,6 +2799,7 @@ export function drawSDFG( const ppp = cManager.points_per_pixel(); const visibleRect = renderer.get_visible_rect() ?? undefined; + SDFGRenderer.rendered_elements_count = 0; drawStateMachine( g, ctx, renderer, ppp, (ctx as any).lod, visibleRect, mousePos ); @@ -2761,7 +2807,7 @@ export function drawSDFG( // Translate an SDFG by a given offset export function offset_sdfg( - sdfg: JsonSDFG, sdfg_graph: DagreSDFG, offset: Point2D + sdfg: JsonSDFG, sdfg_graph: DagreGraph, offset: Point2D ): void { sdfg.nodes.forEach((state: JsonSDFGBlock, id: number) => { const g = sdfg_graph.node(id.toString()); @@ -2793,7 +2839,8 @@ export function offset_state( state.nodes.forEach((_n: JsonSDFGNode, nid: number) => { const node = state_graph.data.graph.node(nid); - if (!node) return; + if (!node) + return; drawn_nodes.add(nid.toString()); node.x += offset.x; @@ -2808,17 +2855,20 @@ export function offset_state( }); if (node.data.node.type === SDFGElementType.NestedSDFG && - node.data.node.attributes.sdfg) + node.data.node.attributes.sdfg) { offset_sdfg( node.data.node.attributes.sdfg, node.data.graph, offset ); + } }); state.edges.forEach((e: JsonSDFGEdge, eid: number) => { const ne = check_and_redirect_edge(e, drawn_nodes, state); - if (!ne) return; + if (!ne) + return; e = ne; const edge = state_graph.data.graph.edge(e.src, e.dst, eid); - if (!edge) return; + if (!edge) + return; edge.x += offset.x; edge.y += offset.y; edge.points.forEach((p: Point2D) => { @@ -2885,9 +2935,9 @@ export function drawAdaptiveText( Math.abs(label_metrics.actualBoundingBoxRight); let label_height = Math.abs(label_metrics.actualBoundingBoxDescent) + Math.abs(label_metrics.actualBoundingBoxAscent); - if (label_width != label_width) + if (label_width !== label_width) label_width = label_metrics.width; - if (label_height != label_height) + if (label_height !== label_height) label_height = (label_metrics as any).height; // Account for canvas2pdf const padding_left = padding.left !== undefined ? padding.left : 1.0; diff --git a/src/sdfv.ts b/src/sdfv.ts index d1d5055b..89a0d4b2 100644 --- a/src/sdfv.ts +++ b/src/sdfv.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import $ from 'jquery'; @@ -8,17 +8,17 @@ import '../scss/sdfv.scss'; import { mean, median } from 'mathjs'; import { - DagreSDFG, + DagreGraph, GenericSdfgOverlay, JsonSDFG, Point2D, sdfg_property_to_string, showErrorModal, - traverseSDFGScopes + traverseSDFGScopes, } from './index'; import { LViewRenderer } from './local_view/lview_renderer'; import { - RuntimeMicroSecondsOverlay + RuntimeMicroSecondsOverlay, } from './overlays/runtime_micro_seconds_overlay'; import { OverlayManager } from './overlay_manager'; import { SDFGRenderer } from './renderer/renderer'; @@ -26,10 +26,14 @@ import { AccessNode, Edge, Memlet, NestedSDFG, SDFG, SDFGElement, SDFGNode, - State + State, } from './renderer/renderer_elements'; import { htmlSanitize } from './utils/sanitization'; -import { checkCompatLoad, parse_sdfg, stringify_sdfg } from './utils/sdfg/json_serializer'; +import { + checkCompatLoad, + parse_sdfg, + stringify_sdfg, +} from './utils/sdfg/json_serializer'; import { SDFVSettings } from './utils/sdfv_settings'; declare const vscode: any; @@ -47,7 +51,8 @@ export class SDFV { public static SCOPE_LOD: number = 0.75; // 0.75 // Points-per-pixel threshold for not drawing memlets/interstate edges. public static EDGE_LOD: number = 5.0; // 5.0 - // Points-per-pixel threshold for not drawing Arrowheads of memlets/interstate edges. + // Points-per-pixel threshold for not drawing Arrowheads of + // memlets/interstate edges. public static ARROW_LOD: number = 2.0; // 2.0 // Points-per-pixel threshold for not drawing connectors. public static CONNECTOR_LOD = 2.0; // 2.0 @@ -103,10 +108,11 @@ export class SDFV { else window.getSelection()?.removeAllRanges(); - if (right) + if (right) { right.style.width = Math.max( ((e.view ? e.view.innerWidth - e.pageX : 0)), 20 ) + 'px'; + } }; if (bar) { @@ -146,7 +152,7 @@ export class SDFV { sidebar.style.display = 'none'; } - public outline(renderer: SDFGRenderer, sdfg: DagreSDFG): void { + public outline(renderer: SDFGRenderer, sdfg: DagreGraph): void { this.sidebar_set_title('SDFG Outline'); const sidebar = this.sidebar_get_contents(); @@ -169,7 +175,7 @@ export class SDFV { const stack: any[] = [sidebar]; // Add elements to tree view in sidebar - traverseSDFGScopes(sdfg, (node: SDFGNode, parent: DagreSDFG) => { + traverseSDFGScopes(sdfg, (node, parent) => { // Skip exit nodes when scopes are known if (node.type().endsWith('Exit') && node.data.node.scope_entry >= 0) { @@ -187,9 +193,8 @@ export class SDFV { // If a scope has children, remove the name "Entry" from the type if (node.type().endsWith('Entry') && node.parent_id && node.id) { const state = node.parentElem?.data.state.nodes[node.parent_id]; - if (state.scope_dict[node.id] !== undefined) { + if (state.scope_dict[node.id] !== undefined) node_type = node_type.slice(0, -5); - } } d.innerHTML = htmlSanitize` @@ -230,7 +235,7 @@ export class SDFV { return false; return true; - }, (_node: SDFGNode, _parent: DagreSDFG) => { + }, (_node: SDFGNode, _parent: DagreGraph) => { // After scope ends, pop ourselves as the current element // and add to parent const elem = stack.pop(); @@ -241,9 +246,9 @@ export class SDFV { this.sidebar_show(); } - public fill_info(elem: SDFGElement): void { + public fill_info(elem: SDFGElement | DagreGraph | null): void { const contentsRaw = this.sidebar_get_contents(); - if (!contentsRaw) + if (!contentsRaw || !elem || !(elem instanceof SDFGElement)) return; const contents = $(contentsRaw); contents.html(''); @@ -310,7 +315,9 @@ export class SDFV { // If access node, add array information too if (elem instanceof AccessNode) { - const sdfg_array = elem.sdfg.attributes._arrays[elem.attributes().data]; + const sdfg_array = elem.sdfg.attributes._arrays[ + elem.attributes().data + ]; contents.append($('
')); contents.append($('

', { text: sdfg_array.type + ' properties:', @@ -406,30 +413,33 @@ function init_sdfv( }); $('#outline').on('click', () => { const renderer = sdfv.get_renderer(); - if (renderer) + if (renderer) { setTimeout(() => { const graph = renderer.get_graph(); if (graph) sdfv.outline(renderer, graph); }, 1); + } }); $('#search-btn').on('click', () => { const renderer = sdfv.get_renderer(); - if (renderer) + if (renderer) { setTimeout(() => { const graph = renderer.get_graph(); const query = $('#search').val(); - if (graph && query) + if (graph && query) { find_in_graph( sdfv, renderer, graph, query.toString(), $('#search-case').is(':checked') ); + } }, 1); + } }); $('#advsearch-btn').on('click', (e) => { e.preventDefault(); const renderer = sdfv.get_renderer(); - if (renderer) + if (renderer) { setTimeout(() => { const graph = renderer.get_graph(); const code = $('#advsearch').val(); @@ -440,6 +450,7 @@ function init_sdfv( ); } }, 1); + } return false; }); $('#search').on('keydown', (e: any) => { @@ -461,21 +472,23 @@ function init_sdfv( add_btns.push(document.getElementById('elem_access_node')); add_btns.push(document.getElementById('elem_stream')); add_btns.push(document.getElementById('elem_state')); - if (pan_btn) + if (pan_btn) { mode_buttons = { pan: pan_btn, move: move_btn, select: select_btn, add_btns: add_btns, }; + } if (sdfg !== null) { const container = document.getElementById('contents'); - if (container) + if (container) { sdfv.set_renderer(new SDFGRenderer( sdfv, sdfg, container, mouse_event, user_transform, debug_draw, null, mode_buttons )); + } } return sdfv; @@ -483,16 +496,18 @@ function init_sdfv( function start_find_in_graph(sdfv: SDFV): void { const renderer = sdfv.get_renderer(); - if (renderer) + if (renderer) { setTimeout(() => { const graph = renderer.get_graph(); const query = $('#search').val(); - if (graph && query) + if (graph && query) { find_in_graph( sdfv, renderer, graph, query.toString(), $('#search-case').is(':checked') ); + } }, 1); + } } export function reload_file(sdfv: SDFV): void { @@ -511,22 +526,24 @@ function file_read_complete(sdfv: SDFV): void { const info_field = document.getElementById('task-info-field'); if (result_string && container && info_field) { - - // Create the loader element before starting to parse and layout the graph. - // The layouting can take several seconds for large graphs on slow machines. - // The user sees a loading animation in the meantime so that the site doesn't - // appear unresponsive. - // The loader element is removed/cleared again at the end of the layout function in - // the SDFGRenderer. - const loaderDiv = document.createElement("div"); - loaderDiv.classList.add("loader"); + // Create the loader element before starting to parse and layout the + // graph. The layouting can take several seconds for large graphs on + // slow machines. The user sees a loading animation in the meantime so + // that the site doesn't appear unresponsive. The loader element is + // removed/cleared again at the end of the layout function in the + // SDFGRenderer. + const loaderDiv = document.createElement('div'); + loaderDiv.classList.add('loader'); info_field.appendChild(loaderDiv); - // Use setTimeout function to force the browser to reload the dom with the above loader element. + // Use setTimeout function to force the browser to reload the dom with + // the above loader element. setTimeout(() => { const sdfg = checkCompatLoad(parse_sdfg(result_string)); sdfv.get_renderer()?.destroy(); - sdfv.set_renderer(new SDFGRenderer(sdfv, sdfg, container, mouse_event)); + sdfv.set_renderer( + new SDFGRenderer(sdfv, sdfg, container, mouse_event) + ); sdfv.close_menu(); }, 20); } @@ -644,8 +661,10 @@ function getParameterByName(name: string): string | null { name = name.replace(/[\[\]]/g, '\\$&'); const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; + if (!results) + return null; + if (!results[2]) + return ''; return decodeURIComponent(results[2].replace(/\+/g, ' ')); } @@ -676,17 +695,15 @@ function load_sdfg_from_url(sdfv: SDFV, url: string): void { } function find_recursive( - graph: DagreSDFG, predicate: CallableFunction, results: any[] + graph: DagreGraph, predicate: CallableFunction, results: any[] ): void { for (const nodeid of graph.nodes()) { const node = graph.node(nodeid); if (predicate(graph, node)) results.push(node); // Enter states or nested SDFGs recursively - if (node.data.graph) { + if (node.data.graph) find_recursive(node.data.graph, predicate, results); - - } } for (const edgeid of graph.edges()) { const edge = graph.edge(edgeid); @@ -696,7 +713,8 @@ function find_recursive( } export function find_in_graph_predicate( - sdfv: SDFV, renderer: SDFGRenderer, sdfg: DagreSDFG, predicate: CallableFunction + sdfv: SDFV, renderer: SDFGRenderer, sdfg: DagreGraph, + predicate: CallableFunction ): void { sdfv.sidebar_set_title('Search Results'); @@ -715,7 +733,9 @@ export function find_in_graph_predicate( const d = document.createElement('div'); d.className = 'context_menu_option'; d.innerHTML = htmlSanitize`${result.type()} ${result.label()}`; - d.onclick = () => { renderer.zoom_to_view([result]); }; + d.onclick = () => { + renderer.zoom_to_view([result]); + }; d.onmouseenter = () => { if (!result.highlighted) { result.highlighted = true; @@ -736,13 +756,13 @@ export function find_in_graph_predicate( } export function find_in_graph( - sdfv: SDFV, renderer: SDFGRenderer, sdfg: DagreSDFG, query: string, + sdfv: SDFV, renderer: SDFGRenderer, sdfg: DagreGraph, query: string, case_sensitive: boolean = false ): void { if (!case_sensitive) query = query.toLowerCase(); find_in_graph_predicate( - sdfv, renderer, sdfg, (graph: DagreSDFG, element: SDFGElement) => { + sdfv, renderer, sdfg, (graph: DagreGraph, element: SDFGElement) => { let label = element.label(); if (!case_sensitive) label = label.toLowerCase(); @@ -753,8 +773,8 @@ export function find_in_graph( } function recursive_find_graph( - graph: DagreSDFG, cfg_id: number -): DagreSDFG | undefined { + graph: DagreGraph, cfg_id: number +): DagreGraph | undefined { let found = undefined; for (const n_id of graph.nodes()) { const n = graph.node(n_id); @@ -770,7 +790,7 @@ function recursive_find_graph( return found; } -function find_state(graph: DagreSDFG, state_id: number): State | undefined { +function find_state(graph: DagreGraph, state_id: number): State | undefined { let state = undefined; for (const s_id of graph.nodes()) { if (Number(s_id) === state_id) { @@ -804,7 +824,7 @@ function find_edge(state: State, edge_id: number): Edge | undefined { } export function find_graph_element( - graph: DagreSDFG, type: string, sdfg_id: number, state_id: number = -1, + graph: DagreGraph, type: string, sdfg_id: number, state_id: number = -1, el_id: number = -1 ): SDFGElement | undefined { const requested_graph = recursive_find_graph(graph, sdfg_id); @@ -919,7 +939,7 @@ $(() => { vscode; if (vscode) return; - } catch (_) {} + } catch (_) { } // Set the default settings based on the current script's attributes // or URL parameters. @@ -974,7 +994,11 @@ declare global { // Exported functions parse_sdfg: (sdfg_json: string) => JsonSDFG; stringify_sdfg: (sdfg: JsonSDFG) => string; - init_sdfv: (sdfg: JsonSDFG, user_transform?: DOMMatrix | null, debug_draw?: boolean, existing_sdfv?: SDFV | null, toolbar?: boolean, minimap?: boolean | null) => SDFV; + init_sdfv: ( + sdfg: JsonSDFG, user_transform?: DOMMatrix | null, + debug_draw?: boolean, existing_sdfv?: SDFV | null, + toolbar?: boolean, minimap?: boolean | null + ) => SDFV; } } diff --git a/src/utils/bounding_box.ts b/src/utils/bounding_box.ts index 34be1b28..3743437b 100644 --- a/src/utils/bounding_box.ts +++ b/src/utils/bounding_box.ts @@ -1,10 +1,10 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { GraphEdge } from 'dagre'; import { Edge, SDFGElement } from '../renderer/renderer_elements'; -import { DagreSDFG } from '../index'; +import { DagreGraph } from '../index'; -export function calculateBoundingBox(g: DagreSDFG): DOMRect { +export function calculateBoundingBox(g: DagreGraph): DOMRect { // iterate over all objects, calculate the size of the bounding box const bb = new DOMRect(); bb.x = 0; diff --git a/src/utils/collections.ts b/src/utils/collections.ts index c69eb9c8..76519c50 100644 --- a/src/utils/collections.ts +++ b/src/utils/collections.ts @@ -1,10 +1,10 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. class ListNode { constructor( public value: T, - public next?: ListNode, + public next?: ListNode ) { } @@ -52,7 +52,7 @@ export class AccessStack extends LinkedStack { * Move a value to the top if it exists, and return its previous depth. * If the value is not in the stack, return -1 and push the value to * the stack. - * @param value + * @param value */ public touch(value: T): number { let depth = 0; diff --git a/src/utils/lerp_matrix.ts b/src/utils/lerp_matrix.ts index 3aa4b98b..b427523b 100644 --- a/src/utils/lerp_matrix.ts +++ b/src/utils/lerp_matrix.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. /** * Returns a function taking a number from 0 to 1 which linearly interpolates @@ -12,7 +12,7 @@ export function lerpMatrix( function decompose(m: DOMMatrix): any { const scale = [ Math.sqrt(m.a * m.a + m.b * m.b), - Math.sqrt(m.c * m.c + m.d * m.d) + Math.sqrt(m.c * m.c + m.d * m.d), ]; const det = m.a * m.d - m.b * m.c; @@ -62,11 +62,10 @@ export function lerpMatrix( } if (Math.abs(d1Angle - d2Angle) > 180) { - if (d1Angle > d2Angle) { + if (d1Angle > d2Angle) d1Angle -= 360; - } else { + else d2Angle -= 360; - } } diff --git a/src/utils/sanitization.ts b/src/utils/sanitization.ts index 48b28416..059ebca0 100644 --- a/src/utils/sanitization.ts +++ b/src/utils/sanitization.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. export function escapeHTML(s: string): string { const escapeCharacters: Map = new Map([ @@ -6,7 +6,7 @@ export function escapeHTML(s: string): string { ['<', '<'], ['>', '>'], ['"', '"'], - ["'", '''], + ['\'', '''], ]); return `${s}`.replace(/[&<>"']/g, m => escapeCharacters.get(m)!); @@ -15,8 +15,7 @@ export function escapeHTML(s: string): string { export function htmlSanitize( strings: TemplateStringsArray, ...values: any[] ): string { - return strings.length === 1 ? strings[0] - : strings.reduce( - (s, n, i) => `${s}${escapeHTML(String(values[i - 1]))}${n}` - ); + return strings.length === 1 ? strings[0] : strings.reduce( + (s, n, i) => `${s}${escapeHTML(String(values[i - 1]))}${n}` + ); } diff --git a/src/utils/sdfg/display.ts b/src/utils/sdfg/display.ts index d9230192..deb39cca 100644 --- a/src/utils/sdfg/display.ts +++ b/src/utils/sdfg/display.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { simplify } from 'mathjs'; @@ -7,9 +7,9 @@ export function sdfg_range_elem_to_string( settings: any = null ): string { let preview = ''; - if (range.start == range.end && range.step == 1 && range.tile == 1) + if (range.start === range.end && range.step === 1 && range.tile === 1) { preview += sdfg_property_to_string(range.start, settings); - else { + } else { if (settings && settings.inclusive_ranges) { preview += sdfg_property_to_string(range.start, settings) + '..' + sdfg_property_to_string(range.end, settings); @@ -21,11 +21,11 @@ export function sdfg_range_elem_to_string( preview += sdfg_property_to_string(range.start, settings) + ':' + endp1; } - if (range.step != 1) { + if (range.step !== 1) { preview += ':' + sdfg_property_to_string(range.step, settings); - if (range.tile != 1) + if (range.tile !== 1) preview += ':' + sdfg_property_to_string(range.tile, settings); - } else if (range.tile != 1) { + } else if (range.tile !== 1) { preview += '::' + sdfg_property_to_string(range.tile, settings); } } @@ -49,7 +49,8 @@ export function sdfg_property_to_string( prop: any, settings: any = null ): string { - if (prop === null || prop === undefined) return prop; + if (prop === null || prop === undefined) + return prop; if (typeof prop === 'boolean') { if (prop) return 'True'; @@ -57,18 +58,16 @@ export function sdfg_property_to_string( } else if (prop.type === 'Indices' || prop.type === 'subsets.Indices') { const indices = prop.indices; let preview = '['; - for (const index of indices) { + for (const index of indices) preview += sdfg_property_to_string(index, settings) + ', '; - } return preview.slice(0, -2) + ']'; } else if (prop.type === 'Range' || prop.type === 'subsets.Range') { const ranges = prop.ranges; // Generate string from range let preview = '['; - for (const range of ranges) { + for (const range of ranges) preview += sdfg_range_elem_to_string(range, settings) + ', '; - } return preview.slice(0, -2) + ']'; } else if (prop.type === 'LogicalGroup' && prop.color !== undefined && prop.name !== undefined) { @@ -77,18 +76,19 @@ export function sdfg_property_to_string( } else if (prop.language !== undefined) { // Code if (prop.string_data !== '' && prop.string_data !== undefined && - prop.string_data !== null) + prop.string_data !== null) { return '
' + prop.string_data.trim() +
                 '
'; + } return ''; } else if (prop.approx !== undefined && prop.main !== undefined) { // SymExpr return prop.main; - } else if (prop.constructor == Object) { + } else if (prop.constructor === Object) { // General dictionary return '
' + JSON.stringify(prop, undefined, 4) +
             '
'; - } else if (prop.constructor == Array) { + } else if (prop.constructor === Array) { // General array let result = '[ '; let first = true; @@ -120,28 +120,31 @@ export function string_to_sdfg_typeclass(str: string): any { argstring.substring(0, splitidx) ); const count = argstring.substring(splitidx); - if (dtype && count) + if (dtype && count) { return { type: 'vector', dtype: dtype, elements: count, }; + } } } } else if (str.startsWith('pointer(')) { const argstring = str.substring(8, str.length - 1); - if (argstring) + if (argstring) { return { type: 'pointer', dtype: string_to_sdfg_typeclass(argstring), }; + } } else if (str.startsWith('opaque(')) { const argstring = str.substring(7, str.length - 1); - if (argstring) + if (argstring) { return { type: 'opaque', name: argstring, }; + } } else if (str.startsWith('callback(')) { const argstring = str.substring(9, str.length - 1); if (argstring) { @@ -158,17 +161,19 @@ export function string_to_sdfg_typeclass(str: string): any { ); const cb_args: any[] = []; - if (cb_args_raw) + if (cb_args_raw) { cb_args_raw.forEach(raw_arg => { cb_args.push(string_to_sdfg_typeclass(raw_arg)); }); + } - if (cb_args && ret_type) + if (cb_args && ret_type) { return { type: 'callback', arguments: cb_args, returntype: ret_type, }; + } } } } @@ -186,16 +191,18 @@ export function sdfg_typeclass_to_string(typeclass: any): string { switch (typeclass.type) { case 'vector': if (typeclass.elements !== undefined && - typeclass.dtype !== undefined) + typeclass.dtype !== undefined) { return 'vector(' + sdfg_typeclass_to_string( typeclass.dtype ) + ', ' + typeclass.elements + ')'; + } break; case 'pointer': - if (typeclass.dtype !== undefined) + if (typeclass.dtype !== undefined) { return 'pointer(' + sdfg_typeclass_to_string( typeclass.dtype ) + ')'; + } break; case 'opaque': if (typeclass.name !== undefined) @@ -212,12 +219,13 @@ export function sdfg_typeclass_to_string(typeclass: any): string { str += ', '; } str += '], '; - if (typeclass.returntype !== undefined) + if (typeclass.returntype !== undefined) { str += sdfg_typeclass_to_string( typeclass.returntype ); - else + } else { str += 'None'; + } str += ')'; return str; } diff --git a/src/utils/sdfg/json_serializer.ts b/src/utils/sdfg/json_serializer.ts index 46ea1efd..ba96f7bf 100644 --- a/src/utils/sdfg/json_serializer.ts +++ b/src/utils/sdfg/json_serializer.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { Edge, JsonSDFG } from '../../index'; import { gunzipSync } from 'zlib'; @@ -8,11 +8,11 @@ const propertyReplacements_0_16_0: { [key: string]: { replaceWith: string, recursive: boolean, }} = { - 'start_state': { + 'start_block': { replaceWith: 'start_block', recursive: false, }, - 'sdfg_list_id': { + 'cfg_list_id': { replaceWith: 'cfg_list_id', recursive: true, }, @@ -70,9 +70,12 @@ export function read_or_decompress( json: string | ArrayBuffer ): [string, boolean] { try { - return [new TextDecoder().decode( - gunzipSync(Buffer.from(json as Uint8Array)) - ), true]; + return [ + new TextDecoder().decode( + gunzipSync(Buffer.from(json as Uint8Array)) + ), + true, + ]; } catch { if (typeof json !== 'string') { const enc = new TextDecoder('utf-8'); @@ -92,9 +95,8 @@ export function stringify_sdfg(sdfg: JsonSDFG): string { } function reviver(name: string, val: unknown) { - if (name === 'sdfg' && val && typeof val === 'string' && val[0] === '{') { + if (name === 'sdfg' && val && typeof val === 'string' && val[0] === '{') return JSON.parse(val, reviver); - } return val; } diff --git a/src/utils/sdfg/memlet_trees.ts b/src/utils/sdfg/memlet_trees.ts new file mode 100644 index 00000000..74fedec2 --- /dev/null +++ b/src/utils/sdfg/memlet_trees.ts @@ -0,0 +1,255 @@ +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. + +import { + JsonSDFG, + JsonSDFGBlock, + JsonSDFGControlFlowRegion, + JsonSDFGEdge, + JsonSDFGNode, + JsonSDFGState, +} from '../../index'; +import { SDFGElementType } from '../../renderer/renderer_elements'; + + +/** + * Returns a partial memlet tree from a given edge. + * It descends into nested SDFGs. + * @param visitedEdges is used to speed up the computation of the memlet trees + **/ +export function memletTreeNested( + sdfg: JsonSDFG, + state: JsonSDFGState, + edge: JsonSDFGEdge, + visitedEdges: JsonSDFGEdge[] = [] +): any[] { + if (visitedEdges.includes(edge) || + edge.attributes.data.attributes.shortcut) + return []; + + visitedEdges.push(edge); + + let result: any[] = []; + + function src(e: JsonSDFGEdge): JsonSDFGNode { + return state.nodes[parseInt(e.src)]; + } + + function dst(e: JsonSDFGEdge): JsonSDFGNode { + return state.nodes[parseInt(e.dst)]; + } + + function isview(node: JsonSDFGNode) { + if (node.type === SDFGElementType.AccessNode) { + const nodedesc = sdfg.attributes._arrays[node.attributes.data]; + return (nodedesc && nodedesc.type === 'View'); + } + return false; + } + + // Determine propagation direction. + let propagateForward = false; + let propagateBackward = false; + if ((edge.src_connector && src(edge).type.endsWith('Entry')) || + (edge.dst_connector && dst(edge).type.endsWith('Entry') && + edge.dst_connector.startsWith('IN_')) || + dst(edge).type === SDFGElementType.NestedSDFG || + isview(dst(edge))) + propagateForward = true; + if ((edge.src_connector && src(edge).type.endsWith('Exit')) || + (edge.dst_connector && dst(edge).type.endsWith('Exit')) || + src(edge).type === SDFGElementType.NestedSDFG || + isview(src(edge))) + propagateBackward = true; + + result.push(edge); + + // If no scope is involved we return only the edge as a degenerate tree. + if (!propagateForward && !propagateBackward) + return result; + + // Descend recursively. + const addedChildren = new Set(); + + function checkNested( + cfg: JsonSDFGControlFlowRegion, nsdfg: JsonSDFG, name: string | null, + direction: 'in' | 'out' + ): void { + cfg.nodes.forEach((block: JsonSDFGBlock) => { + if (block.type === SDFGElementType.SDFGState) { + const nstate: JsonSDFGState = block as JsonSDFGState; + nstate.edges.forEach((e: any) => { + const node = nstate.nodes[ + direction === 'in' ? e.src : e.dst + ]; + if (node.type === SDFGElementType.AccessNode && + node.attributes.data === name) { + result = result.concat( + memletTreeNested( + nsdfg, nstate, e, visitedEdges + ) + ); + } + }); + } else { + checkNested( + block as JsonSDFGControlFlowRegion, nsdfg, name, direction + ); + } + }); + } + + function addChildren(edge: JsonSDFGEdge) { + if (addedChildren.has(edge)) + return; + addedChildren.add(edge); + + const children: JsonSDFGEdge[] = []; + + if (propagateForward) { + const next_node = dst(edge); + + // Descend into nested SDFG. + if (next_node.type === SDFGElementType.NestedSDFG) { + const name = edge.dst_connector; + const nsdfg = next_node.attributes.sdfg; + if (nsdfg) + checkNested(nsdfg, nsdfg, name, 'in'); + } + + if (isview(next_node)) { + state.edges.forEach((e: JsonSDFGEdge) => { + if (parseInt(e.src) === next_node.id) { + children.push(e); + if (!e.attributes.data.attributes.shortcut) + result.push(e); + } + }); + } else { + if (!next_node.type.endsWith('Entry') || + !edge.dst_connector?.startsWith('IN_')) + return; + if (next_node.attributes.is_collapsed) + return; + const conn = edge.dst_connector.substring(3); + state.edges.forEach((e: JsonSDFGEdge) => { + if (parseInt(e.src) === next_node.id && + e.src_connector === 'OUT_' + conn) { + children.push(e); + if (!e.attributes.data.attributes.shortcut) + result.push(e); + } + }); + } + } + + if (propagateBackward) { + const nextNode = src(edge); + + // Descend into nested SDFG. + if (nextNode.type === SDFGElementType.NestedSDFG) { + const name = edge.src_connector; + const nsdfg = nextNode.attributes.sdfg; + if (nsdfg) + checkNested(nsdfg, nsdfg, name, 'out'); + } + + if (isview(nextNode)) { + state.edges.forEach((e: JsonSDFGEdge) => { + if (parseInt(e.dst) === nextNode.id) { + children.push(e); + result.push(e); + } + }); + } else { + if (!(nextNode.type.endsWith('Exit')) || !edge.src_connector) + return; + + const conn = edge.src_connector.substring(4); + state.edges.forEach((e: JsonSDFGEdge) => { + if (parseInt(e.dst) === nextNode.id && + e.dst_connector === 'IN_' + conn) { + children.push(e); + result.push(e); + } + }); + } + } + + for (const child of children) + addChildren(child); + } + + // Descend starting from the current edge. + addChildren(edge); + + return result; +} + +/** + * Calls memletTreeNested for every nested SDFG and its edges and returns a + * list with all memlet trees. As edges are visited only in one direction (from + * outer SDFGs to inner SDFGs) a memlet can be split into several arrays. + */ +export function memletTreeRecursive( + cfg: JsonSDFGControlFlowRegion, sdfg: JsonSDFG +): any[] { + let trees: any[] = []; + const visitedEdges: JsonSDFGEdge[] = []; + + cfg.nodes.forEach((block: JsonSDFGBlock) => { + if (block.type === SDFGElementType.SDFGState) { + const state: JsonSDFGState = block as JsonSDFGState; + state.edges.forEach((e: JsonSDFGEdge) => { + const tree = memletTreeNested(sdfg, state, e, visitedEdges); + if (tree.length > 1) + trees.push(tree); + }); + + state.nodes.forEach((n: JsonSDFGNode) => { + if (n.type === SDFGElementType.NestedSDFG && + n.attributes.sdfg) { + const t = memletTreeRecursive(n.attributes.sdfg, sdfg); + trees = trees.concat(t); + } + }); + } else { + trees = trees.concat(memletTreeRecursive( + block as JsonSDFGControlFlowRegion, sdfg + )); + } + }); + + return trees; +} + +/** + * Returns all memlet trees as sets for the given graph. + * + * @param {JsonSDFG} sdfg The top level SDFG. + */ +export function memletTreeComplete(sdfg: JsonSDFG): any[] { + const allMemletTrees: any[] = []; + const memletTrees = memletTreeRecursive(sdfg, sdfg); + + // combine trees as memlet_tree_recursive does not necessarily return the + // complete trees (they might be split into several trees) + memletTrees.forEach(tree => { + let commonEdge = false; + for (const mt of allMemletTrees) { + for (const edge of tree) { + if (mt.has(edge)) { + tree.forEach((e: JsonSDFGEdge) => mt.add(e)); + commonEdge = true; + break; + } + } + if (commonEdge) + break; + } + if (!commonEdge) + allMemletTrees.push(new Set(tree)); + }); + + return allMemletTrees; +} + diff --git a/src/utils/sdfg/sdfg_parser.ts b/src/utils/sdfg/sdfg_parser.ts index 0884f4cf..d9716d77 100644 --- a/src/utils/sdfg/sdfg_parser.ts +++ b/src/utils/sdfg/sdfg_parser.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2023 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { JsonSDFG, @@ -13,7 +13,9 @@ export class SDFGParser { } public getStates(): SDFGStateParser[] { - return this.sdfg.nodes.map((x: JsonSDFGBlock) => new SDFGStateParser(x)); + return this.sdfg.nodes.map((x: JsonSDFGBlock) => { + return new SDFGStateParser(x); + }); } public static lookupSymbols( @@ -25,10 +27,10 @@ export class SDFGParser { let syms: any[] = []; - if (elem.constructor == Object) { + if (elem.constructor === Object) { // Memlet. const memlets = state.edges.filter((x: any) => { - return x.dst == elem.dst && x.src == elem.src; + return x.dst === elem.dst && x.src === elem.src; }); // Recurse into parent (since this a multigraph, all edges need to @@ -37,7 +39,7 @@ export class SDFGParser { // Find symbols used (may be Indices or Range). const mdata = m.attributes.data.attributes.subset; // Check for indices - if (mdata && mdata.type == 'subsets.Indices') { + if (mdata && mdata.type === 'subsets.Indices') { // These are constants or variables. // Reverse to have smallest unit first. const tmp = mdata.indices.map((x: any) => x).reverse(); @@ -47,7 +49,7 @@ export class SDFGParser { depth += 1; syms.push({ var: x, val: null, depth: depth }); } - } else if (mdata && mdata.type == 'subsets.Range') { + } else if (mdata && mdata.type === 'subsets.Range') { // These are ranges. // These ranges are not of interest, as they specify what is // copied and don't define new variables. @@ -71,7 +73,7 @@ export class SDFGParser { const params = node.attributes.params.map((x: any) => x); console.assert( - rngs.length == params.length, + rngs.length === params.length, 'Ranges and params should have the same count of elements' ); @@ -83,21 +85,22 @@ export class SDFGParser { for (let i = 0; i < rngs.length; ++i) { // Check first if the variable is already defined, and if // yes, if the value is the same. - const fltrd = syms.filter(x => x.var == params[i]); - if (fltrd.length == 0) { + const fltrd = syms.filter(x => x.var === params[i]); + if (fltrd.length === 0) { depth += 1; syms.push({ var: params[i], val: rngs[i], - depth: depth + depth: depth, }); } else { - if (JSON.stringify(fltrd[0].val) != - JSON.stringify(rngs[i])) + if (JSON.stringify(fltrd[0].val) !== + JSON.stringify(rngs[i])) { console.warn( 'Colliding definitions for var ' + params[i], fltrd[0].val, rngs[i] ); + } } } } catch (e) { @@ -105,7 +108,7 @@ export class SDFGParser { // consumes). } // Find all incoming edges. - const inc_edges = state.edges.filter((x: any) => x.dst == elem); + const inc_edges = state.edges.filter((x: any) => x.dst === elem); for (const e of inc_edges) { const tmp = SDFGParser.lookupSymbols( sdfg, stateId, e, symbolsToResolve, depth + 1 @@ -116,6 +119,7 @@ export class SDFGParser { return syms; } + } export class SDFGStateParser { @@ -135,6 +139,7 @@ export class SDFGStateParser { } }); } + } export class SDFGNodeParser { diff --git a/src/utils/sdfg/sdfg_utils.ts b/src/utils/sdfg/sdfg_utils.ts index 5e3d7876..b20ef97b 100644 --- a/src/utils/sdfg/sdfg_utils.ts +++ b/src/utils/sdfg/sdfg_utils.ts @@ -1,68 +1,35 @@ -// Copyright 2019-2023 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import { + CFGListType, + DagreGraph, + JsonSDFGBlock, + JsonSDFGControlFlowRegion, + JsonSDFGEdge, + JsonSDFGNode, + JsonSDFGState, +} from '../../index'; +import { + ControlFlowRegion, Edge, SDFGElement, + SDFGElementType, SDFGNode, - NestedSDFG, State, } from '../../renderer/renderer_elements'; -import { - DagreSDFG, - JsonSDFG, - JsonSDFGEdge, - JsonSDFGNode, - JsonSDFGState, -} from '../../index'; -export function recursively_find_graph( - graph: DagreSDFG, - graph_id: number, - ns_node: SDFGNode | undefined = undefined -): { graph: DagreSDFG | undefined, node: SDFGNode | undefined } { - if (graph.node('0').sdfg.cfg_list_id === graph_id) { - return { - graph: graph, - node: ns_node, - }; - } else { - const result = { - graph: undefined, - node: undefined, - }; - for (const state_id of graph.nodes()) { - const state = graph.node(state_id); - if (state.data.graph !== undefined && state.data.graph !== null) - for (const node_id of state.data.graph.nodes()) { - const node = state.data.graph.node(node_id); - if (node instanceof NestedSDFG) { - const search_graph = recursively_find_graph( - node.data.graph, graph_id, node - ); - if (search_graph.graph !== undefined) { - return search_graph; - } - } - } - } - return result; - } -} - - -export function find_exit_for_entry( - nodes: JsonSDFGNode[], entry_node: JsonSDFGNode +export function findExitForEntry( + nodes: JsonSDFGNode[], entryNode: JsonSDFGNode ): JsonSDFGNode | null { for (const n of nodes) { if (n.type.endsWith('Exit') && n.scope_entry && - parseInt(n.scope_entry) == entry_node.id) + parseInt(n.scope_entry) === entryNode.id) return n; } console.warn('Did not find corresponding exit'); return null; } - /** * Return the string UUID for an SDFG graph element. * @@ -76,18 +43,23 @@ export function find_exit_for_entry( * * @returns String containing the UUID */ -export function get_uuid_graph_element(element: SDFGElement | null): string { +export function getGraphElementUUID(element: SDFGElement | null): string { const undefined_val = -1; + const cfgId = ( + element instanceof ControlFlowRegion ? + element.data.block.cfg_list_id : + element?.cfg?.cfg_list_id + ) ?? undefined_val; if (element instanceof State) { return ( - element.sdfg.cfg_list_id + '/' + + cfgId + '/' + element.id + '/' + undefined_val + '/' + undefined_val ); } else if (element instanceof SDFGNode) { return ( - element.sdfg.cfg_list_id + '/' + + cfgId + '/' + element.parent_id + '/' + element.id + '/' + undefined_val @@ -97,14 +69,14 @@ export function get_uuid_graph_element(element: SDFGElement | null): string { if (element.parent_id !== null && element.parent_id !== undefined) parent_id = element.parent_id; return ( - element.sdfg.cfg_list_id + '/' + + cfgId + '/' + parent_id + '/' + undefined_val + '/' + element.id ); } return ( - undefined_val + '/' + + cfgId + '/' + undefined_val + '/' + undefined_val + '/' + undefined_val @@ -134,73 +106,47 @@ export function check_and_redirect_edge( return new_edge; } -export function find_graph_element_by_uuid( - p_graph: DagreSDFG | undefined | null, uuid: string -): { parent: DagreSDFG | undefined, element: any } { - const uuid_split = uuid.split('/'); - - const graph_id = Number(uuid_split[0]); - const state_id = Number(uuid_split[1]); - const node_id = Number(uuid_split[2]); - const edge_id: any = Number(uuid_split[3]); - - let result: { - parent: DagreSDFG | undefined, - element: any, - } = { - parent: undefined, - element: undefined, - }; - - if (!p_graph) - return result; - - let graph = p_graph; - if (graph_id > 0) { - const found_graph = recursively_find_graph(graph, graph_id); - if (found_graph.graph === undefined) - throw new Error(); +export function findGraphElementByUUID( + cfgList: CFGListType, cfgTree: { [key: number]: number }, uuid: string +): SDFGElement | null { + const uuidParts = uuid.split('/'); - graph = found_graph.graph; - result = { - parent: graph, - element: found_graph.node, - }; - } + const cfgId = uuidParts[0]; + const stateId = uuidParts[1]; + const nodeId = uuidParts[2]; + const edgeId = uuidParts[3]; - let state = undefined; - if (state_id !== -1 && graph !== undefined) { - state = graph.node(state_id.toString()); - result = { - parent: graph, - element: state, - }; - } + if (!(cfgId in cfgList)) + return null; - if (node_id !== -1 && state !== undefined && state.data.graph !== null) { - // Look for a node in a state. - result = { - parent: state.data.graph, - element: state.data.graph.node(node_id), - }; - } else if ( - edge_id !== -1 && state !== undefined && - state.data.graph !== null - ) { - // Look for an edge in a state. - result = { - parent: state.data.graph, - element: state.data.graph.edge(edge_id), - }; - } else if (edge_id !== -1 && state === undefined) { - // Look for an inter-state edge. - result = { - parent: graph, - element: graph.edge(edge_id), - }; - } + const graph = cfgList[cfgId].graph; + if (graph === null) + return null; - return result; + let state = null; + if (stateId !== '-1') + state = graph.node(stateId); + + let element = null; + if (nodeId !== '-1' && state !== null && state.data.graph !== null) + element = state.data.graph.node(nodeId); // SDFG Dataflow graph node + else if (edgeId !== '-1' && state !== null && state.data.graph !== null) + element = state.data.graph.edge(edgeId); // Memlet + else if (edgeId !== '-1' && state === null) + element = graph.edge(edgeId as any); // Interstate edge + + if (element) + return element; + if (state) + return state; + + const parentCfgId = cfgTree[Number(cfgId)]; + if (parentCfgId === undefined || parentCfgId === null) + return null; + const parentCfg = cfgList[parentCfgId].graph; + if (!parentCfg) + return null; + return parentCfg.node(cfgList[cfgId].jsonObj.id.toString()) ?? null; } /** @@ -219,7 +165,7 @@ export function initialize_positioning_info(elem: any): any { position = { points: points ? points : [], scope_dx: 0, - scope_dy: 0 + scope_dy: 0, }; for (let i = 0; elem.points && i < elem.points.length; i++) @@ -277,53 +223,78 @@ export function deletePositioningInfo(elem: any): void { } -export function find_root_sdfg( - sdfgs: Iterable, sdfg_tree: { [key: number]: number } +export function findRootCFG( + cfgs: Iterable, cfgTree: { [key: number]: number }, + cfgList: CFGListType, + sdfgsOnly: boolean = false ): number | null { - const make_sdfg_path = (sdfg: number, array: Array) => { - array.push(sdfg); - if (sdfg in sdfg_tree) { - make_sdfg_path(sdfg_tree[sdfg], array); - } + const makeCFGPath = (cfg: number, path: Array) => { + path.push(cfg); + if (cfg in cfgTree) + makeCFGPath(cfgTree[cfg], path); }; - let common_sdfgs: Array | null = null; - for (const sid of sdfgs) { + + let commonCFGs: Array | null = null; + for (const sid of cfgs) { const path: Array = []; - make_sdfg_path(sid, path); + makeCFGPath(sid, path); - if (common_sdfgs === null) - common_sdfgs = path; - else - common_sdfgs = [...common_sdfgs].filter( + if (commonCFGs === null) { + commonCFGs = path; + } else { + commonCFGs = [...commonCFGs].filter( (x: number) => path.includes(x) ); + } } + // Return the first one (greatest common denominator). - if (common_sdfgs && common_sdfgs.length > 0) - return common_sdfgs[0]; + // If only looking for SDFGs, only return the first one that is of type + // SDFG. + if (commonCFGs && commonCFGs.length > 0) { + for (let i = 0; i < commonCFGs.length; i++) { + const cfgId = commonCFGs[i]; + const cfg = cfgList[cfgId].jsonObj; + if (sdfgsOnly) { + if (cfg.type === 'SDFG') + return cfgId; + } else { + return cfgId; + } + } + } // No root SDFG found. return null; } // In-place delete of SDFG state nodes. -export function delete_sdfg_nodes( - sdfg: JsonSDFG, state_id: number, nodes: Array, +export function deleteSDFGNodes( + cfg: JsonSDFGControlFlowRegion, stateId: number, nodeIds: number[], delete_others = false ): void { - const state: JsonSDFGState = sdfg.nodes[state_id]; - nodes.sort((a, b) => (a - b)); + const block = cfg.nodes[stateId]; + if (block.type !== SDFGElementType.SDFGState) { + console.warn( + 'Trying to delete an SDFG node, but parent element', + block, 'is not of type SDFGState' + ); + return; + } + + const state: JsonSDFGState = block as JsonSDFGState; + nodeIds.sort((a, b) => (a - b)); const mapping: { [key: string]: string } = { '-1': '-1' }; state.nodes.forEach((n: JsonSDFGNode) => mapping[n.id] = '-1'); let predicate: CallableFunction; if (delete_others) - predicate = (ind: number) => nodes.includes(ind); + predicate = (ind: number) => nodeIds.includes(ind); else - predicate = (ind: number) => !nodes.includes(ind); + predicate = (ind: number) => !nodeIds.includes(ind); state.nodes = state.nodes.filter((_v, ind: number) => predicate(ind)); state.edges = state.edges.filter((e: JsonSDFGEdge) => ( - predicate(parseInt(e.src)) && predicate(parseInt(e.dst)) + predicate(parseInt(e.src)) && predicate(parseInt(e.dst)) )); // Remap node and edge indices. @@ -355,33 +326,35 @@ export function delete_sdfg_nodes( state.scope_dict = new_scope_dict; } -export function delete_sdfg_states( - sdfg: JsonSDFG, states: Array, delete_others = false +export function deleteCFGBlocks( + cfg: JsonSDFGControlFlowRegion, blockIds: number[], + deleteOthers: boolean = false ): void { - states.sort((a, b) => (a - b)); + blockIds.sort((a, b) => (a - b)); let predicate: CallableFunction; - if (delete_others) - predicate = (ind: number) => states.includes(ind); + if (deleteOthers) + predicate = (ind: number) => blockIds.includes(ind); else - predicate = (ind: number) => !states.includes(ind); + predicate = (ind: number) => !blockIds.includes(ind); - sdfg.nodes = sdfg.nodes.filter((_v, ind: number) => predicate(ind)); - sdfg.edges = sdfg.edges.filter((e: JsonSDFGEdge) => ( + cfg.nodes = cfg.nodes.filter((_v, ind: number) => predicate(ind)); + cfg.edges = cfg.edges.filter((e: JsonSDFGEdge) => ( predicate(parseInt(e.src)) && predicate(parseInt(e.dst)) )); // Remap node and edge indices. const mapping: { [key: string]: string } = {}; - sdfg.nodes.forEach((n: JsonSDFGState, index: number) => { + cfg.nodes.forEach((n: JsonSDFGBlock, index: number) => { mapping[n.id] = index.toString(); n.id = index; }); - sdfg.edges.forEach((e: JsonSDFGEdge) => { + cfg.edges.forEach((e: JsonSDFGEdge) => { e.src = mapping[e.src]; e.dst = mapping[e.dst]; }); - if (mapping[sdfg.start_block] === '-1') - sdfg.start_block = 0; + if (mapping[cfg.start_block] === '-1' || + mapping[cfg.start_block] === undefined) + cfg.start_block = 0; else - sdfg.start_block = parseInt(mapping[sdfg.start_block]); + cfg.start_block = parseInt(mapping[cfg.start_block]); } diff --git a/src/utils/sdfg/traversal.ts b/src/utils/sdfg/traversal.ts index faa0ca70..795b62e7 100644 --- a/src/utils/sdfg/traversal.ts +++ b/src/utils/sdfg/traversal.ts @@ -1,22 +1,6 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. -import { - Edge as DagreEdge -} from 'dagre'; -import { - Edge, - EntryNode, - ExitNode, - SDFGElementType, - SDFGNode, -} from '../../renderer/renderer_elements'; -import { - DagreSDFG, - JsonSDFG, - JsonSDFGEdge, - JsonSDFGNode, - JsonSDFGState, -} from '../../index'; +import { DagreGraph, SDFGNode } from '../../index'; /** * Receives a callback that accepts (node, parent graph) and returns a value. @@ -25,11 +9,12 @@ import { * visited. The function also accepts an optional post-subscope callback (same * signature as `func`). **/ - export function traverseSDFGScopes( - sdfg: DagreSDFG, func: CallableFunction, postSubscopeFunc?: CallableFunction +export function traverseSDFGScopes( + sdfg: DagreGraph, func: (gNode: SDFGNode, g: DagreGraph) => boolean, + postSubscopeFunc?: (gNode: SDFGNode, g: DagreGraph) => void ): void { function scopesRecursive( - graph: DagreSDFG, nodes: string[], processedNodes?: Set + graph: DagreGraph, nodes: string[], processedNodes?: Set ): void { if (processedNodes === undefined) processedNodes = new Set(); @@ -49,22 +34,25 @@ import { if (node.type().endsWith('Entry') && node.parent_id !== null && node.id !== null) { const state = node.parentElem?.data.state; - if (state.scope_dict[node.id] !== undefined) + if (state.scope_dict[node.id] !== undefined) { scopesRecursive( graph, state.scope_dict[node.id], processedNodes ); + } } // Traverse states or nested SDFGs if (node.data.graph) { const state = node.data.state; if (state !== undefined && - state.scope_dict[-1] !== undefined) + state.scope_dict[-1] !== undefined) { scopesRecursive(node.data.graph, state.scope_dict[-1]); - else // No scope_dict, traverse all nodes as a flat hierarchy + } else { + // No scope_dict, traverse all nodes as a flat hierarchy scopesRecursive( node.data.graph, node.data.graph.nodes() ); + } } } @@ -77,361 +65,3 @@ import { scopesRecursive(sdfg, sdfg.nodes()); } - - - -/** - * Returns a partial memlet tree from a given edge, from the root node - * through all children (without siblings). Calling this function with - * the root edge returns the entire memlet tree. - **/ -export function memlet_tree( - graph: DagreSDFG, - edge: Edge, - root_only: boolean = false -): any[] { - const result = []; - const graph_edges: any = {}; - graph.edges().forEach((e: DagreEdge) => { - if (e.name) - graph_edges[e.name] = e; - }); - - - function src(e: any): SDFGNode { - const ge = graph_edges[e.id]; - return graph.node(ge.v); - } - function dst(e: any): SDFGNode { - const ge = graph_edges[e.id]; - return graph.node(ge.w); - } - - // Determine direction - let propagate_forward = false, propagate_backward = false; - if ((edge.src_connector && src(edge) instanceof EntryNode) || - (edge.dst_connector && dst(edge) instanceof EntryNode && - edge.dst_connector.startsWith('IN_'))) - propagate_forward = true; - if ((edge.src_connector && src(edge) instanceof ExitNode) || - (edge.dst_connector && dst(edge) instanceof ExitNode)) - propagate_backward = true; - - result.push(edge); - - // If either both are false (no scopes involved) or both are true - // (invalid SDFG), we return only the current edge as a degenerate tree - if (propagate_forward == propagate_backward) - return result; - - // Ascend (find tree root) while prepending - let curedge: any = edge; - if (propagate_forward) { - let source = src(curedge); - while (source instanceof EntryNode && curedge && curedge.src_connector) { - if (source.attributes().is_collapsed) - break; - - const cname = curedge.src_connector.substring(4); // Remove OUT_ - curedge = null; - graph.inEdges(source.id.toString())?.forEach(e => { - const ge = graph.edge(e); - if (ge.dst_connector == 'IN_' + cname) - curedge = ge; - }); - if (curedge) { - result.unshift(curedge); - source = src(curedge); - } - } - } else if (propagate_backward) { - let dest = dst(curedge); - while (dest instanceof ExitNode && curedge && curedge.dst_connector) { - const cname = curedge.dst_connector.substring(3); // Remove IN_ - curedge = null; - graph.outEdges(dest.id.toString())?.forEach(e => { - const ge = graph.edge(e); - if (ge.src_connector == 'OUT_' + cname) - curedge = ge; - }); - if (curedge) { - result.unshift(curedge); - dest = dst(curedge); - } - } - } - - if (root_only) - return [result[0]]; - - // Descend recursively - function add_children(edge: any) { - const children: any[] = []; - if (propagate_forward) { - const next_node = dst(edge); - if (!(next_node instanceof EntryNode) || - !edge.dst_connector || !edge.dst_connector.startsWith('IN_')) - return; - if (next_node.attributes().is_collapsed) - return; - const conn = edge.dst_connector.substring(3); - graph.outEdges(next_node.id.toString())?.forEach(e => { - const ge = graph.edge(e); - if (ge.src_connector == 'OUT_' + conn) { - children.push(ge); - result.push(ge); - } - }); - } else if (propagate_backward) { - const next_node = src(edge); - if (!(next_node instanceof ExitNode) || !edge.src_connector) - return; - const conn = edge.src_connector.substring(4); - graph.inEdges(next_node.id.toString())?.forEach(e => { - const ge = graph.edge(e); - if (ge.dst_connector == 'IN_' + conn) { - children.push(ge); - result.push(ge); - } - }); - } - - for (const child of children) - add_children(child); - } - - // Start from current edge - add_children(edge); - - return result; -} - -/** - * Returns a partial memlet tree from a given edge. It descends into nested SDFGs. - * @param visited_edges is used to speed up the computation of the memlet trees - **/ -export function memlet_tree_nested( - sdfg: JsonSDFG, - state: JsonSDFGState, - edge: JsonSDFGEdge, - visited_edges: JsonSDFGEdge[] = [] -): any[] { - if (visited_edges.includes(edge) || - edge.attributes.data.attributes.shortcut) { - return []; - } - - visited_edges.push(edge); - - let result: any[] = []; - - function src(e: JsonSDFGEdge): JsonSDFGNode { - return state.nodes[parseInt(e.src)]; - } - - function dst(e: JsonSDFGEdge): JsonSDFGNode { - return state.nodes[parseInt(e.dst)]; - } - - function isview(node: JsonSDFGNode) { - if (node.type === SDFGElementType.AccessNode) { - const nodedesc = sdfg.attributes._arrays[node.attributes.data]; - return (nodedesc && nodedesc.type === 'View'); - } - return false; - } - - // Determine propagation direction. - let propagate_forward = false; - let propagate_backward = false; - if ((edge.src_connector && src(edge).type.endsWith('Entry')) || - (edge.dst_connector && dst(edge).type.endsWith('Entry') && - edge.dst_connector.startsWith('IN_')) || - dst(edge).type === SDFGElementType.NestedSDFG || - isview(dst(edge))) - propagate_forward = true; - if ((edge.src_connector && src(edge).type.endsWith('Exit')) || - (edge.dst_connector && dst(edge).type.endsWith('Exit')) || - src(edge).type === SDFGElementType.NestedSDFG || - isview(src(edge))) - propagate_backward = true; - - result.push(edge); - - // If no scope is involved we return only the edge as a degenerate tree. - if (!propagate_forward && !propagate_backward) - return result; - - // Descend recursively. - const added_children = new Set(); - function add_children(edge: JsonSDFGEdge) { - if (added_children.has(edge)) - return; - added_children.add(edge); - - const children: JsonSDFGEdge[] = []; - - if (propagate_forward) { - const next_node = dst(edge); - - // Descend into nested SDFG. - if (next_node.type === SDFGElementType.NestedSDFG) { - const name = edge.dst_connector; - const nested_sdfg = next_node.attributes.sdfg; - - nested_sdfg?.nodes.forEach((nstate: any) => { - nstate.edges.forEach((e: any) => { - const node = nstate.nodes[e.src]; - if (node.type === SDFGElementType.AccessNode && - node.attributes.data === name) { - result = result.concat( - memlet_tree_nested( - nested_sdfg, nstate, e, visited_edges - ) - ); - } - }); - }); - } - - if (isview(next_node)) { - state.edges.forEach((e: JsonSDFGEdge) => { - if (parseInt(e.src) === next_node.id) { - children.push(e); - if (!e.attributes.data.attributes.shortcut) - result.push(e); - } - }); - } else { - if (!next_node.type.endsWith('Entry') || - !edge.dst_connector?.startsWith('IN_')) - return; - if (next_node.attributes.is_collapsed) - return; - const conn = edge.dst_connector.substring(3); - state.edges.forEach((e: JsonSDFGEdge) => { - if (parseInt(e.src) === next_node.id && - e.src_connector === 'OUT_' + conn) { - children.push(e); - if (!e.attributes.data.attributes.shortcut) - result.push(e); - } - }); - } - } - - if (propagate_backward) { - const next_node = src(edge); - - // Descend into nested SDFG. - if (next_node.type === SDFGElementType.NestedSDFG) { - const name = edge.src_connector; - const nested_sdfg = next_node.attributes.sdfg; - - nested_sdfg?.nodes.forEach((nstate: JsonSDFGState) => { - nstate.edges.forEach((e: JsonSDFGEdge) => { - const node = nstate.nodes[parseInt(e.dst)]; - if (node.type === SDFGElementType.AccessNode && - node.attributes.data === name) { - result = result.concat( - memlet_tree_nested( - nested_sdfg, nstate, e, visited_edges - ) - ); - } - }); - }); - } - - if (isview(next_node)) { - state.edges.forEach((e: JsonSDFGEdge) => { - if (parseInt(e.dst) === next_node.id) { - children.push(e); - result.push(e); - } - }); - } else { - if (!(next_node.type.endsWith('Exit')) || !edge.src_connector) - return; - - const conn = edge.src_connector.substring(4); - state.edges.forEach((e: JsonSDFGEdge) => { - if (parseInt(e.dst) === next_node.id && - e.dst_connector === 'IN_' + conn) { - children.push(e); - result.push(e); - } - }); - } - } - - for (const child of children) - add_children(child); - } - - // Descend starting from the current edge. - add_children(edge); - - return result; -} - -/** - * Calls memlet_tree_nested for every nested SDFG and its edges and returns a - * list with all memlet trees. As edges are visited only in one direction (from - * outer SDFGs to inner SDFGs) a memlet can be split into several arrays. - */ -export function memlet_tree_recursive(root_sdfg: JsonSDFG): any[] { - let trees: any[] = []; - const visited_edges: JsonSDFGEdge[] = []; - - root_sdfg.nodes.forEach((state: JsonSDFGState) => { - - state.edges.forEach((e: JsonSDFGEdge) => { - const tree = memlet_tree_nested(root_sdfg, state, e, visited_edges); - if (tree.length > 1) { - trees.push(tree); - } - }); - - state.nodes.forEach((n: JsonSDFGNode) => { - if (n.type == SDFGElementType.NestedSDFG && n.attributes.sdfg) { - const t = memlet_tree_recursive(n.attributes.sdfg); - trees = trees.concat(t); - } - }); - - }); - - return trees; -} - -/** - * Returns all memlet trees as sets for the given graph. - * - * @param {Graph} root_graph The top level graph. - */ -export function memlet_tree_complete(sdfg: JsonSDFG): any[] { - const all_memlet_trees: any[] = []; - const memlet_trees = memlet_tree_recursive(sdfg); - - // combine trees as memlet_tree_recursive does not necessarily return the - // complete trees (they might be split into several trees) - memlet_trees.forEach(tree => { - let common_edge = false; - for (const mt of all_memlet_trees) { - for (const edge of tree) { - if (mt.has(edge)) { - tree.forEach((e: JsonSDFGEdge) => mt.add(e)); - common_edge = true; - break; - } - } - if (common_edge) - break; - } - if (!common_edge) - all_memlet_trees.push(new Set(tree)); - }); - - return all_memlet_trees; -} diff --git a/src/utils/sdfv_settings.ts b/src/utils/sdfv_settings.ts index 74d04099..5600a44b 100644 --- a/src/utils/sdfv_settings.ts +++ b/src/utils/sdfv_settings.ts @@ -1,4 +1,4 @@ -// Copyright 2019-2022 ETH Zurich and the DaCe authors. All rights reserved. +// Copyright 2019-2024 ETH Zurich and the DaCe authors. All rights reserved. import $ from 'jquery'; @@ -75,8 +75,8 @@ export class SDFVSettings { }).append($('
', { text: 'View Settings', css: { - 'font-weight': 'bold' - } + 'font-weight': 'bold', + }, })); $('
', { class: 'row', @@ -116,8 +116,8 @@ export class SDFVSettings { })).append($('
', { text: 'Mouse Settings', css: { - 'font-weight': 'bold' - } + 'font-weight': 'bold', + }, })); $('
', { class: 'row', @@ -135,19 +135,20 @@ export class SDFVSettings { })).append($('
', { text: 'Performance Settings', css: { - 'font-weight': 'bold' - } + 'font-weight': 'bold', + }, })); $('
', { class: 'row', }).appendTo(root).append(performanceSettingsTitle); - // TODO: Remove this setting as disabling the adaptive content hiding can cause - // massive performance issues. TODO: add sliders for LOD thresholds of sdfv.ts - // into an advanced settings menu. + // TODO: Remove this setting as disabling the adaptive content hiding + // can cause massive performance issues. TODO: add sliders for LOD + // thresholds of sdfv.ts into an advanced settings menu. this.addToggle( - root, 'Adaptively hide content when zooming out (Warning: turning this off can cause\ - huge performance issues on big graphs)', + root, + 'Adaptively hide content when zooming out (Warning: turning this \ + off can cause huge performance issues on big graphs)', 'adaptiveContentHiding', false, (value: boolean) => { if (this.renderer) (this.renderer.get_context() as any).lod = value; @@ -183,7 +184,7 @@ export class SDFVSettings { text: 'Settings', })).append($('
', { id: 'task-info-field-settings', - style: 'margin-left: 15px;' + style: 'margin-left: 15px;', })).append($('