summaryrefslogtreecommitdiff
path: root/chromium/third_party/webgpu-cts
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/third_party/webgpu-cts
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-c30a6232df03e1efbd9f3b226777b07e087a1122.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/webgpu-cts')
-rw-r--r--chromium/third_party/webgpu-cts/src/.eslint-resolver.js23
-rw-r--r--chromium/third_party/webgpu-cts/src/.eslintrc.json73
-rw-r--r--chromium/third_party/webgpu-cts/src/.travis.yml2
-rw-r--r--chromium/third_party/webgpu-cts/src/.vscode/tasks.json7
-rw-r--r--chromium/third_party/webgpu-cts/src/CONTRIBUTING.md2
-rw-r--r--chromium/third_party/webgpu-cts/src/Gruntfile.js69
-rw-r--r--chromium/third_party/webgpu-cts/src/README.md7
-rw-r--r--chromium/third_party/webgpu-cts/src/babel.config.js2
-rw-r--r--chromium/third_party/webgpu-cts/src/docs/terms.md278
-rw-r--r--chromium/third_party/webgpu-cts/src/package-lock.json6674
-rw-r--r--chromium/third_party/webgpu-cts/src/package.json44
-rw-r--r--chromium/third_party/webgpu-cts/src/prettier.config.js1
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/allowed_characters.ts2
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/file_loader.ts51
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/fixture.ts28
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/generate_minimal_query_list.ts112
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/gpu/device_pool.ts140
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/id.ts25
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/listing.ts9
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/loader.ts65
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/logger.ts159
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/logging/log_message.ts37
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/logging/logger.ts25
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/logging/result.ts18
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/logging/test_case_recorder.ts126
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/params.ts112
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/params_builder.ts127
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/params_utils.ts77
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/query/compare.ts93
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/query/encode_selectively.ts20
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/query/parseQuery.ts132
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/query/query.ts123
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/query/separators.ts14
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/query/stringify_params.ts28
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/query/validQueryPart.ts2
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/filter_by_group.ts52
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/filter_one_file.ts153
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/internal.ts17
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/load_filter.ts63
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/test_filter_result.ts8
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/test_group.ts181
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/test_suite_listing.ts16
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/tree.ts469
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/url_query.ts42
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/util/collect_garbage.ts (renamed from chromium/third_party/webgpu-cts/src/src/common/framework/collect_garbage.ts)15
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/util/stack.ts34
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/framework/util/util.ts28
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/runtime/cmdline.ts86
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker-worker.ts31
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker.ts24
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/runtime/standalone.ts191
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/runtime/wpt.ts79
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/templates/cts.html20
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/tools/.eslintrc.json8
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/tools/crawl.ts65
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/tools/gen_listings.ts3
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/tools/gen_wpt_cts_html.ts48
-rw-r--r--chromium/third_party/webgpu-cts/src/src/common/tools/setup-ts-in-node.js2
-rw-r--r--chromium/third_party/webgpu-cts/src/src/demo/README.txt1
-rw-r--r--chromium/third_party/webgpu-cts/src/src/demo/a.spec.ts6
-rw-r--r--chromium/third_party/webgpu-cts/src/src/demo/a/README.txt1
-rw-r--r--chromium/third_party/webgpu-cts/src/src/demo/a/b.spec.ts6
-rw-r--r--chromium/third_party/webgpu-cts/src/src/demo/a/b/README.txt1
-rw-r--r--chromium/third_party/webgpu-cts/src/src/demo/a/b/c.spec.ts39
-rw-r--r--chromium/third_party/webgpu-cts/src/src/demo/a/b/d.spec.ts8
-rw-r--r--chromium/third_party/webgpu-cts/src/src/demo/file_depth_2/in_single_child_dir/r.spec.ts6
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/async_mutex.spec.ts19
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/basic.spec.ts52
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/getStackTrace.spec.ts148
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/listing.ts2
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/loaders_and_trees.spec.ts360
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/loading.spec.ts348
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/logger.spec.ts154
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/make_filter.spec.ts11
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/param_helpers.spec.ts84
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/params.spec.ts74
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/params_builder_and_utils.spec.ts140
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/params_builder_toplevel.spec.ts95
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/query_compare.spec.ts133
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/test_filter.spec.ts82
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/test_group.spec.ts202
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/test_group_test.ts40
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/test_query.spec.ts56
-rw-r--r--chromium/third_party/webgpu-cts/src/src/unittests/url_query.spec.ts76
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/create_mapped.spec.ts33
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map.spec.ts89
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_detach.spec.ts94
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_oom.spec.ts30
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/basic.spec.ts6
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/compute/basic.spec.ts6
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/copies.spec.ts10
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/basic.spec.ts6
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/rendering.spec.ts8
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/storeop.spec.ts121
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/fences.spec.ts38
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/copied_texture_clear.spec.ts86
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/depth_stencil_attachment_clear.spec.ts211
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/sampled_texture_clear.spec.ts276
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/texture_zero_init_test.ts581
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroup.spec.ts357
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroupLayout.spec.ts318
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createPipelineLayout.spec.ts148
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createRenderPipeline.spec.ts216
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createTexture.spec.ts185
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createView.spec.ts297
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/error_scope.spec.ts16
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/fences.spec.ts40
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/queue_submit.spec.ts6
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass.spec.ts140
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass_descriptor.spec.ts416
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBindGroup.spec.ts250
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBlendColor.spec.ts8
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setScissorRect.spec.ts44
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setStencilReference.spec.ts24
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setVertexBuffer.spec.ts8
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setViewport.spec.ts74
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/validation_test.ts57
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/vertex_state.spec.ts269
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/capability_info.ts294
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/examples.spec.ts29
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/gpu_test.ts253
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/idl/constants/flags.spec.ts55
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/idl/idl_test.ts27
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/listing.ts2
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/shader/execution/robust_access.spec.ts368
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/util/conversion.ts71
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/util/math.ts7
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/layout.ts157
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/subresource.ts55
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/texelData.ts341
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/canvas/context_creation.spec.ts12
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/copyImageBitmapToTexture.spec.ts270
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_clear.html10
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_clear.ts27
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_complex.ts76
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_complex_bgra8unorm.html18
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/gpu_ref_test.ts23
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/ref/canvas_clear-ref.html12
-rw-r--r--chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/ref/canvas_complex-ref.html17
-rw-r--r--chromium/third_party/webgpu-cts/src/standalone/index.html74
-rwxr-xr-xchromium/third_party/webgpu-cts/src/tools/gen_version2
-rw-r--r--chromium/third_party/webgpu-cts/src/tsconfig.json9
-rw-r--r--chromium/third_party/webgpu-cts/src/tslint.json38
-rw-r--r--chromium/third_party/webgpu-cts/src/yarn.lock3557
144 files changed, 14753 insertions, 8005 deletions
diff --git a/chromium/third_party/webgpu-cts/src/.eslint-resolver.js b/chromium/third_party/webgpu-cts/src/.eslint-resolver.js
new file mode 100644
index 00000000000..e2b0f32d354
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/.eslint-resolver.js
@@ -0,0 +1,23 @@
+const path = require('path');
+const resolve = require('resolve')
+
+// Implements the following resolver spec:
+// https://github.com/benmosher/eslint-plugin-import/blob/master/resolvers/README.md
+exports.interfaceVersion = 2
+
+exports.resolve = function (source, file, config) {
+ if (resolve.isCore(source)) return { found: true, path: null }
+
+ source = source.replace(/\.js$/, '.ts');
+ try {
+ return {
+ found: true, path: resolve.sync(source, {
+ extensions: [],
+ basedir: path.dirname(path.resolve(file)),
+ ...config,
+ })
+ }
+ } catch (err) {
+ return { found: false }
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/.eslintrc.json b/chromium/third_party/webgpu-cts/src/.eslintrc.json
new file mode 100644
index 00000000000..f4f1d2c1f52
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/.eslintrc.json
@@ -0,0 +1,73 @@
+{
+ "extends": [
+ "./node_modules/gts",
+ "plugin:import/errors",
+ "plugin:import/warnings",
+ "plugin:import/typescript"
+ ],
+ "env": {
+ "browser": true,
+ "node": true
+ },
+ "plugins": ["node", "ban", "import"],
+ "rules": {
+ "ban/ban": [
+ "warn",
+ {
+ "name": "setTimeout",
+ "message": "WPT disallows setTimeout; use `framework/util/timeout.js`."
+ }
+ ],
+ "linebreak-style": ["warn", "unix"],
+ "object-shorthand": "warn",
+ "no-console": "warn",
+ "no-undef": "off",
+ "no-useless-rename": "warn",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "import/order": [
+ "warn",
+ {
+ "groups": ["builtin", "external", "internal", "parent", "sibling", "index"],
+ "newlines-between": "always",
+ "alphabetize": { "order": "asc", "caseInsensitive": false }
+ }
+ ],
+ "import/newline-after-import": ["warn", { "count": 1 }],
+ "import/no-duplicates": "warn",
+ "import/no-restricted-paths": [
+ "error",
+ {
+ "zones": [
+ {
+ "target": "./src/webgpu",
+ "from": "./src/common",
+ "except": ["./framework", "./tools/crawl.ts", "./constants.ts"],
+ "message": "Non-framework common/ code imported from webgpu/ suite"
+ },
+ {
+ "target": "./src/unittests",
+ "from": "./src/common",
+ "except": ["./framework", "./tools/crawl.ts", "./constants.ts"],
+ "message": "Non-framework common/ code imported from unittests/ suite"
+ },
+ {
+ "target": "./src/webgpu",
+ "from": "./src/unittests",
+ "message": "unittests/ suite imported from webgpu/ suite"
+ },
+ {
+ "target": "./src/common",
+ "from": "./src",
+ "except": ["./common"],
+ "message": "Non common/ code imported from common/"
+ }
+ ]
+ }
+ ]
+ },
+ "settings": {
+ "import/resolver": {
+ "./.eslint-resolver": {}
+ }
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/.travis.yml b/chromium/third_party/webgpu-cts/src/.travis.yml
index 7bd2152fa45..86f8bd32494 100644
--- a/chromium/third_party/webgpu-cts/src/.travis.yml
+++ b/chromium/third_party/webgpu-cts/src/.travis.yml
@@ -2,8 +2,6 @@ language: node_js
node_js:
- 'node'
-before_install: yarn global add grunt-cli
-
deploy:
provider: pages
skip_cleanup: true
diff --git a/chromium/third_party/webgpu-cts/src/.vscode/tasks.json b/chromium/third_party/webgpu-cts/src/.vscode/tasks.json
index 8b8758ae40c..85d45561f8b 100644
--- a/chromium/third_party/webgpu-cts/src/.vscode/tasks.json
+++ b/chromium/third_party/webgpu-cts/src/.vscode/tasks.json
@@ -14,6 +14,13 @@
"type": "grunt",
"task": "pre",
"problemMatcher": []
+ },
+ {
+ "type": "grunt",
+ "task": "check",
+ "problemMatcher": [
+ "$tsc"
+ ]
}
]
}
diff --git a/chromium/third_party/webgpu-cts/src/CONTRIBUTING.md b/chromium/third_party/webgpu-cts/src/CONTRIBUTING.md
index faf7df58b06..ce0ea903ad6 100644
--- a/chromium/third_party/webgpu-cts/src/CONTRIBUTING.md
+++ b/chromium/third_party/webgpu-cts/src/CONTRIBUTING.md
@@ -6,7 +6,7 @@ License Agreement (CLA)](http://www.w3.org/community/about/agreements/cla/). To
make substantive contributions, you must join the CG.
Contributions to the source code repository are subject to the terms of the
-[3-Clause BSD License](https://github.com/gpuweb/admin/blob/SourceCodeLicense/LICENSE.txt).
+[3-Clause BSD License](./LICENSE.txt).
If you are not the sole contributor to a contribution (pull request), please identify all
contributors in the pull request comment.
diff --git a/chromium/third_party/webgpu-cts/src/Gruntfile.js b/chromium/third_party/webgpu-cts/src/Gruntfile.js
index b0515d09c7a..4cf5c1b86c9 100644
--- a/chromium/third_party/webgpu-cts/src/Gruntfile.js
+++ b/chromium/third_party/webgpu-cts/src/Gruntfile.js
@@ -8,14 +8,6 @@ module.exports = function (grunt) {
out: ['out/', 'out-wpt'],
},
- mkdir: {
- out: {
- options: {
- create: ['out'],
- },
- },
- },
-
run: {
'generate-version': {
cmd: 'node',
@@ -23,7 +15,7 @@ module.exports = function (grunt) {
},
'generate-listings': {
cmd: 'node',
- args: ['tools/gen_listings', 'webgpu', 'unittests'],
+ args: ['tools/gen_listings', 'webgpu', 'unittests', 'demo'],
},
'generate-wpt-cts-html': {
cmd: 'node',
@@ -31,7 +23,7 @@ module.exports = function (grunt) {
},
test: {
cmd: 'node',
- args: ['tools/run', 'unittests:'],
+ args: ['tools/run', 'unittests:*'],
},
'build-out': {
cmd: 'node',
@@ -43,16 +35,26 @@ module.exports = function (grunt) {
'src/',
],
},
- 'gts-check': {
+ lint: {
cmd: 'node',
- args: ['node_modules/gts/build/src/cli', 'check'],
+ args: ['node_modules/eslint/bin/eslint', 'src/**/*.ts', '--max-warnings=0'],
},
- 'gts-fix': {
+ fix: {
cmd: 'node',
- args: ['node_modules/gts/build/src/cli', 'fix'],
+ args: ['node_modules/eslint/bin/eslint', 'src/**/*.ts', '--fix'],
},
},
+ watch: {
+ src: {
+ files: ['src/**/*'],
+ tasks: ['run:build-out', 'run:lint'],
+ options: {
+ spawn: false,
+ }
+ }
+ },
+
copy: {
'webgpu-constants': {
files: [
@@ -79,9 +81,10 @@ module.exports = function (grunt) {
{ expand: true, cwd: '.', src: 'LICENSE.txt', dest: 'out-wpt/' },
{ expand: true, cwd: 'out', src: 'common/constants.js', dest: 'out-wpt/' },
{ expand: true, cwd: 'out', src: 'common/framework/**/*.js', dest: 'out-wpt/' },
- { expand: true, cwd: 'out', src: 'webgpu/**/*.js', dest: 'out-wpt/' },
{ expand: true, cwd: 'out', src: 'common/runtime/wpt.js', dest: 'out-wpt/' },
{ expand: true, cwd: 'out', src: 'common/runtime/helper/**/*.js', dest: 'out-wpt/' },
+ { expand: true, cwd: 'out', src: 'webgpu/**/*.js', dest: 'out-wpt/' },
+ { expand: true, cwd: 'src', src: 'webgpu/**/*.html', dest: 'out-wpt/' },
],
},
},
@@ -93,6 +96,19 @@ module.exports = function (grunt) {
host: '127.0.0.1',
cache: -1,
},
+ 'background': {
+ root: '.',
+ port: 8080,
+ host: '127.0.0.1',
+ cache: -1,
+ runInBackground: true,
+ logFn: function (req, res, error) {
+ // Only log errors to not spam the console.
+ if (error) {
+ console.error(error);
+ }
+ },
+ },
},
ts: {
@@ -108,9 +124,19 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-http-server');
- grunt.loadNpmTasks('grunt-mkdir');
grunt.loadNpmTasks('grunt-run');
grunt.loadNpmTasks('grunt-ts');
+ grunt.loadNpmTasks('grunt-contrib-watch');
+
+ grunt.event.on('watch', function (action, filepath) {
+ const buildArgs = grunt.config(['run', 'build-out', 'args']);
+ buildArgs[buildArgs.length - 1] = filepath;
+ grunt.config(['run', 'build-out', 'args'], buildArgs);
+
+ const lintArgs = grunt.config(['run', 'lint', 'args']);
+ lintArgs[lintArgs.length - 1] = filepath;
+ grunt.config(['run', 'lint', 'args'], lintArgs);
+ });
const helpMessageTasks = [];
function registerTaskAndAddToHelp(name, desc, deps) {
@@ -128,7 +154,6 @@ module.exports = function (grunt) {
grunt.registerTask('prebuild', 'Pre-build tasks (clean and re-copy)', [
'clean',
- 'mkdir:out',
'copy:webgpu-constants',
'copy:glslang',
]);
@@ -148,7 +173,7 @@ module.exports = function (grunt) {
registerTaskAndAddToHelp('pre', 'Run all presubmit checks: build+typecheck+test+lint', [
'set-quiet-mode',
'wpt',
- 'run:gts-check',
+ 'run:lint',
]);
registerTaskAndAddToHelp('test', 'Quick development build: build+typecheck+test', [
'set-quiet-mode',
@@ -171,11 +196,15 @@ module.exports = function (grunt) {
'set-quiet-mode',
'copy:webgpu-constants',
'ts:check',
- 'run:gts-check',
+ 'run:lint',
+ ]);
+ registerTaskAndAddToHelp('dev', 'Start the dev server, and watch for changes', [
+ 'http-server:background',
+ 'watch',
]);
registerTaskAndAddToHelp('serve', 'Serve out/ on 127.0.0.1:8080', ['http-server:.']);
- registerTaskAndAddToHelp('fix', 'Fix lint and formatting', ['run:gts-fix']);
+ registerTaskAndAddToHelp('fix', 'Fix lint and formatting', ['run:fix']);
grunt.registerTask('default', '', () => {
console.error('\nAvailable tasks (see grunt --help for info):');
diff --git a/chromium/third_party/webgpu-cts/src/README.md b/chromium/third_party/webgpu-cts/src/README.md
index e242cbc8e00..75394d297ed 100644
--- a/chromium/third_party/webgpu-cts/src/README.md
+++ b/chromium/third_party/webgpu-cts/src/README.md
@@ -19,12 +19,11 @@ The WebGPU CTS is written in TypeScript, and builds into two directories:
### Setup
-After checking out the repository and installing Yarn, run these commands to
-set up dependencies:
+After checking out the repository and installing node/npm, run these commands
+in the checkout:
```sh
-cd webgpu/
-yarn install
+npm install
npx grunt # show available grunt commands
```
diff --git a/chromium/third_party/webgpu-cts/src/babel.config.js b/chromium/third_party/webgpu-cts/src/babel.config.js
index 947be09cd4a..0ba071db6da 100644
--- a/chromium/third_party/webgpu-cts/src/babel.config.js
+++ b/chromium/third_party/webgpu-cts/src/babel.config.js
@@ -15,6 +15,6 @@ module.exports = function (api) {
],
],
compact: false,
- shouldPrintComment: val => !/tslint:/.test(val),
+ shouldPrintComment: val => !/eslint/.test(val),
};
};
diff --git a/chromium/third_party/webgpu-cts/src/docs/terms.md b/chromium/third_party/webgpu-cts/src/docs/terms.md
index d718c648fba..be9d83a15ee 100644
--- a/chromium/third_party/webgpu-cts/src/docs/terms.md
+++ b/chromium/third_party/webgpu-cts/src/docs/terms.md
@@ -1,11 +1,36 @@
# Writing Tests
-- _Suites_ contain multiple:
- - _READMEs_
- - _Test Spec Files_. Contains one:
- - _Test Group_. Defines a _test fixture_ and contains multiple:
- - _Tests_. Defines a _test function_ and contains multiple:
- - _Test Cases_, each with the same test function but different _parameters_.
+Each test suite is organized as a tree, both in the filesystem and further within each file.
+
+- _Suites_, e.g. `src/webgpu/`.
+ - _READMEs_, e.g. `src/webgpu/README.txt`.
+ - _Test Spec Files_, e.g. `src/webgpu/examples.spec.ts`.
+ Identified by their file path.
+ Each test spec file provides a description and a _Test Group_.
+ A _Test Group_ defines a test fixture, and contains multiple:
+ - _Tests_.
+ Identified by a comma-separated list of parts (e.g. `basic,async`)
+ which define a path through a filesystem-like tree (analogy: `basic/async.txt`).
+ Defines a _test function_ and contains multiple:
+ - _Test Cases_.
+ Identified by a list of _Public Parameters_ (e.g. `x` = `1`, `y` = `2`).
+ Each Test Case has the same test function but different Public Parameters.
+
+## Test Tree
+
+A _Test Tree_ is a tree whose leaves are individual Test Cases.
+
+A Test Tree can be thought of as follows:
+
+- Suite, which is the root of a tree with "leaves" which are:
+ - Test Spec Files, each of which is a tree with "leaves" which are:
+ - Tests, each of which is a tree with leaves which are:
+ - Test Cases.
+
+(In the implementation, this conceptual tree of trees is decomposed into one big tree
+whose leaves are Test Cases.)
+
+**Type:** `TestTree`
## Suite
@@ -22,30 +47,53 @@ Each member of a suite is identified by its path within the suite.
Describes (in prose) the contents of a subdirectory in a suite.
-**Type:** After a README is loaded, it is stored as a `ReadmeFile`.
+READMEs are only processed at build time, when generating the _Listing_ for a suite.
-## IDs
+**Type:** `TestSuiteListingEntryReadme`
-### Test Spec ID
+## Queries
-Uniquely identifies a single test spec file.
-Comprised of suite name (`suite`) and test spec file path relative to the suite root (`path`).
+A _Query_ is a structured object which specifies a subset of cases in exactly one Suite.
+A Query can be represented uniquely as a string.
+Queries are used to:
-**Type:** `TestSpecID`
+- Identify a subtree of a suite (by identifying the root node of that subtree).
+- Identify individual cases.
+- Represent the list of tests that a test runner (standalone, wpt, or cmdline) should run.
+- Identify subtrees which should not be "collapsed" during WPT `cts.html` generation,
+ so that that cts.html "variants" can have individual test expectations
+ (i.e. marked as "expected to fail", "skip", etc.).
-**Example:** `{ suite: 'webgpu', path: 'command_buffer/compute/basic' }` corresponds to
-`src/webgpu/command_buffer/compute/basic.spec.ts`.
+There are four types of `TestQuery`:
-### Test Case ID
+- `TestQueryMultiFile` represents any subtree of the file hierarchy:
+ - `suite:*`
+ - `suite:path,to,*`
+ - `suite:path,to,file,*`
+- `TestQueryMultiTest` represents any subtree of the test hierarchy:
+ - `suite:path,to,file:*`
+ - `suite:path,to,file:path,to,*`
+ - `suite:path,to,file:path,to,test,*`
+- `TestQueryMultiCase` represents any subtree of the case hierarchy:
+ - `suite:path,to,file:path,to,test:*`
+ - `suite:path,to,file:path,to,test:my=0;*`
+ - `suite:path,to,file:path,to,test:my=0;params="here";*`
+- `TestQuerySingleCase` represents as single case:
+ - `suite:path,to,file:path,to,test:my=0;params="here"`
-Uniquely identifies a single test case within a test spec.
+Test Queries are a **weakly ordered set**: any query is
+_Unordered_, _Equal_, _StrictSuperset_, or _StrictSubset_ relative to any other.
+This property is used to construct the complete tree of test cases.
+In the examples above, every example query is a StrictSubset of the previous one
+(note: even `:*` is a subset of `,*`).
-Comprised of test name (`test`) and the parameters for a case (`params`).
-(If `params` is null, there is only one case for the test.)
+In the WPT and standalone harnesses, the query is stored in the URL, e.g.
+`index.html?q=q:u,e:r,y:*`.
-**Type:** `TestCaseID`
+Queries are selectively URL-encoded for readability and compatibility with browsers
+(see `encodeURIComponentSelectively`).
-**Example:** `{ test: '', params: { 'value': 1 } }`
+**Type:** `TestQuery`
## Listing
@@ -53,39 +101,35 @@ A listing of the **test spec files** in a suite.
This can be generated only in Node, which has filesystem access (see `src/tools/crawl.ts`).
As part of the build step, a _listing file_ is generated (see `src/tools/gen.ts`) so that the
-test files can be discovered by the web runner (since it does not have filesystem access).
+Test Spec Files can be discovered by the web runner (since it does not have filesystem access).
**Type:** `TestSuiteListing`
### Listing File
-**Example:** `out/webgpu/listing.js`
+Each Suite has one Listing File (`suite/listing.[tj]s`), containing a list of the files
+in the suite.
-## Test Spec
+In `src/suite/listing.ts`, this is computed dynamically.
+In `out/suite/listing.js`, the listing has been pre-baked (by `tools/gen_listings`).
-May be either a _test spec file_ or a _filtered test spec_.
-It is identified by a `TestSpecID`.
+**Type:** Once `import`ed, `ListingFile`
-Always contains one `RunCaseIterable`.
+**Example:** `out/webgpu/listing.js`
-**Type:** `TestSpec`
+## Test Spec File
-### Test Spec File
+A Test Spec File has a `description` and a Test Group (under which tests and cases are defined).
-A single `.spec.ts` file. It always contains one _test group_.
+**Type:** Once `import`ed, `SpecFile`
**Example:** `src/webgpu/**/*.spec.ts`
-### Filtered Test Spec
-
-A subset of the tests in a single test spec file.
-It is created at runtime, via a filter.
-
-It contains one "virtual" test group, which has type `RunCaseIterable`.
+## Test Group
-## Test Group / Group
+A subtree of tests. There is one Test Group per Test Spec File.
-A collection of test cases. There is one per test spec file.
+The Test Fixture used for tests is defined at TestGroup creation.
**Type:** `TestGroup`
@@ -93,18 +137,17 @@ A collection of test cases. There is one per test spec file.
One test. It has a single _test function_.
-It may represent multiple _test cases_, each of which runs the same test function with different **parameters**.
+It may represent multiple _test cases_, each of which runs the same Test Function with different
+Parameters.
-It is created by `TestGroup.test()`.
-At creation time, it can be parameterized via `Test.params()`.
-
-**Type:** `Test`
+A test is named using `TestGroup.test()`, which returns a `TestBuilder`.
+`TestBuilder.params()` can optionally be used to parameterize the test.
+Then, `TestBuilder.fn()` provides the Test Function.
### Test Function
-A test function is defined inline inside of a `TestGroup.test()` call.
-
-It receives an instance of the appropriate _test fixture_, through which it produce test results.
+When a test case is run, the Test Function receives an instance of the
+Test Fixture provided to the Test Group, producing test results.
**Type:** `TestFn`
@@ -116,9 +159,20 @@ A single case of a test. It is identified by a `TestCaseID`: a test name, and it
## Parameters / Params
+Each Test Case has a (possibly empty) set of Parameters.
+The parameters are available to the Test Function `f(t)` via `t.params`.
+
+A set of Public Parameters identifies a Test Case within a Test.
+
+There are also Private Paremeters: any parameter name beginning with an underscore (`_`).
+These parameters are not part of the Test Case identification, but are still passed into
+the Test Function. They can be used to manually specify expected results.
+
+**Type:** `CaseParams`
+
## Test Fixture / Fixture
-Test fixtures provide helpers for tests to use.
+_Test Fixtures_ provide helpers for tests to use.
A new instance of the fixture is created for every run of every test case.
There is always one fixture class for a whole test group (though this may change).
@@ -126,7 +180,7 @@ There is always one fixture class for a whole test group (though this may change
The fixture is also how a test gets access to the _case recorder_,
which allows it to produce test results.
-They are also how tests produce results: `.log()`, `.fail()`, etc.
+They are also how tests produce results: `.skip()`, `.fail()`, etc.
**Type:** `Fixture`
@@ -138,137 +192,61 @@ Provides basic fixture utilities most useful in the `unittests` suite.
Provides utilities useful in WebGPU CTS tests.
-# Running Tests
-
-- _Queries_ contain multiple:
- - _Filters_ (positive or negative).
-
-## Query
-
-A query is a string which denotes a subset of a test suite to run.
-It is comprised of a list of filters.
-A case is included in the subset if it matches any of the filters.
-
-In the WPT and standalone harnesses, the query is stored in the URL.
-
-Queries are selectively URL-encoded for readability and compatibility with browsers.
-
-**Example:** `?q=unittests:param_helpers:combine/=`
-**Example:** `?q=unittests:param_helpers:combine/mixed=`
-
-**Type:** None yet. TODO
-
-### Filter
-
-A filter matches a set of cases in a suite.
-
-Each filter may match one of:
-
-- `S:s` In one suite `S`, all specs whose paths start with `s` (which may be empty).
-- `S:s:t` In one spec `S:s`, all tests whose names start with `t` (which may be empty).
-- `S:s:t~c` In one test `S:s:t`, all cases whose params are a superset of `c`.
-- `S:s:t=c` In one test `S:s:t`, the single case whose params equal `c` (empty string = `{}`).
-
-**Type:** `TestFilter`
-
-### Using filters to split expectations
-
-A set of cases can be split using negative filters. For example, imagine you have one WPT test variant:
-
-- `webgpu/cts.html?q=unittests:param_helpers:`
-
-But one of the cases is failing. To be able to suppress the failing test without losing test coverage, the WPT test variant can be split into two variants:
-
-- `webgpu/cts.html?q=unittests:param_helpers:&not=unittests:param_helpers:combine/mixed:`
-- `webgpu/cts.html?q=unittests:param_helpers:combine/mixed:`
-
-This runs the same set of cases, but in two separate page loads.
-
# Test Results
## Logger
A logger logs the results of a whole test run.
-It saves an empty `LiveTestSpecResult` into its results array, then creates a
+It saves an empty `LiveTestSpecResult` into its results map, then creates a
_test spec recorder_, which records the results for a group into the `LiveTestSpecResult`.
-### Test Spec Recorder
-
-Refers to a `LiveTestSpecResult` in the logger, and writes results into it.
-
-It saves an empty `LiveTestCaseResult` into its `LiveTestSpecResult`, then creates a
-_test case recorder_, which records the results for a case into the `LiveTestCaseResult`.
+**Type:** `Logger`
### Test Case Recorder
-Records the actual results of running a test case (its pass-status, run time, and logs)
-into its `LiveTestCaseResult`.
+Refers to a `LiveTestCaseResult` created by the logger.
+Records the results of running a test case (its pass-status, run time, and logs) into it.
+
+**Types:** `TestCaseRecorder`, `LiveTestCaseResult`
#### Test Case Status
The `status` of a `LiveTestCaseResult` can be one of:
-- `'running'`
-- `'fail'`
-- `'warn'`
+- `'running'` (only while still running)
- `'pass'`
+- `'skip'`
+- `'warn'`
+- `'fail'`
+
+The "worst" result from running a case is always reported (fail > warn > skip > pass).
+Note this means a test can still fail if it's "skipped", if it failed before
+`.skip()` was called.
-The "worst" result from running a case is always reported.
+**Type:** `Status`
## Results Format
The results are returned in JSON format.
-They are designed to be easily merged in JavaScript.
-(TODO: Write a merge tool.)
+They are designed to be easily merged in JavaScript:
+the `"results"` can be passed into the constructor of `Map` and merged from there.
-(TODO: Update these docs if the format changes.)
+(TODO: Write a merge tool, if needed.)
```js
{
- "version": "e24c459b46c4815f93f0aed5261e28008d1f2882-dirty",
+ "version": "bf472c5698138cdf801006cd400f587e9b1910a5-dirty",
"results": [
- // LiveTestSpecResult objects
- {
- "spec": "unittests:basic:",
- "cases": [
- // LiveTestCaseResult objects
- {
- "test": "test/sync",
- "params": null,
- "status": "pass",
- "timems": 145,
- "logs": []
- },
- {
- "test": "test/async",
- "params": null,
- "status": "pass",
- "timems": 26,
- "logs": []
- }
- ]
- },
- {
- "spec": "unittests:test_group:",
- "cases": [
- {
- "test": "invalid test name",
- "params": { "char": "\"" },
- "status": "pass",
- "timems": 66,
- "logs": ["OK: threw"]
- },
- {
- "test": "invalid test name",
- "params": { "char": "`" },
- "status": "pass",
- "timems": 15,
- "logs": ["OK: threw"]
- }
- ]
- }
+ [
+ "unittests:async_mutex:basic:",
+ { "status": "pass", "timems": 0.286, "logs": [] }
+ ],
+ [
+ "unittests:async_mutex:serial:",
+ { "status": "pass", "timems": 0.415, "logs": [] }
+ ]
]
}
```
diff --git a/chromium/third_party/webgpu-cts/src/package-lock.json b/chromium/third_party/webgpu-cts/src/package-lock.json
new file mode 100644
index 00000000000..2becb20ea92
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/package-lock.json
@@ -0,0 +1,6674 @@
+{
+ "name": "@webgpu/cts",
+ "version": "0.1.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/cli": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.10.1.tgz",
+ "integrity": "sha512-cVB+dXeGhMOqViIaZs3A9OUAe4pKw4SBNdMw6yHJMYR7s4TB+Cei7ThquV/84O19PdIFWuwe03vxxES0BHUm5g==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^2.1.8",
+ "commander": "^4.0.1",
+ "convert-source-map": "^1.1.0",
+ "fs-readdir-recursive": "^1.1.0",
+ "glob": "^7.0.0",
+ "lodash": "^4.17.13",
+ "make-dir": "^2.1.0",
+ "slash": "^2.0.0",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
+ "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.1"
+ }
+ },
+ "@babel/core": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz",
+ "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.1",
+ "@babel/generator": "^7.10.2",
+ "@babel/helper-module-transforms": "^7.10.1",
+ "@babel/helpers": "^7.10.1",
+ "@babel/parser": "^7.10.2",
+ "@babel/template": "^7.10.1",
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.2",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.1",
+ "json5": "^2.1.2",
+ "lodash": "^4.17.13",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz",
+ "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.2",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-create-class-features-plugin": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.2.tgz",
+ "integrity": "sha512-5C/QhkGFh1vqcziq1vAL6SI9ymzUp8BCYjFpvYVhWP4DlATIb3u5q3iUd35mvlyGs8fO7hckkW7i0tmH+5+bvQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.10.1",
+ "@babel/helper-member-expression-to-functions": "^7.10.1",
+ "@babel/helper-optimise-call-expression": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-replace-supers": "^7.10.1",
+ "@babel/helper-split-export-declaration": "^7.10.1"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz",
+ "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.1",
+ "@babel/template": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz",
+ "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz",
+ "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz",
+ "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz",
+ "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.1",
+ "@babel/helper-replace-supers": "^7.10.1",
+ "@babel/helper-simple-access": "^7.10.1",
+ "@babel/helper-split-export-declaration": "^7.10.1",
+ "@babel/template": "^7.10.1",
+ "@babel/types": "^7.10.1",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz",
+ "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.1.tgz",
+ "integrity": "sha512-fvoGeXt0bJc7VMWZGCAEBEMo/HAjW2mP8apF5eXK0wSqwLAVHAISCWRoLMBMUs2kqeaG77jltVqu4Hn8Egl3nA==",
+ "dev": true
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz",
+ "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.1",
+ "@babel/helper-optimise-call-expression": "^7.10.1",
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz",
+ "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz",
+ "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz",
+ "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==",
+ "dev": true
+ },
+ "@babel/helpers": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz",
+ "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.1",
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz",
+ "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.1",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz",
+ "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==",
+ "dev": true
+ },
+ "@babel/plugin-proposal-class-properties": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.1.tgz",
+ "integrity": "sha512-sqdGWgoXlnOdgMXU+9MbhzwFRgxVLeiGBqTrnuS7LC2IBU31wSsESbTUreT2O418obpfPdGUR2GbEufZF1bpqw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-import-meta": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.1.tgz",
+ "integrity": "sha512-ypC4jwfIVF72og0dgvEcFRdOM2V9Qm1tu7RGmdZOlhsccyK0wisXmMObGuWEOd5jQ+K9wcIgSNftCpk2vkjUfQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-syntax-typescript": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.1.tgz",
+ "integrity": "sha512-X/d8glkrAtra7CaQGMiGs/OGa6XgUzqPcBXCIGFCpCqnfGlT0Wfbzo/B89xHhnInTaItPK8LALblVXcUOEh95Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1"
+ }
+ },
+ "@babel/plugin-transform-typescript": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.10.1.tgz",
+ "integrity": "sha512-v+QWKlmCnsaimLeqq9vyCsVRMViZG1k2SZTlcZvB+TqyH570Zsij8nvVUZzOASCRiQFUxkLrn9Wg/kH0zgy5OQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-syntax-typescript": "^7.10.1"
+ }
+ },
+ "@babel/preset-typescript": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.10.1.tgz",
+ "integrity": "sha512-m6GV3y1ShiqxnyQj10600ZVOFrSSAa8HQ3qIUk2r+gcGtHTIRw0dJnFLt1WNXpKjtVw7yw1DAPU/6ma2ZvgJuA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/plugin-transform-typescript": "^7.10.1"
+ }
+ },
+ "@babel/template": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz",
+ "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.1",
+ "@babel/parser": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz",
+ "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.1",
+ "@babel/generator": "^7.10.1",
+ "@babel/helper-function-name": "^7.10.1",
+ "@babel/helper-split-export-declaration": "^7.10.1",
+ "@babel/parser": "^7.10.1",
+ "@babel/types": "^7.10.1",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/types": {
+ "version": "7.10.2",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz",
+ "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.1",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
+ "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.3",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
+ "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz",
+ "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.3",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@sindresorhus/is": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
+ "dev": true
+ },
+ "@szmarczak/http-timer": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
+ "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
+ "dev": true,
+ "requires": {
+ "defer-to-connect": "^1.0.1"
+ }
+ },
+ "@types/color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+ "dev": true
+ },
+ "@types/eslint-visitor-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+ "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
+ "dev": true
+ },
+ "@types/jquery": {
+ "version": "3.3.38",
+ "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.38.tgz",
+ "integrity": "sha512-nkDvmx7x/6kDM5guu/YpXkGZ/Xj/IwGiLDdKM99YA5Vag7pjGyTJ8BNUh/6hxEn/sEu5DKtyRgnONJ7EmOoKrA==",
+ "dev": true,
+ "requires": {
+ "@types/sizzle": "*"
+ }
+ },
+ "@types/json-schema": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz",
+ "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==",
+ "dev": true
+ },
+ "@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
+ "dev": true
+ },
+ "@types/minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "14.0.12",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.12.tgz",
+ "integrity": "sha512-/sjzehvjkkpvLpYtN6/2dv5kg41otMGuHQUt9T2aiAuIfleCQRQHXXzF1eAw/qkZTj5Kcf4JSTf7EIizHocy6Q==",
+ "dev": true
+ },
+ "@types/normalize-package-data": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
+ "dev": true
+ },
+ "@types/offscreencanvas": {
+ "version": "2019.6.2",
+ "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.6.2.tgz",
+ "integrity": "sha512-ndVeLKDF10p4hZswi0KKSUWAmNoTcgz8LUPiIIPeT3qD8bTaYe0pXyuyQ21+DmGRMkT8orxiISm4O+YpMLCDBw==",
+ "dev": true,
+ "requires": {
+ "@types/webgl2": "*"
+ }
+ },
+ "@types/sizzle": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
+ "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
+ "dev": true
+ },
+ "@types/webgl2": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.5.tgz",
+ "integrity": "sha512-oGaKsBbxQOY5+aJFV3KECDhGaXt+yZJt2y/OZsnQGLRkH6Fvr7rv4pCt3SRH1somIHfej/c4u7NSpCyd9x+1Ow==",
+ "dev": true
+ },
+ "@typescript-eslint/eslint-plugin": {
+ "version": "2.31.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.31.0.tgz",
+ "integrity": "sha512-iIC0Pb8qDaoit+m80Ln/aaeu9zKQdOLF4SHcGLarSeY1gurW6aU4JsOPMjKQwXlw70MvWKZQc6S2NamA8SJ/gg==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/experimental-utils": "2.31.0",
+ "functional-red-black-tree": "^1.0.1",
+ "regexpp": "^3.0.0",
+ "tsutils": "^3.17.1"
+ },
+ "dependencies": {
+ "regexpp": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
+ "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+ "dev": true
+ }
+ }
+ },
+ "@typescript-eslint/experimental-utils": {
+ "version": "2.31.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.31.0.tgz",
+ "integrity": "sha512-MI6IWkutLYQYTQgZ48IVnRXmLR/0Q6oAyJgiOror74arUMh7EWjJkADfirZhRsUMHeLJ85U2iySDwHTSnNi9vA==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.3",
+ "@typescript-eslint/typescript-estree": "2.31.0",
+ "eslint-scope": "^5.0.0",
+ "eslint-utils": "^2.0.0"
+ },
+ "dependencies": {
+ "eslint-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
+ "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ }
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "2.31.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.31.0.tgz",
+ "integrity": "sha512-uph+w6xUOlyV2DLSC6o+fBDzZ5i7+3/TxAsH4h3eC64tlga57oMb96vVlXoMwjR/nN+xyWlsnxtbDkB46M2EPQ==",
+ "dev": true,
+ "requires": {
+ "@types/eslint-visitor-keys": "^1.0.0",
+ "@typescript-eslint/experimental-utils": "2.31.0",
+ "@typescript-eslint/typescript-estree": "2.31.0",
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "2.31.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.31.0.tgz",
+ "integrity": "sha512-vxW149bXFXXuBrAak0eKHOzbcu9cvi6iNcJDzEtOkRwGHxJG15chiAQAwhLOsk+86p9GTr/TziYvw+H9kMaIgA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "eslint-visitor-keys": "^1.1.0",
+ "glob": "^7.1.6",
+ "is-glob": "^4.0.1",
+ "lodash": "^4.17.15",
+ "semver": "^6.3.0",
+ "tsutils": "^3.17.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@webgpu/glslang": {
+ "version": "0.0.15",
+ "resolved": "https://registry.npmjs.org/@webgpu/glslang/-/glslang-0.0.15.tgz",
+ "integrity": "sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q==",
+ "dev": true
+ },
+ "@webgpu/types": {
+ "version": "0.0.24",
+ "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.0.24.tgz",
+ "integrity": "sha512-g3axpnE8h42vzcl9Zi8jBjht9ts4Y2E8AI0DTktwsRh4yiIg+OmVjn49Kp/5atsAmsbAGNtROgrOj/lyxkftsA==",
+ "dev": true
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "acorn": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz",
+ "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz",
+ "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==",
+ "dev": true
+ },
+ "ajv": {
+ "version": "6.12.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+ "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-align": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz",
+ "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.0.0"
+ },
+ "dependencies": {
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ }
+ }
+ },
+ "ansi-escapes": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz",
+ "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.11.0"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz",
+ "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==",
+ "dev": true
+ }
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+ "dev": true
+ },
+ "array-includes": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz",
+ "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0",
+ "is-string": "^1.0.5"
+ }
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
+ },
+ "array.prototype.flat": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz",
+ "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1"
+ }
+ },
+ "arrify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
+ "dev": true
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true
+ },
+ "astral-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+ "dev": true
+ },
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ },
+ "async-each": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
+ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
+ "dev": true
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "dev": true
+ },
+ "babel-plugin-add-header-comment": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-add-header-comment/-/babel-plugin-add-header-comment-1.0.3.tgz",
+ "integrity": "sha1-URxJAQYmQNWkgLSsPt1pRBlYUOw=",
+ "dev": true
+ },
+ "babel-plugin-const-enum": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-const-enum/-/babel-plugin-const-enum-1.0.1.tgz",
+ "integrity": "sha512-6oGu63g1FS9psUPQyLCJM08ty6kGihGKTbzWGbAKHfUuCzCh7y9twh516cR6v0lM4d4NOoR+DgLb7uKVytyp6Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-typescript": "^7.3.3"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
+ "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+ "dev": true
+ },
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "body": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz",
+ "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=",
+ "dev": true,
+ "requires": {
+ "continuable-cache": "^0.3.1",
+ "error": "^7.0.0",
+ "raw-body": "~1.1.0",
+ "safe-json-parse": "~1.0.1"
+ }
+ },
+ "boxen": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz",
+ "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==",
+ "dev": true,
+ "requires": {
+ "ansi-align": "^3.0.0",
+ "camelcase": "^5.3.1",
+ "chalk": "^3.0.0",
+ "cli-boxes": "^2.2.0",
+ "string-width": "^4.1.0",
+ "term-size": "^2.1.0",
+ "type-fest": "^0.8.1",
+ "widest-line": "^3.1.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+ "dev": true
+ },
+ "bytes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz",
+ "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=",
+ "dev": true
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "cacheable-request": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
+ "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
+ "dev": true,
+ "requires": {
+ "clone-response": "^1.0.2",
+ "get-stream": "^5.1.0",
+ "http-cache-semantics": "^4.0.0",
+ "keyv": "^3.0.0",
+ "lowercase-keys": "^2.0.0",
+ "normalize-url": "^4.1.0",
+ "responselike": "^1.0.2"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
+ "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "lowercase-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+ "dev": true
+ }
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "dev": true,
+ "requires": {
+ "camelcase": "^2.0.0",
+ "map-obj": "^1.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "cli-boxes": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz",
+ "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==",
+ "dev": true
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-width": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz",
+ "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "clone-response": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
+ "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+ "dev": true
+ },
+ "coffeescript": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz",
+ "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=",
+ "dev": true
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+ "dev": true
+ },
+ "commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "configstore": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
+ "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^5.2.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^3.0.0",
+ "unique-string": "^2.0.0",
+ "write-file-atomic": "^3.0.0",
+ "xdg-basedir": "^4.0.0"
+ },
+ "dependencies": {
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.0.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "contains-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
+ "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
+ "dev": true
+ },
+ "continuable-cache": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz",
+ "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
+ "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "corser": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
+ "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "dependencies": {
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "crypto-random-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
+ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
+ "dev": true
+ },
+ "csproj2ts": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/csproj2ts/-/csproj2ts-1.1.0.tgz",
+ "integrity": "sha512-sk0RTT51t4lUNQ7UfZrqjQx7q4g0m3iwNA6mvyh7gLsgQYvwKzfdyoAgicC9GqJvkoIkU0UmndV9c7VZ8pJ45Q==",
+ "dev": true,
+ "requires": {
+ "es6-promise": "^4.1.1",
+ "lodash": "^4.17.4",
+ "semver": "^5.4.1",
+ "xml2js": "^0.4.19"
+ },
+ "dependencies": {
+ "es6-promise": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+ "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
+ "dev": true
+ }
+ }
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "dev": true,
+ "requires": {
+ "array-find-index": "^1.0.1"
+ }
+ },
+ "dateformat": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
+ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1",
+ "meow": "^3.3.0"
+ }
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "decamelize-keys": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
+ "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=",
+ "dev": true,
+ "requires": {
+ "decamelize": "^1.1.0",
+ "map-obj": "^1.0.0"
+ }
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
+ "decompress-response": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+ "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
+ "dev": true,
+ "requires": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "defer-to-connect": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
+ "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==",
+ "dev": true
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "detect-indent": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+ "dev": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "detect-newline": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz",
+ "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=",
+ "dev": true
+ },
+ "diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "dev": true
+ },
+ "divhide": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/divhide/-/divhide-2.0.1.tgz",
+ "integrity": "sha1-jHsCb3/w6XWAPLuWWuyhFN6C2bs=",
+ "dev": true,
+ "requires": {
+ "lodash": "=3.9.3"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "3.9.3",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.9.3.tgz",
+ "integrity": "sha1-AVnoaDL+/8bWHYUrEqlTuZSWvTI=",
+ "dev": true
+ }
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "dot-prop": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
+ "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
+ "dev": true,
+ "requires": {
+ "is-obj": "^2.0.0"
+ }
+ },
+ "duplexer3": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
+ "dev": true
+ },
+ "ecstatic": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz",
+ "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==",
+ "dev": true,
+ "requires": {
+ "he": "^1.1.1",
+ "mime": "^1.6.0",
+ "minimist": "^1.1.0",
+ "url-join": "^2.0.5"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "error": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz",
+ "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==",
+ "dev": true,
+ "requires": {
+ "string-template": "~0.2.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.17.5",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
+ "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.1.5",
+ "is-regex": "^1.0.5",
+ "object-inspect": "^1.7.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.0",
+ "string.prototype.trimleft": "^2.1.1",
+ "string.prototype.trimright": "^2.1.1"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es6-promise": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-0.1.2.tgz",
+ "integrity": "sha1-8RLCn+paCZhTn8tqL9IUQ9KPBfc=",
+ "dev": true
+ },
+ "escape-goat": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
+ "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eslint": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.2.0.tgz",
+ "integrity": "sha512-B3BtEyaDKC5MlfDa2Ha8/D6DsS4fju95zs0hjS3HdGazw+LNayai38A25qMppK37wWGWNYSPOR6oYzlz5MHsRQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "eslint-scope": "^5.1.0",
+ "eslint-utils": "^2.0.0",
+ "eslint-visitor-keys": "^1.2.0",
+ "espree": "^7.1.0",
+ "esquery": "^1.2.0",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^5.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.0.0",
+ "globals": "^12.1.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "inquirer": "^7.0.0",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash": "^4.17.14",
+ "minimatch": "^3.0.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "progress": "^2.0.0",
+ "regexpp": "^3.1.0",
+ "semver": "^7.2.1",
+ "strip-ansi": "^6.0.0",
+ "strip-json-comments": "^3.1.0",
+ "table": "^5.2.3",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+ "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+ "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.8.1"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "semver": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "eslint-config-prettier": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz",
+ "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^6.0.0"
+ },
+ "dependencies": {
+ "get-stdin": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
+ "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-import-resolver-node": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz",
+ "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==",
+ "dev": true,
+ "requires": {
+ "debug": "^2.6.9",
+ "resolve": "^1.13.1"
+ }
+ },
+ "eslint-module-utils": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz",
+ "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==",
+ "dev": true,
+ "requires": {
+ "debug": "^2.6.9",
+ "pkg-dir": "^2.0.0"
+ }
+ },
+ "eslint-plugin-ban": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-ban/-/eslint-plugin-ban-1.5.1.tgz",
+ "integrity": "sha512-I15ptCK+Oy/6N0/Trd9+fXRW0DHivX2K3lQf6+XNK0mRRv5G/4PFuVs7YQa5VxIxui8HVgXnwoa1HGHJDQF/WQ==",
+ "dev": true,
+ "requires": {
+ "requireindex": "~1.2.0"
+ }
+ },
+ "eslint-plugin-es": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz",
+ "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==",
+ "dev": true,
+ "requires": {
+ "eslint-utils": "^2.0.0",
+ "regexpp": "^3.0.0"
+ },
+ "dependencies": {
+ "eslint-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
+ "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ },
+ "regexpp": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
+ "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-import": {
+ "version": "2.21.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.21.1.tgz",
+ "integrity": "sha512-qYOOsgUv63vHof7BqbzuD+Ud34bXHxFJxntuAC1ZappFZXYbRIek3aJ7jc9i2dHDGDyZ/0zlO0cpioES265Lsw==",
+ "dev": true,
+ "requires": {
+ "array-includes": "^3.1.1",
+ "array.prototype.flat": "^1.2.3",
+ "contains-path": "^0.1.0",
+ "debug": "^2.6.9",
+ "doctrine": "1.5.0",
+ "eslint-import-resolver-node": "^0.3.3",
+ "eslint-module-utils": "^2.6.0",
+ "has": "^1.0.3",
+ "minimatch": "^3.0.4",
+ "object.values": "^1.1.1",
+ "read-pkg-up": "^2.0.0",
+ "resolve": "^1.17.0",
+ "tsconfig-paths": "^3.9.0"
+ },
+ "dependencies": {
+ "doctrine": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+ "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2",
+ "isarray": "^1.0.0"
+ }
+ }
+ }
+ },
+ "eslint-plugin-node": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
+ "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==",
+ "dev": true,
+ "requires": {
+ "eslint-plugin-es": "^3.0.0",
+ "eslint-utils": "^2.0.0",
+ "ignore": "^5.1.1",
+ "minimatch": "^3.0.4",
+ "resolve": "^1.10.1",
+ "semver": "^6.1.0"
+ },
+ "dependencies": {
+ "eslint-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
+ "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ },
+ "ignore": {
+ "version": "5.1.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-prettier": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.3.tgz",
+ "integrity": "sha512-+HG5jmu/dN3ZV3T6eCD7a4BlAySdN7mLIbJYo0z1cFQuI+r2DiTJEFeF68ots93PsnrMxbzIZ2S/ieX+mkrBeQ==",
+ "dev": true,
+ "requires": {
+ "prettier-linter-helpers": "^1.0.0"
+ }
+ },
+ "eslint-scope": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
+ "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz",
+ "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz",
+ "integrity": "sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ==",
+ "dev": true
+ },
+ "espree": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz",
+ "integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.2.0",
+ "acorn-jsx": "^5.2.0",
+ "eslint-visitor-keys": "^1.2.0"
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz",
+ "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz",
+ "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==",
+ "dev": true
+ }
+ }
+ },
+ "esrecurse": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^4.1.0"
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "eventemitter2": {
+ "version": "0.4.14",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz",
+ "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
+ "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==",
+ "dev": true
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ }
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-diff": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz",
+ "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.0",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.2",
+ "picomatch": "^2.2.1"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+ "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
+ "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.0.5"
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ }
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz",
+ "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
+ "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^2.0.1"
+ }
+ },
+ "file-sync-cmp": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz",
+ "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=",
+ "dev": true
+ },
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "dev": true,
+ "optional": true
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "findup-sync": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz",
+ "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=",
+ "dev": true,
+ "requires": {
+ "glob": "~5.0.0"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "dev": true,
+ "requires": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "flat-cache": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+ "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+ "dev": true,
+ "requires": {
+ "flatted": "^2.0.0",
+ "rimraf": "2.6.3",
+ "write": "1.0.3"
+ }
+ },
+ "flatted": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
+ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
+ "dev": true
+ },
+ "follow-redirects": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.11.0.tgz",
+ "integrity": "sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fs-readdir-recursive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
+ "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
+ "gaze": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
+ "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
+ "dev": true,
+ "requires": {
+ "globule": "^1.0.0"
+ }
+ },
+ "gensync": {
+ "version": "1.0.0-beta.1",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
+ "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==",
+ "dev": true
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+ "dev": true
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true
+ },
+ "getobject": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz",
+ "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "global-dirs": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz",
+ "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==",
+ "dev": true,
+ "requires": {
+ "ini": "^1.3.5"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "globule": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
+ "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==",
+ "dev": true,
+ "requires": {
+ "glob": "~7.1.1",
+ "lodash": "~4.17.10",
+ "minimatch": "~3.0.2"
+ }
+ },
+ "got": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
+ "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
+ "dev": true,
+ "requires": {
+ "@sindresorhus/is": "^0.14.0",
+ "@szmarczak/http-timer": "^1.1.2",
+ "cacheable-request": "^6.0.0",
+ "decompress-response": "^3.3.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^4.1.0",
+ "lowercase-keys": "^1.0.1",
+ "mimic-response": "^1.0.1",
+ "p-cancelable": "^1.0.0",
+ "to-readable-stream": "^1.0.0",
+ "url-parse-lax": "^3.0.0"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+ "dev": true
+ },
+ "grunt": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.1.0.tgz",
+ "integrity": "sha512-+NGod0grmviZ7Nzdi9am7vuRS/h76PcWDsV635mEXF0PEQMUV6Kb+OjTdsVxbi0PZmfQOjCMKb3w8CVZcqsn1g==",
+ "dev": true,
+ "requires": {
+ "coffeescript": "~1.10.0",
+ "dateformat": "~1.0.12",
+ "eventemitter2": "~0.4.13",
+ "exit": "~0.1.1",
+ "findup-sync": "~0.3.0",
+ "glob": "~7.0.0",
+ "grunt-cli": "~1.2.0",
+ "grunt-known-options": "~1.1.0",
+ "grunt-legacy-log": "~2.0.0",
+ "grunt-legacy-util": "~1.1.1",
+ "iconv-lite": "~0.4.13",
+ "js-yaml": "~3.13.1",
+ "minimatch": "~3.0.2",
+ "mkdirp": "~1.0.3",
+ "nopt": "~3.0.6",
+ "path-is-absolute": "~1.0.0",
+ "rimraf": "~2.6.2"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.2",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "grunt-cli": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz",
+ "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=",
+ "dev": true,
+ "requires": {
+ "findup-sync": "~0.3.0",
+ "grunt-known-options": "~1.1.0",
+ "nopt": "~3.0.6",
+ "resolve": "~1.1.0"
+ }
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-contrib-clean": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-2.0.0.tgz",
+ "integrity": "sha512-g5ZD3ORk6gMa5ugZosLDQl3dZO7cI3R14U75hTM+dVLVxdMNJCPVmwf9OUt4v4eWgpKKWWoVK9DZc1amJp4nQw==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.1",
+ "rimraf": "^2.6.2"
+ },
+ "dependencies": {
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ }
+ }
+ },
+ "grunt-contrib-copy": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz",
+ "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.1",
+ "file-sync-cmp": "^0.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "grunt-contrib-watch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz",
+ "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.0",
+ "gaze": "^1.1.0",
+ "lodash": "^4.17.10",
+ "tiny-lr": "^1.1.1"
+ },
+ "dependencies": {
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ }
+ }
+ },
+ "grunt-http-server": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/grunt-http-server/-/grunt-http-server-2.1.0.tgz",
+ "integrity": "sha512-kv1qgucbRG0XthXu/uyoi15mYeF8W2QDODPurKE9zuRaJPhpuglOkHThGmqKdmJU38CEqc/Q49+Z51VhGFsN8g==",
+ "dev": true,
+ "requires": {
+ "divhide": "2.0.1",
+ "http-server": "0.11.1",
+ "lodash": "4.17.5",
+ "opener": "1.4.3",
+ "showdown": "1.8.6"
+ },
+ "dependencies": {
+ "colors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+ "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
+ "dev": true
+ },
+ "http-server": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz",
+ "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==",
+ "dev": true,
+ "requires": {
+ "colors": "1.0.3",
+ "corser": "~2.0.0",
+ "ecstatic": "^3.0.0",
+ "http-proxy": "^1.8.1",
+ "opener": "~1.4.0",
+ "optimist": "0.6.x",
+ "portfinder": "^1.0.13",
+ "union": "~0.4.3"
+ }
+ },
+ "lodash": {
+ "version": "4.17.5",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
+ "dev": true
+ },
+ "opener": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz",
+ "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=",
+ "dev": true
+ },
+ "qs": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz",
+ "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=",
+ "dev": true
+ },
+ "union": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz",
+ "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=",
+ "dev": true,
+ "requires": {
+ "qs": "~2.3.3"
+ }
+ }
+ }
+ },
+ "grunt-known-options": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz",
+ "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==",
+ "dev": true
+ },
+ "grunt-legacy-log": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz",
+ "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==",
+ "dev": true,
+ "requires": {
+ "colors": "~1.1.2",
+ "grunt-legacy-log-utils": "~2.0.0",
+ "hooker": "~0.2.3",
+ "lodash": "~4.17.5"
+ }
+ },
+ "grunt-legacy-log-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz",
+ "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==",
+ "dev": true,
+ "requires": {
+ "chalk": "~2.4.1",
+ "lodash": "~4.17.10"
+ }
+ },
+ "grunt-legacy-util": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz",
+ "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==",
+ "dev": true,
+ "requires": {
+ "async": "~1.5.2",
+ "exit": "~0.1.1",
+ "getobject": "~0.1.0",
+ "hooker": "~0.2.3",
+ "lodash": "~4.17.10",
+ "underscore.string": "~3.3.4",
+ "which": "~1.3.0"
+ }
+ },
+ "grunt-run": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/grunt-run/-/grunt-run-0.8.1.tgz",
+ "integrity": "sha512-+wvoOJevugcjMLldbVCyspRHHntwVIJiTGjx0HFq+UwXhVPe7AaAiUdY4135CS68pAoRLhd7pAILpL2ITe1tmA==",
+ "dev": true,
+ "requires": {
+ "strip-ansi": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
+ "grunt-ts": {
+ "version": "6.0.0-beta.22",
+ "resolved": "https://registry.npmjs.org/grunt-ts/-/grunt-ts-6.0.0-beta.22.tgz",
+ "integrity": "sha512-g9e+ZImQ7W38dfpwhp0+GUltXWidy3YGPfIA/IyGL5HMv6wmVmMMoSgscI5swhs2HSPf8yAvXAAJbwrouijoRg==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^2.0.4",
+ "csproj2ts": "^1.1.0",
+ "detect-indent": "^4.0.0",
+ "detect-newline": "^2.1.0",
+ "es6-promise": "~0.1.1",
+ "jsmin2": "^1.2.1",
+ "lodash": "~4.17.10",
+ "ncp": "0.5.1",
+ "rimraf": "2.2.6",
+ "semver": "^5.3.0",
+ "strip-bom": "^2.0.0"
+ },
+ "dependencies": {
+ "rimraf": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz",
+ "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=",
+ "dev": true
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ }
+ }
+ },
+ "gts": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/gts/-/gts-2.0.2.tgz",
+ "integrity": "sha512-SLytzl2IqKXf6kGULwr07XQ9lVsvjrzFD3OAA7DEfIQYuD+lKBPt/cZ/RYGxaWerY4PTfmnXT7KdxEr9Ec8uHQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/eslint-plugin": "2.31.0",
+ "@typescript-eslint/parser": "2.31.0",
+ "chalk": "^4.0.0",
+ "eslint": "^6.8.0",
+ "eslint-config-prettier": "^6.10.1",
+ "eslint-plugin-node": "^11.1.0",
+ "eslint-plugin-prettier": "^3.1.2",
+ "execa": "^4.0.0",
+ "inquirer": "^7.1.0",
+ "meow": "^7.0.0",
+ "ncp": "^2.0.0",
+ "prettier": "^2.0.4",
+ "rimraf": "^3.0.2",
+ "update-notifier": "^4.1.0",
+ "write-file-atomic": "^3.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "camelcase": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz",
+ "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+ "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.3.1",
+ "map-obj": "^4.0.0",
+ "quick-lru": "^4.0.1"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ }
+ }
+ },
+ "chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "eslint": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
+ "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "ajv": "^6.10.0",
+ "chalk": "^2.1.0",
+ "cross-spawn": "^6.0.5",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "eslint-scope": "^5.0.0",
+ "eslint-utils": "^1.4.3",
+ "eslint-visitor-keys": "^1.1.0",
+ "espree": "^6.1.2",
+ "esquery": "^1.0.1",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^5.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.0.0",
+ "globals": "^12.1.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "inquirer": "^7.0.0",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.3.0",
+ "lodash": "^4.17.14",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.8.3",
+ "progress": "^2.0.0",
+ "regexpp": "^2.0.1",
+ "semver": "^6.1.2",
+ "strip-ansi": "^5.2.0",
+ "strip-json-comments": "^3.0.1",
+ "table": "^5.2.3",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "eslint-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+ "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ },
+ "espree": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
+ "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.1.1",
+ "acorn-jsx": "^5.2.0",
+ "eslint-visitor-keys": "^1.1.0"
+ }
+ },
+ "execa": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz",
+ "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
+ "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+ "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+ "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.8.1"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ }
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "map-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz",
+ "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==",
+ "dev": true
+ },
+ "meow": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz",
+ "integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==",
+ "dev": true,
+ "requires": {
+ "@types/minimist": "^1.2.0",
+ "arrify": "^2.0.1",
+ "camelcase": "^6.0.0",
+ "camelcase-keys": "^6.2.2",
+ "decamelize-keys": "^1.1.0",
+ "hard-rejection": "^2.1.0",
+ "minimist-options": "^4.0.2",
+ "normalize-package-data": "^2.5.0",
+ "read-pkg-up": "^7.0.1",
+ "redent": "^3.0.0",
+ "trim-newlines": "^3.0.0",
+ "type-fest": "^0.13.1",
+ "yargs-parser": "^18.1.3"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "ncp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
+ "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
+ "dev": true
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "requires": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "parse-json": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
+ "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1",
+ "lines-and-columns": "^1.1.6"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "requires": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true
+ }
+ }
+ },
+ "read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "requires": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ }
+ }
+ },
+ "redent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "dev": true,
+ "requires": {
+ "indent-string": "^4.0.0",
+ "strip-indent": "^3.0.0"
+ }
+ },
+ "regexpp": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "requires": {
+ "min-indent": "^1.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "trim-newlines": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz",
+ "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==",
+ "dev": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2"
+ }
+ },
+ "type-fest": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
+ "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "hard-rejection": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
+ "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ }
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+ "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
+ "dev": true
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "has-yarn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
+ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==",
+ "dev": true
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true
+ },
+ "hooker": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz",
+ "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
+ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+ "dev": true
+ },
+ "http-cache-semantics": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+ "dev": true
+ },
+ "http-parser-js": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz",
+ "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ==",
+ "dev": true
+ },
+ "http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "dev": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
+ "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "import-lazy": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+ "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=",
+ "dev": true
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "dev": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz",
+ "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^3.0.0",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.15",
+ "mute-stream": "0.0.8",
+ "run-async": "^2.4.0",
+ "rxjs": "^6.5.3",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
+ "dev": true
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
+ "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+ "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^2.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
+ "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
+ "dev": true
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
+ "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-installed-globally": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz",
+ "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==",
+ "dev": true,
+ "requires": {
+ "global-dirs": "^2.0.1",
+ "is-path-inside": "^3.0.1"
+ }
+ },
+ "is-npm": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz",
+ "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "dev": true
+ },
+ "is-path-inside": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz",
+ "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==",
+ "dev": true
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
+ "dev": true
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz",
+ "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-string": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
+ "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+ "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
+ "dev": true
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true
+ },
+ "is-yarn-global": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
+ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
+ "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "jsmin2": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/jsmin2/-/jsmin2-1.2.1.tgz",
+ "integrity": "sha1-iPvi+/dfCpH2YCD9mBzWk/S/5X4=",
+ "dev": true
+ },
+ "json-buffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+ "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
+ "dev": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+ "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "keyv": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
+ "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
+ "dev": true,
+ "requires": {
+ "json-buffer": "3.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true
+ },
+ "latest-version": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
+ "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==",
+ "dev": true,
+ "requires": {
+ "package-json": "^6.3.0"
+ }
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^1.0.0"
+ }
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "lines-and-columns": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
+ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
+ "dev": true
+ },
+ "livereload-js": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz",
+ "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==",
+ "dev": true
+ },
+ "load-json-file": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "strip-bom": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "dev": true
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "dev": true,
+ "requires": {
+ "currently-unhandled": "^0.4.1",
+ "signal-exit": "^3.0.0"
+ }
+ },
+ "lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "mem": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ },
+ "dependencies": {
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "dev": true
+ }
+ }
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "dev": true,
+ "requires": {
+ "camelcase-keys": "^2.0.0",
+ "decamelize": "^1.1.2",
+ "loud-rejection": "^1.0.0",
+ "map-obj": "^1.0.1",
+ "minimist": "^1.1.3",
+ "normalize-package-data": "^2.3.4",
+ "object-assign": "^4.0.1",
+ "read-pkg-up": "^1.0.1",
+ "redent": "^1.0.0",
+ "trim-newlines": "^1.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "strip-bom": "^2.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^1.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^1.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "dev": true,
+ "requires": {
+ "find-up": "^1.0.0",
+ "read-pkg": "^1.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "dev": true,
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ }
+ }
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "mimic-response": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+ "dev": true
+ },
+ "min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
+ },
+ "minimist-options": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
+ "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.1",
+ "is-plain-obj": "^1.1.0",
+ "kind-of": "^6.0.3"
+ },
+ "dependencies": {
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ }
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "dev": true,
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
+ "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
+ "dev": true,
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "ncp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.5.1.tgz",
+ "integrity": "sha1-dDmFMW49tFkoG1hxaehFc1oFQ58=",
+ "dev": true
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "dev": true,
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "normalize-url": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
+ "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==",
+ "dev": true
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
+ "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "object.values": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz",
+ "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+ "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "optimist": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+ "dev": true,
+ "requires": {
+ "minimist": "~0.0.1",
+ "wordwrap": "~0.0.2"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
+ "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
+ "dev": true
+ }
+ }
+ },
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "dev": true,
+ "requires": {
+ "execa": "^0.7.0",
+ "lcid": "^1.0.0",
+ "mem": "^1.1.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "p-cancelable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
+ "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
+ "dev": true
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "package-json": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
+ "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
+ "dev": true,
+ "requires": {
+ "got": "^9.6.0",
+ "registry-auth-token": "^4.0.0",
+ "registry-url": "^5.0.0",
+ "semver": "^6.2.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+ "dev": true,
+ "requires": {
+ "pify": "^2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "picomatch": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+ "dev": true
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ },
+ "portfinder": {
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz",
+ "integrity": "sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.2",
+ "debug": "^3.1.1",
+ "mkdirp": "^0.5.1"
+ },
+ "dependencies": {
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "prepend-http": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+ "dev": true
+ },
+ "prettier": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
+ "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==",
+ "dev": true
+ },
+ "prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "requires": {
+ "fast-diff": "^1.1.2"
+ }
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "pupa": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz",
+ "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==",
+ "dev": true,
+ "requires": {
+ "escape-goat": "^2.0.0"
+ }
+ },
+ "qs": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz",
+ "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==",
+ "dev": true
+ },
+ "quick-lru": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
+ "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
+ "dev": true
+ },
+ "quiet-grunt": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/quiet-grunt/-/quiet-grunt-0.2.3.tgz",
+ "integrity": "sha1-8JCJeal9JCrC2NbuvP5Vj1nAYYQ=",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz",
+ "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=",
+ "dev": true,
+ "requires": {
+ "bytes": "1",
+ "string_decoder": "0.10"
+ },
+ "dependencies": {
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ }
+ }
+ },
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^2.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^2.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
+ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.0.0",
+ "read-pkg": "^2.0.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "dev": true,
+ "requires": {
+ "indent-string": "^2.1.0",
+ "strip-indent": "^1.0.1"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexpp": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
+ "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+ "dev": true
+ },
+ "registry-auth-token": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz",
+ "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==",
+ "dev": true,
+ "requires": {
+ "rc": "^1.2.8"
+ }
+ },
+ "registry-url": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz",
+ "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==",
+ "dev": true,
+ "requires": {
+ "rc": "^1.2.8"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "requires": {
+ "is-finite": "^1.0.0"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+ "dev": true
+ },
+ "requireindex": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz",
+ "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
+ "dev": true
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true
+ },
+ "responselike": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=",
+ "dev": true,
+ "requires": {
+ "lowercase-keys": "^1.0.0"
+ }
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true
+ },
+ "run-parallel": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz",
+ "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==",
+ "dev": true
+ },
+ "rxjs": {
+ "version": "6.5.5",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz",
+ "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "safe-json-parse": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz",
+ "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=",
+ "dev": true
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "semver-diff": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
+ "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "showdown": {
+ "version": "1.8.6",
+ "resolved": "https://registry.npmjs.org/showdown/-/showdown-1.8.6.tgz",
+ "integrity": "sha1-kepO47elRIqspoIKTifmkMatdxw=",
+ "dev": true,
+ "requires": {
+ "yargs": "^10.0.3"
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+ "dev": true
+ },
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
+ "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "astral-regex": "^1.0.0",
+ "is-fullwidth-code-point": "^2.0.0"
+ },
+ "dependencies": {
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ }
+ }
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-resolve": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
+ "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+ "dev": true,
+ "requires": {
+ "atob": "^2.1.2",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-support": {
+ "version": "0.5.19",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+ "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
+ "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "dev": true
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "string-template": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz",
+ "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "dependencies": {
+ "strip-ansi": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+ "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.0"
+ }
+ }
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
+ "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "string.prototype.trimleft": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
+ "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5",
+ "string.prototype.trimstart": "^1.0.0"
+ }
+ },
+ "string.prototype.trimright": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
+ "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5",
+ "string.prototype.trimend": "^1.0.0"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
+ "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ }
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "dev": true,
+ "requires": {
+ "get-stdin": "^4.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz",
+ "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "table": {
+ "version": "5.4.6",
+ "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
+ "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.10.2",
+ "lodash": "^4.17.14",
+ "slice-ansi": "^2.1.0",
+ "string-width": "^3.0.0"
+ },
+ "dependencies": {
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ }
+ }
+ },
+ "term-size": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz",
+ "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==",
+ "dev": true
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "tiny-lr": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz",
+ "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==",
+ "dev": true,
+ "requires": {
+ "body": "^5.1.0",
+ "debug": "^3.1.0",
+ "faye-websocket": "~0.10.0",
+ "livereload-js": "^2.3.0",
+ "object-assign": "^4.1.0",
+ "qs": "^6.4.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-readable-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
+ "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
+ "dev": true
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
+ "dev": true
+ },
+ "ts-node": {
+ "version": "8.10.2",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz",
+ "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==",
+ "dev": true,
+ "requires": {
+ "arg": "^4.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "source-map-support": "^0.5.17",
+ "yn": "3.1.1"
+ }
+ },
+ "tsconfig-paths": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz",
+ "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==",
+ "dev": true,
+ "requires": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.1",
+ "minimist": "^1.2.0",
+ "strip-bom": "^3.0.0"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ }
+ }
+ },
+ "tslib": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
+ "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
+ "dev": true
+ },
+ "tsutils": {
+ "version": "3.17.1",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
+ "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ },
+ "typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "requires": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "typescript": {
+ "version": "3.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
+ "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==",
+ "dev": true
+ },
+ "underscore.string": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz",
+ "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "^1.0.3",
+ "util-deprecate": "^1.0.2"
+ }
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "unique-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
+ "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
+ "dev": true,
+ "requires": {
+ "crypto-random-string": "^2.0.0"
+ }
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true
+ }
+ }
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+ "dev": true
+ },
+ "update-notifier": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz",
+ "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==",
+ "dev": true,
+ "requires": {
+ "boxen": "^4.2.0",
+ "chalk": "^3.0.0",
+ "configstore": "^5.0.1",
+ "has-yarn": "^2.1.0",
+ "import-lazy": "^2.1.0",
+ "is-ci": "^2.0.0",
+ "is-installed-globally": "^0.3.1",
+ "is-npm": "^4.0.0",
+ "is-yarn-global": "^0.3.0",
+ "latest-version": "^5.0.0",
+ "pupa": "^2.0.1",
+ "semver-diff": "^3.1.1",
+ "xdg-basedir": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+ "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "dev": true,
+ "requires": {
+ "@types/color-name": "^1.1.1",
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+ "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "url-join": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz",
+ "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=",
+ "dev": true
+ },
+ "url-parse-lax": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+ "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^2.0.0"
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "v8-compile-cache": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
+ "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "dev": true,
+ "requires": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "widest-line": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+ "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.0.0"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "wordwrap": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
+ "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+ "dev": true,
+ "requires": {
+ "mkdirp": "^0.5.1"
+ }
+ },
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "xdg-basedir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
+ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==",
+ "dev": true
+ },
+ "xml2js": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
+ "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
+ "dev": true,
+ "requires": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ }
+ },
+ "xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "dev": true
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
+ "dev": true
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "10.1.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz",
+ "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.1.1",
+ "find-up": "^2.1.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^2.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^8.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz",
+ "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^4.1.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=",
+ "dev": true
+ }
+ }
+ },
+ "yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true
+ }
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/package.json b/chromium/third_party/webgpu-cts/src/package.json
index ac33bc81f50..3d90cc714b4 100644
--- a/chromium/third_party/webgpu-cts/src/package.json
+++ b/chromium/third_party/webgpu-cts/src/package.json
@@ -5,6 +5,9 @@
"scripts": {
"test": "grunt pre"
},
+ "engines": {
+ "node": ">=11.14.0"
+ },
"repository": {
"type": "git",
"url": "git+https://github.com/gpuweb/cts.git"
@@ -17,34 +20,33 @@
},
"homepage": "https://github.com/gpuweb/cts#readme",
"devDependencies": {
- "@babel/cli": "^7.7.7",
- "@babel/core": "^7.7.7",
- "@babel/plugin-proposal-class-properties": "^7.7.4",
- "@babel/plugin-syntax-dynamic-import": "^7.7.4",
- "@babel/plugin-syntax-import-meta": "^7.7.4",
- "@babel/preset-typescript": "^7.7.7",
- "@types/jquery": "^3.3.30",
- "@types/node": "^13.1.2",
- "@types/offscreencanvas": "^2019.6.1",
+ "@babel/cli": "^7.10.1",
+ "@babel/core": "^7.10.2",
+ "@babel/plugin-proposal-class-properties": "^7.10.1",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-import-meta": "^7.10.1",
+ "@babel/preset-typescript": "^7.10.1",
+ "@types/jquery": "^3.3.38",
+ "@types/node": "^14.0.12",
+ "@types/offscreencanvas": "^2019.6.2",
"@webgpu/glslang": "^0.0.15",
- "@webgpu/types": "0.0.22",
+ "@webgpu/types": "0.0.24",
"babel-plugin-add-header-comment": "^1.0.3",
- "babel-plugin-const-enum": "^0.0.5",
- "clang-format": "^1.3.0",
- "fast-glob": "^3.1.1",
- "grunt": "^1.0.4",
- "grunt-babel": "^8.0.0",
+ "babel-plugin-const-enum": "^1.0.1",
+ "eslint": "^7.2.0",
+ "eslint-plugin-ban": "^1.5.1",
+ "eslint-plugin-import": "^2.21.1",
+ "fast-glob": "^3.2.2",
+ "grunt": "^1.1.0",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-copy": "^1.0.0",
+ "grunt-contrib-watch": "^1.1.0",
"grunt-http-server": "^2.1.0",
- "grunt-mkdir": "^1.0.0",
"grunt-run": "^0.8.1",
"grunt-ts": "^6.0.0-beta.22",
- "gts": "^1.1.2",
+ "gts": "^2.0.2",
"quiet-grunt": "^0.2.3",
- "ts-node": "^8.5.4",
- "tslint": "^6.1.1",
- "typescript": "^3.8.3",
- "typescript-formatter": "^7.2.2"
+ "ts-node": "^8.10.2",
+ "typescript": "^3.9.5"
}
}
diff --git a/chromium/third_party/webgpu-cts/src/prettier.config.js b/chromium/third_party/webgpu-cts/src/prettier.config.js
index 9aa538d6526..9f4053f719e 100644
--- a/chromium/third_party/webgpu-cts/src/prettier.config.js
+++ b/chromium/third_party/webgpu-cts/src/prettier.config.js
@@ -1,5 +1,6 @@
module.exports = {
printWidth: 100,
+
arrowParens: 'avoid',
bracketSpacing: true,
singleQuote: true,
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/allowed_characters.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/allowed_characters.ts
deleted file mode 100644
index bc54c2c7395..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/allowed_characters.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// It may be OK to add more allowed characters here.
-export const allowedTestNameCharacters = 'a-zA-Z0-9/_';
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/file_loader.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/file_loader.ts
new file mode 100644
index 00000000000..27e39bccfd0
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/file_loader.ts
@@ -0,0 +1,51 @@
+import { parseQuery } from './query/parseQuery.js';
+import { TestQuery } from './query/query.js';
+import { RunCaseIterable } from './test_group.js';
+import { TestSuiteListing } from './test_suite_listing.js';
+import { loadTreeForQuery, TestTree, TestTreeLeaf } from './tree.js';
+
+// A listing file, e.g. either of:
+// - `src/webgpu/listing.ts` (which is dynamically computed, has a Promise<TestSuiteListing>)
+// - `out/webgpu/listing.js` (which is pre-baked, has a TestSuiteListing)
+interface ListingFile {
+ listing: Promise<TestSuiteListing> | TestSuiteListing;
+}
+
+// A .spec.ts file, as imported.
+export interface SpecFile {
+ readonly description: string;
+ readonly g: RunCaseIterable;
+}
+
+// Base class for DefaultTestFileLoader and FakeTestFileLoader.
+export abstract class TestFileLoader {
+ abstract listing(suite: string): Promise<TestSuiteListing>;
+ protected abstract import(path: string): Promise<SpecFile>;
+
+ importSpecFile(suite: string, path: string[]): Promise<SpecFile> {
+ return this.import(`${suite}/${path.join('/')}.spec.js`);
+ }
+
+ async loadTree(query: TestQuery, subqueriesToExpand: string[] = []): Promise<TestTree> {
+ return loadTreeForQuery(
+ this,
+ query,
+ subqueriesToExpand.map(q => parseQuery(q))
+ );
+ }
+
+ async loadCases(query: TestQuery): Promise<IterableIterator<TestTreeLeaf>> {
+ const tree = await this.loadTree(query);
+ return tree.iterateLeaves();
+ }
+}
+
+export class DefaultTestFileLoader extends TestFileLoader {
+ async listing(suite: string): Promise<TestSuiteListing> {
+ return ((await import(`../../${suite}/listing.js`)) as ListingFile).listing;
+ }
+
+ import(path: string): Promise<SpecFile> {
+ return import(`../../${path}`);
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/fixture.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/fixture.ts
index a592d4f4c97..0cf811704f2 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/fixture.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/fixture.ts
@@ -1,5 +1,5 @@
-import { TestCaseRecorder } from './logger.js';
-import { ParamSpec } from './params_utils.js';
+import { TestCaseRecorder } from './logging/test_case_recorder.js';
+import { CaseParams } from './params_utils.js';
import { assert } from './util/util.js';
export class SkipTestCase extends Error {}
@@ -8,12 +8,12 @@ export class SkipTestCase extends Error {}
// A new instance of the Fixture is created for every single test case
// (i.e. every time the test function is run).
export class Fixture {
- params: ParamSpec;
+ params: unknown;
protected rec: TestCaseRecorder;
private eventualExpectations: Array<Promise<unknown>> = [];
private numOutstandingAsyncExpectations = 0;
- constructor(rec: TestCaseRecorder, params: ParamSpec) {
+ constructor(rec: TestCaseRecorder, params: CaseParams) {
this.rec = rec;
this.params = params;
}
@@ -43,7 +43,7 @@ export class Fixture {
}
fail(msg?: string): void {
- this.rec.fail(new Error(msg));
+ this.rec.expectationFailed(new Error(msg));
}
protected async immediateAsyncExpectation<T>(fn: () => Promise<T>): Promise<T> {
@@ -61,16 +61,16 @@ export class Fixture {
private expectErrorValue(expectedName: string, ex: unknown, niceStack: Error): void {
if (!(ex instanceof Error)) {
- niceStack.message = 'THREW non-error value, of type ' + typeof ex + niceStack.message;
- this.rec.fail(niceStack);
+ niceStack.message = `THREW non-error value, of type ${typeof ex}: ${ex}`;
+ this.rec.expectationFailed(niceStack);
return;
}
const actualName = ex.name;
if (actualName !== expectedName) {
- niceStack.message = `THREW ${actualName}, instead of ${expectedName}` + niceStack.message;
- this.rec.fail(niceStack);
+ niceStack.message = `THREW ${actualName}, instead of ${expectedName}: ${ex}`;
+ this.rec.expectationFailed(niceStack);
} else {
- niceStack.message = 'OK: threw ' + actualName + niceStack.message;
+ niceStack.message = `OK: threw ${actualName}${ex.message}`;
this.rec.debug(niceStack);
}
}
@@ -80,8 +80,8 @@ export class Fixture {
const m = msg ? ': ' + msg : '';
try {
await p;
- niceStack.message = 'DID NOT THROW' + m;
- this.rec.fail(niceStack);
+ niceStack.message = 'DID NOT REJECT' + m;
+ this.rec.expectationFailed(niceStack);
} catch (ex) {
niceStack.message = m;
this.expectErrorValue(expectedName, ex, niceStack);
@@ -93,7 +93,7 @@ export class Fixture {
const m = msg ? ': ' + msg : '';
try {
fn();
- this.rec.fail(new Error('DID NOT THROW' + m));
+ this.rec.expectationFailed(new Error('DID NOT THROW' + m));
} catch (ex) {
this.expectErrorValue(expectedName, ex, new Error(m));
}
@@ -104,7 +104,7 @@ export class Fixture {
const m = msg ? ': ' + msg : '';
this.rec.debug(new Error('expect OK' + m));
} else {
- this.rec.fail(new Error(msg));
+ this.rec.expectationFailed(new Error(msg));
}
return cond;
}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/generate_minimal_query_list.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/generate_minimal_query_list.ts
deleted file mode 100644
index 32538bbe621..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/generate_minimal_query_list.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import { TestSpecOrTestOrCaseID } from './id.js';
-import { Logger } from './logger.js';
-import { makeFilter } from './test_filter/load_filter.js';
-import { TestFilterResult } from './test_filter/test_filter_result.js';
-import { FilterResultTreeNode, treeFromFilterResults } from './tree.js';
-
-interface QuerySplitterTreeNode {
- needsSplit: boolean;
- children?: Map<string, QuerySplitterTreeNode>;
-}
-
-interface Expectation {
- id: TestSpecOrTestOrCaseID;
- line: string;
- seen: boolean;
-}
-
-function makeQuerySplitterTree(
- caselist: TestFilterResult[],
- expectationStrings: string[]
-): QuerySplitterTreeNode {
- const expectations: Expectation[] = [];
- for (const e of expectationStrings) {
- const filter = makeFilter(e);
- const id = filter.idIfSingle();
- if (!id) {
- throw new Error(
- 'Can only handle expectations which cover one file, one test, or one case. ' + e
- );
- }
- expectations.push({ id, line: e, seen: false });
- }
-
- const convertToQuerySplitterTree = (
- tree: FilterResultTreeNode,
- name?: string
- ): QuerySplitterTreeNode => {
- const children = tree.children;
- let needsSplit = true;
-
- if (name !== undefined) {
- const filter = makeFilter(name);
- const moreThanOneFile = !filter.definitelyOneFile();
- const matchingExpectations = expectations.map(e => {
- const matches = filter.matches(e.id);
- if (matches) e.seen = true;
- return matches;
- });
- needsSplit = matchingExpectations.some(m => m) || moreThanOneFile;
- }
-
- const queryNode: QuerySplitterTreeNode = { needsSplit };
- if (children) {
- queryNode.children = new Map();
- for (const [k, v] of children) {
- const subtree = convertToQuerySplitterTree(v, k);
- queryNode.children.set(k, subtree);
- }
- }
- return queryNode;
- };
-
- const log = new Logger();
- const tree = treeFromFilterResults(log, caselist.values());
- const queryTree = convertToQuerySplitterTree(tree)!;
-
- for (const e of expectations) {
- if (!e.seen) throw new Error('expectation had no effect: ' + e.line);
- }
-
- return queryTree;
-}
-
-// Takes a TestFilterResultIterator enumerating every test case in the suite, and a list of
-// expectation queries from a browser's expectations file. Creates a minimal list of queries
-// (i.e. wpt variant lines) such that:
-//
-// - There is at least one query per spec file.
-// - Each of those those input queries is in the output, so that it can have its own expectation.
-//
-// It does this by creating a tree from the list of cases (same tree as the standalone runner uses),
-// then marking every node which is a parent of a node that matches an expectation.
-export async function generateMinimalQueryList(
- caselist: TestFilterResult[],
- expectationStrings: string[]
-): Promise<string[]> {
- const unsplitNodes: string[] = [];
- const findUnsplitNodes = (name: string, node: QuerySplitterTreeNode | undefined) => {
- if (node === undefined) {
- return;
- }
- if (node.needsSplit && node.children) {
- for (const [k, v] of node.children) {
- findUnsplitNodes(k, v);
- }
- } else {
- unsplitNodes.push(name);
- }
- };
-
- const queryTree = makeQuerySplitterTree(caselist, expectationStrings);
- findUnsplitNodes('', queryTree);
-
- for (const exp of expectationStrings) {
- if (!unsplitNodes.some(name => name === exp)) {
- throw new Error(
- 'Something went wrong: all expectation strings should always appear exactly: ' + exp
- );
- }
- }
- return unsplitNodes;
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/gpu/device_pool.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/gpu/device_pool.ts
new file mode 100644
index 00000000000..b008aa180c0
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/gpu/device_pool.ts
@@ -0,0 +1,140 @@
+import { assert, raceWithRejectOnTimeout, unreachable, assertReject } from '../util/util.js';
+
+import { getGPU } from './implementation.js';
+
+interface DeviceHolder {
+ acquired: boolean; // whether the device is currently in use by a test
+ device: GPUDevice;
+ lostReason?: string; // initially undefined; becomes set when the device is lost
+}
+
+class TestFailedButDeviceReusable extends Error {}
+export class TestOOMedShouldAttemptGC extends Error {}
+
+const kPopErrorScopeTimeoutMS = 5000;
+
+export class DevicePool {
+ failed: boolean = false; // if device init failed once, never try again
+ holder?: DeviceHolder = undefined; // undefined if "uninitialized" (not yet initialized, or lost)
+
+ async acquire(): Promise<GPUDevice> {
+ assert(!this.failed, 'WebGPU device previously failed to initialize; not retrying');
+
+ if (this.holder === undefined) {
+ try {
+ this.holder = await DevicePool.makeHolder();
+ } catch (ex) {
+ this.failed = true;
+ throw ex;
+ }
+ }
+ assert(!this.holder.acquired, 'Device was in use on DevicePool.acquire');
+ this.holder.acquired = true;
+
+ this.beginErrorScopes();
+ return this.holder.device;
+ }
+
+ // When a test is done using a device, it's released back into the pool.
+ // This waits for error scopes, checks their results, and checks for various error conditions.
+ async release(device: GPUDevice): Promise<void> {
+ const holder = this.holder;
+ assert(holder !== undefined, 'trying to release a device while pool is uninitialized');
+ assert(holder.acquired, 'trying to release a device while already released');
+ assert(device === holder.device, 'Released device was the wrong device');
+
+ try {
+ // Time out if popErrorScope never completes. This could happen due to a browser bug - e.g.,
+ // as of this writing, on Chrome GPU process crash, popErrorScope just hangs.
+ await raceWithRejectOnTimeout(
+ this.endErrorScopes(),
+ kPopErrorScopeTimeoutMS,
+ 'finalization popErrorScope timed out'
+ );
+
+ // (Hopefully if the device was lost, it has been reported by the time endErrorScopes()
+ // has finished (or timed out). If not, it could cause a finite number of extra test
+ // failures following this one (but should recover eventually).)
+ const lostReason = holder.lostReason;
+ if (lostReason !== undefined) {
+ // Fail the current test.
+ unreachable(`Device was lost: ${lostReason}`);
+ }
+ } catch (ex) {
+ // Any error that isn't explicitly TestFailedButDeviceReusable forces a new device to be
+ // created for the next test.
+ if (!(ex instanceof TestFailedButDeviceReusable)) {
+ this.holder = undefined;
+ }
+ throw ex;
+ } finally {
+ // TODO: device.destroy()
+
+ // Mark the holder as free. (This only has an effect if the pool still has the holder.)
+ // This could be done at the top but is done here to guard against async-races during release.
+ holder.acquired = false;
+ }
+ }
+
+ // Gets a device and creates a DeviceHolder.
+ // If the device is lost, DeviceHolder.lostReason gets set.
+ private static async makeHolder(): Promise<DeviceHolder> {
+ const gpu = getGPU();
+ const adapter = await gpu.requestAdapter();
+
+ const holder: DeviceHolder = {
+ acquired: false,
+ device: await adapter.requestDevice(),
+ lostReason: undefined,
+ };
+ holder.device.lost.then(ev => {
+ holder.lostReason = ev.message;
+ });
+ return holder;
+ }
+
+ // Create error scopes that wrap the entire test.
+ private beginErrorScopes(): void {
+ assert(this.holder !== undefined);
+ this.holder.device.pushErrorScope('out-of-memory');
+ this.holder.device.pushErrorScope('validation');
+ }
+
+ // End the whole-test error scopes. Check that there are no extra error scopes, and that no
+ // otherwise-uncaptured errors occurred during the test.
+ private async endErrorScopes(): Promise<void> {
+ assert(this.holder !== undefined);
+ let gpuValidationError: GPUValidationError | GPUOutOfMemoryError | null;
+ let gpuOutOfMemoryError: GPUValidationError | GPUOutOfMemoryError | null;
+
+ try {
+ // May reject if the device was lost.
+ gpuValidationError = await this.holder.device.popErrorScope();
+ gpuOutOfMemoryError = await this.holder.device.popErrorScope();
+ } catch (ex) {
+ assert(
+ this.holder.lostReason !== undefined,
+ "popErrorScope failed, but device.lost hasn't fired (yet)"
+ );
+ throw ex;
+ }
+
+ await assertReject(
+ this.holder.device.popErrorScope(),
+ 'There was an extra error scope on the stack after a test'
+ );
+
+ if (gpuValidationError !== null) {
+ assert(gpuValidationError instanceof GPUValidationError);
+ // Allow the device to be reused.
+ throw new TestFailedButDeviceReusable(
+ `Unexpected validation error occurred: ${gpuValidationError.message}`
+ );
+ }
+ if (gpuOutOfMemoryError !== null) {
+ assert(gpuOutOfMemoryError instanceof GPUOutOfMemoryError);
+ // Don't allow the device to be reused; unexpected OOM could break the device.
+ throw new TestOOMedShouldAttemptGC('Unexpected out-of-memory error occurred');
+ }
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/id.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/id.ts
deleted file mode 100644
index 60d04da1598..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/id.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { ParamSpec } from './params_utils.js';
-
-// Identifies a test spec file.
-export interface TestSpecID {
- // The spec's suite name, e.g. 'webgpu'.
- readonly suite: string;
- // The spec's path within the suite, e.g. 'command_buffer/compute/basic'.
- readonly path: string;
-}
-
-export function testSpecEquals(x: TestSpecID, y: TestSpecID): boolean {
- return x.suite === y.suite && x.path === y.path;
-}
-
-// Identifies a test case (a specific parameterization of a test), within its spec file.
-export interface TestCaseID {
- readonly test: string;
- readonly params: ParamSpec | null;
-}
-
-export interface TestSpecOrTestOrCaseID {
- readonly spec: TestSpecID;
- readonly test?: string;
- readonly params?: ParamSpec | null;
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/listing.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/listing.ts
deleted file mode 100644
index bc5bedaf709..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/listing.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// A listing of all specs within a single suite. This is the (awaited) type of
-// `groups` in '{cts,unittests}/listing.ts' and the auto-generated
-// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings).
-export type TestSuiteListing = Iterable<TestSuiteListingEntry>;
-
-export interface TestSuiteListingEntry {
- readonly path: string;
- readonly description: string;
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/loader.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/loader.ts
deleted file mode 100644
index 78f804ae2bc..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/loader.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { TestSuiteListing } from './listing.js';
-import { loadFilter } from './test_filter/load_filter.js';
-import { TestFilterResult } from './test_filter/test_filter_result.js';
-import { RunCaseIterable } from './test_group.js';
-
-// One of the following:
-// - An actual .spec.ts file, as imported.
-// - A *filtered* list of cases from a single .spec.ts file.
-export interface TestSpec {
- readonly description: string;
- readonly g: RunCaseIterable;
-}
-
-// A shell object describing a directory (from its README.txt).
-export interface ReadmeFile {
- readonly description: string;
-}
-
-export type TestSpecOrReadme = TestSpec | ReadmeFile;
-
-type TestFilterResultIterator = IterableIterator<TestFilterResult>;
-function* concat(lists: TestFilterResult[][]): TestFilterResultIterator {
- for (const specs of lists) {
- yield* specs;
- }
-}
-
-export interface TestFileLoader {
- listing(suite: string): Promise<TestSuiteListing>;
- import(path: string): Promise<TestSpecOrReadme>;
-}
-
-class DefaultTestFileLoader implements TestFileLoader {
- async listing(suite: string): Promise<TestSuiteListing> {
- return (await import(`../../${suite}/listing.js`)).listing;
- }
-
- import(path: string): Promise<TestSpec> {
- return import('../../' + path);
- }
-}
-
-export class TestLoader {
- private fileLoader: TestFileLoader;
-
- constructor(fileLoader: TestFileLoader = new DefaultTestFileLoader()) {
- this.fileLoader = fileLoader;
- }
-
- // TODO: Test
- async loadTestsFromQuery(query: string): Promise<TestFilterResultIterator> {
- return this.loadTests(new URLSearchParams(query).getAll('q'));
- }
-
- // TODO: Test
- // TODO: Probably should actually not exist at all, just use queries on cmd line too.
- async loadTestsFromCmdLine(filters: string[]): Promise<TestFilterResultIterator> {
- return this.loadTests(filters);
- }
-
- async loadTests(filters: string[]): Promise<TestFilterResultIterator> {
- const loads = filters.map(f => loadFilter(this.fileLoader, f));
- return concat(await Promise.all(loads));
- }
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/logger.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/logger.ts
deleted file mode 100644
index 0dc2eb1a161..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/logger.ts
+++ /dev/null
@@ -1,159 +0,0 @@
-import { SkipTestCase } from './fixture.js';
-import { TestSpecID } from './id.js';
-import { ParamSpec, extractPublicParams } from './params_utils.js';
-import { makeQueryString } from './url_query.js';
-import { getStackTrace } from './util/stack.js';
-import { assert, now } from './util/util.js';
-import { version } from './version.js';
-
-type Status = 'running' | 'pass' | 'skip' | 'warn' | 'fail';
-export interface LiveTestSpecResult {
- readonly spec: string;
- readonly cases: LiveTestCaseResult[];
-}
-
-interface TestCaseResult {
- readonly test: string;
- readonly params: ParamSpec | null;
- status: Status;
- timems: number;
-}
-
-export interface LiveTestCaseResult extends TestCaseResult {
- logs?: LogMessageWithStack[];
-}
-
-export interface TransferredTestCaseResult extends TestCaseResult {
- // When transferred from a worker, a LogMessageWithStack turns into a generic Error
- // (its prototype gets lost and replaced with Error).
- logs?: Error[];
-}
-
-export class LogMessageWithStack extends Error {
- constructor(name: string, ex: Error, includeStack: boolean = true) {
- super(ex.message);
-
- this.name = name;
- this.stack = includeStack ? ex.stack : undefined;
- }
-
- toJSON(): string {
- let m = this.name;
- if (this.message) {
- m += ': ' + this.message;
- }
- if (this.stack) {
- m += '\n' + getStackTrace(this);
- }
- return m;
- }
-}
-
-export class Logger {
- readonly results: LiveTestSpecResult[] = [];
-
- constructor() {}
-
- record(spec: TestSpecID): [TestSpecRecorder, LiveTestSpecResult] {
- const result: LiveTestSpecResult = { spec: makeQueryString(spec), cases: [] };
- this.results.push(result);
- return [new TestSpecRecorder(result), result];
- }
-
- asJSON(space?: number): string {
- return JSON.stringify({ version, results: this.results }, undefined, space);
- }
-}
-
-export class TestSpecRecorder {
- private result: LiveTestSpecResult;
-
- constructor(result: LiveTestSpecResult) {
- this.result = result;
- }
-
- record(test: string, params: ParamSpec | null): [TestCaseRecorder, LiveTestCaseResult] {
- const result: LiveTestCaseResult = {
- test,
- params: params ? extractPublicParams(params) : null,
- status: 'running',
- timems: -1,
- };
- this.result.cases.push(result);
- return [new TestCaseRecorder(result), result];
- }
-}
-
-enum PassState {
- pass = 0,
- skip = 1,
- warn = 2,
- fail = 3,
-}
-
-export class TestCaseRecorder {
- private result: LiveTestCaseResult;
- private state = PassState.pass;
- private startTime = -1;
- private logs: LogMessageWithStack[] = [];
- private debugging = false;
-
- constructor(result: LiveTestCaseResult) {
- this.result = result;
- }
-
- start(debug: boolean = false): void {
- this.startTime = now();
- this.logs = [];
- this.state = PassState.pass;
- this.debugging = debug;
- }
-
- finish(): void {
- assert(this.startTime >= 0, 'finish() before start()');
-
- const endTime = now();
- // Round to next microsecond to avoid storing useless .xxxx00000000000002 in results.
- this.result.timems = Math.ceil((endTime - this.startTime) * 1000) / 1000;
- this.result.status = PassState[this.state] as Status;
-
- this.result.logs = this.logs;
- this.debugging = false;
- }
-
- debug(ex: Error): void {
- if (!this.debugging) {
- return;
- }
- this.logs.push(new LogMessageWithStack('DEBUG', ex, false));
- }
-
- warn(ex: Error): void {
- this.setState(PassState.warn);
- this.logs.push(new LogMessageWithStack('WARN', ex));
- }
-
- fail(ex: Error): void {
- this.setState(PassState.fail);
- this.logs.push(new LogMessageWithStack('FAIL', ex));
- }
-
- skipped(ex: SkipTestCase): void {
- this.setState(PassState.skip);
- this.logs.push(new LogMessageWithStack('SKIP', ex));
- }
-
- threw(ex: Error): void {
- if (ex instanceof SkipTestCase) {
- this.skipped(ex);
- return;
- }
-
- this.setState(PassState.fail);
- this.logs.push(new LogMessageWithStack('EXCEPTION', ex));
- }
-
- private setState(state: PassState): void {
- this.state = Math.max(this.state, state);
- }
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/logging/log_message.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/logging/log_message.ts
new file mode 100644
index 00000000000..5c5c0900357
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/logging/log_message.ts
@@ -0,0 +1,37 @@
+import { extractImportantStackTrace } from '../util/stack.js';
+
+export class LogMessageWithStack extends Error {
+ private stackHidden: boolean = false;
+ private timesSeen: number = 1;
+
+ constructor(name: string, ex: Error) {
+ super(ex.message);
+
+ this.name = name;
+ this.stack = ex.stack;
+ }
+
+ /** Set a flag so the stack is not printed in toJSON(). */
+ setStackHidden() {
+ this.stackHidden = true;
+ }
+
+ /** Increment the "seen x times" counter. */
+ incrementTimesSeen() {
+ this.timesSeen++;
+ }
+
+ toJSON(): string {
+ let m = this.name + ': ';
+ if (!this.stackHidden && this.stack) {
+ // this.message is already included in this.stack
+ m += extractImportantStackTrace(this);
+ } else {
+ m += this.message;
+ }
+ if (this.timesSeen > 1) {
+ m += `\n(seen ${this.timesSeen} times with identical stack)`;
+ }
+ return m;
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/logging/logger.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/logging/logger.ts
new file mode 100644
index 00000000000..4f4bc1c45e5
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/logging/logger.ts
@@ -0,0 +1,25 @@
+import { version } from '../version.js';
+
+import { LiveTestCaseResult } from './result.js';
+import { TestCaseRecorder } from './test_case_recorder.js';
+
+export type LogResults = Map<string, LiveTestCaseResult>;
+
+export class Logger {
+ readonly debug: boolean;
+ readonly results: LogResults = new Map();
+
+ constructor(debug: boolean) {
+ this.debug = debug;
+ }
+
+ record(name: string): [TestCaseRecorder, LiveTestCaseResult] {
+ const result: LiveTestCaseResult = { status: 'running', timems: -1 };
+ this.results.set(name, result);
+ return [new TestCaseRecorder(result, this.debug), result];
+ }
+
+ asJSON(space?: number): string {
+ return JSON.stringify({ version, results: Array.from(this.results) }, undefined, space);
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/logging/result.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/logging/result.ts
new file mode 100644
index 00000000000..ebdaf47642b
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/logging/result.ts
@@ -0,0 +1,18 @@
+import { LogMessageWithStack } from './log_message.js';
+
+export type Status = 'running' | 'pass' | 'skip' | 'warn' | 'fail';
+
+export interface TestCaseResult {
+ status: Status;
+ timems: number;
+}
+
+export interface LiveTestCaseResult extends TestCaseResult {
+ logs?: LogMessageWithStack[];
+}
+
+export interface TransferredTestCaseResult extends TestCaseResult {
+ // When transferred from a worker, a LogMessageWithStack turns into a generic Error
+ // (its prototype gets lost and replaced with Error).
+ logs?: Error[];
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/logging/test_case_recorder.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/logging/test_case_recorder.ts
new file mode 100644
index 00000000000..55dcd26b1d8
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/logging/test_case_recorder.ts
@@ -0,0 +1,126 @@
+import { SkipTestCase } from '../fixture.js';
+import { now, assert } from '../util/util.js';
+
+import { LogMessageWithStack } from './log_message.js';
+import { LiveTestCaseResult } from './result.js';
+
+enum LogSeverity {
+ Pass = 0,
+ Skip = 1,
+ Warn = 2,
+ ExpectFailed = 3,
+ ValidationFailed = 4,
+ ThrewException = 5,
+}
+
+const kMaxLogStacks = 2;
+
+/** Holds onto a LiveTestCaseResult owned by the Logger, and writes the results into it. */
+export class TestCaseRecorder {
+ private result: LiveTestCaseResult;
+ private maxLogSeverity = LogSeverity.Pass;
+ private startTime = -1;
+ private logs: LogMessageWithStack[] = [];
+ private logLinesAtCurrentSeverity = 0;
+ private debugging = false;
+ /** Used to dedup log messages which have identical stacks. */
+ private messagesForPreviouslySeenStacks = new Map<string, LogMessageWithStack>();
+
+ constructor(result: LiveTestCaseResult, debugging: boolean) {
+ this.result = result;
+ this.debugging = debugging;
+ }
+
+ start(): void {
+ assert(this.startTime < 0, 'TestCaseRecorder cannot be reused');
+ this.startTime = now();
+ }
+
+ finish(): void {
+ assert(this.startTime >= 0, 'finish() before start()');
+
+ const timeMilliseconds = now() - this.startTime;
+ // Round to next microsecond to avoid storing useless .xxxx00000000000002 in results.
+ this.result.timems = Math.ceil(timeMilliseconds * 1000) / 1000;
+
+ // Convert numeric enum back to string (but expose 'exception' as 'fail')
+ this.result.status =
+ this.maxLogSeverity === LogSeverity.Pass
+ ? 'pass'
+ : this.maxLogSeverity === LogSeverity.Skip
+ ? 'skip'
+ : this.maxLogSeverity === LogSeverity.Warn
+ ? 'warn'
+ : 'fail'; // Everything else is an error
+
+ this.result.logs = this.logs;
+ }
+
+ injectResult(injectedResult: LiveTestCaseResult): void {
+ Object.assign(this.result, injectedResult);
+ }
+
+ debug(ex: Error): void {
+ if (!this.debugging) {
+ return;
+ }
+ const logMessage = new LogMessageWithStack('DEBUG', ex);
+ logMessage.setStackHidden();
+ this.logImpl(LogSeverity.Pass, logMessage);
+ }
+
+ skipped(ex: SkipTestCase): void {
+ this.logImpl(LogSeverity.Skip, new LogMessageWithStack('SKIP', ex));
+ }
+
+ warn(ex: Error): void {
+ this.logImpl(LogSeverity.Warn, new LogMessageWithStack('WARN', ex));
+ }
+
+ expectationFailed(ex: Error): void {
+ this.logImpl(LogSeverity.ExpectFailed, new LogMessageWithStack('EXPECTATION FAILED', ex));
+ }
+
+ validationFailed(ex: Error): void {
+ this.logImpl(LogSeverity.ValidationFailed, new LogMessageWithStack('VALIDATION FAILED', ex));
+ }
+
+ threw(ex: Error): void {
+ if (ex instanceof SkipTestCase) {
+ this.skipped(ex);
+ return;
+ }
+ this.logImpl(LogSeverity.ThrewException, new LogMessageWithStack('EXCEPTION', ex));
+ }
+
+ private logImpl(level: LogSeverity, logMessage: LogMessageWithStack): void {
+ // Deduplicate errors with the exact same stack
+ if (logMessage.stack) {
+ const seen = this.messagesForPreviouslySeenStacks.get(logMessage.stack);
+ if (seen) {
+ seen.incrementTimesSeen();
+ return;
+ }
+ this.messagesForPreviouslySeenStacks.set(logMessage.stack, logMessage);
+ }
+
+ // Mark printStack=false for all logs except 2 at the highest severity
+ if (level > this.maxLogSeverity) {
+ this.logLinesAtCurrentSeverity = 0;
+ this.maxLogSeverity = level;
+ if (!this.debugging) {
+ // Go back and turn off printStack for everything of a lower log level
+ for (const log of this.logs) {
+ log.setStackHidden();
+ }
+ }
+ }
+ if (level < this.maxLogSeverity || this.logLinesAtCurrentSeverity >= kMaxLogStacks) {
+ if (!this.debugging) {
+ logMessage.setStackHidden();
+ }
+ }
+ this.logs.push(logMessage);
+ this.logLinesAtCurrentSeverity++;
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/params.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/params.ts
deleted file mode 100644
index b76279cd2aa..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/params.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import {
- ParamArgument,
- ParamSpec,
- ParamSpecIterable,
- ParamSpecIterator,
- paramsEquals,
-} from './params_utils.js';
-import { assert } from './util/util.js';
-
-export function poptions(name: string, values: ParamArgument[]): POptions {
- return new POptions(name, values);
-}
-export function pbool(name: string): POptions {
- return new POptions(name, [false, true]);
-}
-export function pexclude(params: ParamSpecIterable, exclude: ParamSpecIterable): PExclude {
- return new PExclude(params, exclude);
-}
-export function pfilter(cases: ParamSpecIterable, pred: Predicate): PFilter {
- return new PFilter(cases, pred);
-}
-export function pcombine(...params: ParamSpecIterable[]): ParamSpecIterable {
- return new PCombine(params);
-}
-
-class POptions implements ParamSpecIterable {
- private name: string;
- private values: ParamArgument[];
-
- constructor(name: string, values: ParamArgument[]) {
- this.name = name;
- this.values = values;
- }
-
- *[Symbol.iterator](): ParamSpecIterator {
- for (const value of this.values) {
- yield { [this.name]: value };
- }
- }
-}
-
-class PExclude implements ParamSpecIterable {
- private cases: ParamSpecIterable;
- private exclude: ParamSpec[];
-
- constructor(cases: ParamSpecIterable, exclude: ParamSpecIterable) {
- this.cases = cases;
- this.exclude = Array.from(exclude);
- }
-
- *[Symbol.iterator](): ParamSpecIterator {
- for (const p of this.cases) {
- if (this.exclude.every(e => !paramsEquals(p, e))) {
- yield p;
- }
- }
- }
-}
-
-type Predicate = (o: ParamSpec) => boolean;
-class PFilter implements ParamSpecIterable {
- private cases: ParamSpecIterable;
- private pred: Predicate;
-
- constructor(cases: ParamSpecIterable, pred: Predicate) {
- this.cases = cases;
- this.pred = pred;
- }
-
- *[Symbol.iterator](): ParamSpecIterator {
- for (const p of this.cases) {
- if (this.pred(p)) {
- yield p;
- }
- }
- }
-}
-
-class PCombine implements ParamSpecIterable {
- private params: ParamSpecIterable[];
-
- constructor(params: ParamSpecIterable[]) {
- this.params = params;
- }
-
- [Symbol.iterator](): ParamSpecIterator {
- return PCombine.cartesian(this.params);
- }
-
- static merge(a: ParamSpec, b: ParamSpec): ParamSpec {
- for (const key of Object.keys(a)) {
- assert(!b.hasOwnProperty(key), 'Duplicate key: ' + key);
- }
- return { ...a, ...b };
- }
-
- static *cartesian(iters: ParamSpecIterable[]): ParamSpecIterator {
- if (iters.length === 0) {
- return;
- }
- if (iters.length === 1) {
- yield* iters[0];
- return;
- }
- const [as, ...rest] = iters;
- for (const a of as) {
- for (const b of PCombine.cartesian(rest)) {
- yield PCombine.merge(a, b);
- }
- }
- }
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/params_builder.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/params_builder.ts
new file mode 100644
index 00000000000..9b18c9f30d6
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/params_builder.ts
@@ -0,0 +1,127 @@
+import { CaseParams, CaseParamsIterable, publicParamsEquals } from './params_utils.js';
+import { assert } from './util/util.js';
+
+// https://stackoverflow.com/a/56375136
+/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void
+ ? I
+ : never;
+type CheckForUnion<T, TErr, TOk> = [T] extends [UnionToIntersection<T>] ? TOk : TErr;
+
+type CheckForStringLiteralType<T, TOk> = string extends T ? void : CheckForUnion<T, void, TOk>;
+
+export function poptions<Name extends string, V>(
+ name: Name,
+ values: Iterable<V>
+): CheckForStringLiteralType<Name, Iterable<{ [name in Name]: V }>> {
+ const iter = makeReusableIterable(function* () {
+ for (const value of values) {
+ yield { [name]: value };
+ }
+ });
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+ return iter as any;
+}
+
+export function pbool<Name extends string>(
+ name: Name
+): CheckForStringLiteralType<Name, Iterable<{ [name in Name]: boolean }>> {
+ return poptions(name, [false, true]);
+}
+
+export function params(): ParamsBuilder<{}> {
+ return new ParamsBuilder();
+}
+
+export class ParamsBuilder<A extends {}> implements CaseParamsIterable {
+ private paramSpecs: CaseParamsIterable = [{}];
+
+ [Symbol.iterator](): Iterator<A> {
+ const iter: Iterator<CaseParams> = this.paramSpecs[Symbol.iterator]();
+ return iter as Iterator<A>;
+ }
+
+ combine<B extends {}>(newParams: Iterable<B>): ParamsBuilder<Merged<A, B>> {
+ const paramSpecs = this.paramSpecs as Iterable<A>;
+ this.paramSpecs = makeReusableIterable(function* () {
+ for (const a of paramSpecs) {
+ for (const b of newParams) {
+ yield mergeParams(a, b);
+ }
+ }
+ }) as CaseParamsIterable;
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+ return this as any;
+ }
+
+ expand<B extends {}>(expander: (_: A) => Iterable<B>): ParamsBuilder<Merged<A, B>> {
+ const paramSpecs = this.paramSpecs as Iterable<A>;
+ this.paramSpecs = makeReusableIterable(function* () {
+ for (const a of paramSpecs) {
+ for (const b of expander(a)) {
+ yield mergeParams(a, b);
+ }
+ }
+ }) as CaseParamsIterable;
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+ return this as any;
+ }
+
+ filter(pred: (_: A) => boolean): ParamsBuilder<A> {
+ const paramSpecs = this.paramSpecs as Iterable<A>;
+ this.paramSpecs = makeReusableIterable(function* () {
+ for (const p of paramSpecs) {
+ if (pred(p)) {
+ yield p;
+ }
+ }
+ });
+ return this;
+ }
+
+ unless(pred: (_: A) => boolean): ParamsBuilder<A> {
+ return this.filter(x => !pred(x));
+ }
+
+ exclude(exclude: CaseParamsIterable): ParamsBuilder<A> {
+ const excludeArray = Array.from(exclude);
+ const paramSpecs = this.paramSpecs;
+ this.paramSpecs = makeReusableIterable(function* () {
+ for (const p of paramSpecs) {
+ if (excludeArray.every(e => !publicParamsEquals(p, e))) {
+ yield p;
+ }
+ }
+ });
+ return this;
+ }
+}
+
+// If you create an Iterable by calling a generator function (e.g. in IIFE), it is exhausted after
+// one use. This just wraps a generator function in an object so it be iterated multiple times.
+function makeReusableIterable<P>(generatorFn: () => Generator<P>): Iterable<P> {
+ return { [Symbol.iterator]: generatorFn };
+}
+
+type ValueTypeForKeyOfMergedType<A, B, Key extends keyof A | keyof B> = Key extends keyof A
+ ? Key extends keyof B
+ ? void // Key is in both types
+ : A[Key] // Key is only in A
+ : Key extends keyof B
+ ? B[Key] // Key is only in B
+ : void; // Key is in neither type (not possible)
+
+type Merged<A, B> = keyof A & keyof B extends never
+ ? string extends keyof A | keyof B
+ ? never // (keyof A | keyof B) == string, which is too broad
+ : {
+ [Key in keyof A | keyof B]: ValueTypeForKeyOfMergedType<A, B, Key>;
+ }
+ : never; // (keyof A & keyof B) is not empty, so they overlapped
+
+function mergeParams<A extends {}, B extends {}>(a: A, b: B): Merged<A, B> {
+ for (const key of Object.keys(a)) {
+ assert(!(key in b), 'Duplicate key: ' + key);
+ }
+ return { ...a, ...b } as Merged<A, B>;
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/params_utils.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/params_utils.ts
index 4022f1d0d3a..e8c9f4cedda 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/params_utils.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/params_utils.ts
@@ -1,69 +1,34 @@
-import { objectEquals } from './util/util.js';
+import { comparePublicParamsPaths, Ordering } from './query/compare.js';
+import { kWildcard, kParamSeparator, kParamKVSeparator } from './query/separators.js';
-// tslint:disable-next-line: no-any
-export type ParamArgument = any;
-export interface ParamSpec {
+// Consider adding more types here if needed
+export type ParamArgument = void | undefined | number | string | boolean | number[];
+export interface CaseParams {
+ readonly [k: string]: ParamArgument;
+}
+export interface CaseParamsRW {
[k: string]: ParamArgument;
}
-export type ParamSpecIterable = Iterable<ParamSpec>;
-export type ParamSpecIterator = IterableIterator<ParamSpec>;
+export type CaseParamsIterable = Iterable<CaseParams>;
+
+export function paramKeyIsPublic(key: string): boolean {
+ return !key.startsWith('_');
+}
-export function extractPublicParams(params: ParamSpec): ParamSpec {
- const publicParams: ParamSpec = {};
+export function extractPublicParams(params: CaseParams): CaseParams {
+ const publicParams: CaseParamsRW = {};
for (const k of Object.keys(params)) {
- if (!k.startsWith('_')) {
+ if (paramKeyIsPublic(k)) {
publicParams[k] = params[k];
}
}
return publicParams;
}
-export function stringifyPublicParams(p: ParamSpec | null): string {
- if (p === null || paramsEquals(p, {})) {
- return '';
- }
- return JSON.stringify(extractPublicParams(p));
-}
+export const badParamValueChars = new RegExp(
+ '[' + kParamKVSeparator + kParamSeparator + kWildcard + ']'
+);
-export function paramsEquals(x: ParamSpec | null, y: ParamSpec | null): boolean {
- if (x === y) {
- return true;
- }
- if (x === null) {
- x = {};
- }
- if (y === null) {
- y = {};
- }
-
- for (const xk of Object.keys(x)) {
- if (x[xk] !== undefined && !y.hasOwnProperty(xk)) {
- return false;
- }
- if (!objectEquals(x[xk], y[xk])) {
- return false;
- }
- }
-
- for (const yk of Object.keys(y)) {
- if (y[yk] !== undefined && !x.hasOwnProperty(yk)) {
- return false;
- }
- }
- return true;
-}
-
-export function paramsSupersets(sup: ParamSpec | null, sub: ParamSpec | null): boolean {
- if (sub === null) {
- return true;
- }
- if (sup === null) {
- sup = {};
- }
- for (const k of Object.keys(sub)) {
- if (!sup.hasOwnProperty(k) || sup[k] !== sub[k]) {
- return false;
- }
- }
- return true;
+export function publicParamsEquals(x: CaseParams, y: CaseParams): boolean {
+ return comparePublicParamsPaths(x, y) === Ordering.Equal;
}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/query/compare.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/query/compare.ts
new file mode 100644
index 00000000000..c823ec915a7
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/query/compare.ts
@@ -0,0 +1,93 @@
+import { CaseParams, paramKeyIsPublic } from '../params_utils.js';
+import { assert, objectEquals } from '../util/util.js';
+
+import { TestQuery } from './query.js';
+
+export const enum Ordering {
+ Unordered,
+ StrictSuperset,
+ Equal,
+ StrictSubset,
+}
+
+/**
+ * Compares two queries for their ordering (which is used to build the tree).
+ *
+ * See src/unittests/query_compare.spec.ts for examples.
+ */
+export function compareQueries(a: TestQuery, b: TestQuery): Ordering {
+ if (a.suite !== b.suite) {
+ return Ordering.Unordered;
+ }
+
+ const filePathOrdering = comparePaths(a.filePathParts, b.filePathParts);
+ if (filePathOrdering !== Ordering.Equal || a.isMultiFile || b.isMultiFile) {
+ return compareOneLevel(filePathOrdering, a.isMultiFile, b.isMultiFile);
+ }
+ assert('testPathParts' in a && 'testPathParts' in b);
+
+ const testPathOrdering = comparePaths(a.testPathParts, b.testPathParts);
+ if (testPathOrdering !== Ordering.Equal || a.isMultiTest || b.isMultiTest) {
+ return compareOneLevel(testPathOrdering, a.isMultiTest, b.isMultiTest);
+ }
+ assert('params' in a && 'params' in b);
+
+ const paramsPathOrdering = comparePublicParamsPaths(a.params, b.params);
+ if (paramsPathOrdering !== Ordering.Equal || a.isMultiCase || b.isMultiCase) {
+ return compareOneLevel(paramsPathOrdering, a.isMultiCase, b.isMultiCase);
+ }
+ return Ordering.Equal;
+}
+
+/**
+ * Compares a single level of a query.
+ *
+ * "IsBig" means the query is big relative to the level, e.g. for test-level:
+ * - Anything >= `suite:a,*` is big
+ * - Anything <= `suite:a:*` is small
+ */
+function compareOneLevel(ordering: Ordering, aIsBig: boolean, bIsBig: boolean): Ordering {
+ assert(ordering !== Ordering.Equal || aIsBig || bIsBig);
+ if (ordering === Ordering.Unordered) return Ordering.Unordered;
+ if (aIsBig && bIsBig) return ordering;
+ if (!aIsBig && !bIsBig) return Ordering.Unordered; // Equal case is already handled
+ // Exactly one of (a, b) is big.
+ if (aIsBig && ordering !== Ordering.StrictSubset) return Ordering.StrictSuperset;
+ if (bIsBig && ordering !== Ordering.StrictSuperset) return Ordering.StrictSubset;
+ return Ordering.Unordered;
+}
+
+function comparePaths(a: readonly string[], b: readonly string[]): Ordering {
+ const shorter = Math.min(a.length, b.length);
+
+ for (let i = 0; i < shorter; ++i) {
+ if (a[i] !== b[i]) {
+ return Ordering.Unordered;
+ }
+ }
+ if (a.length === b.length) {
+ return Ordering.Equal;
+ } else if (a.length < b.length) {
+ return Ordering.StrictSuperset;
+ } else {
+ return Ordering.StrictSubset;
+ }
+}
+
+export function comparePublicParamsPaths(a: CaseParams, b: CaseParams): Ordering {
+ const aKeys = Object.keys(a).filter(k => paramKeyIsPublic(k));
+ const commonKeys = new Set(aKeys.filter(k => k in b));
+
+ for (const k of commonKeys) {
+ if (!objectEquals(a[k], b[k])) {
+ return Ordering.Unordered;
+ }
+ }
+ const bKeys = Object.keys(b).filter(k => paramKeyIsPublic(k));
+ const aRemainingKeys = aKeys.length - commonKeys.size;
+ const bRemainingKeys = bKeys.length - commonKeys.size;
+ if (aRemainingKeys === 0 && bRemainingKeys === 0) return Ordering.Equal;
+ if (aRemainingKeys === 0) return Ordering.StrictSuperset;
+ if (bRemainingKeys === 0) return Ordering.StrictSubset;
+ return Ordering.Unordered;
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/query/encode_selectively.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/query/encode_selectively.ts
new file mode 100644
index 00000000000..cc25e2dc739
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/query/encode_selectively.ts
@@ -0,0 +1,20 @@
+/**
+ * Encodes a stringified TestQuery so that it can be placed in a `?q=` parameter in a URL.
+ *
+ * `encodeURIComponent` encodes in accordance with `application/x-www-form-urlencoded`,
+ * but URLs don't actually have to be as strict as HTML form encoding
+ * (we interpret this purely from JavaScript).
+ * So we encode the component, then selectively convert some %-encoded escape codes
+ * back to their original form for readability/copyability.
+ */
+export function encodeURIComponentSelectively(s: string): string {
+ let ret = encodeURIComponent(s);
+ ret = ret.replace(/%22/g, '"'); // for JSON strings
+ ret = ret.replace(/%2C/g, ','); // for path separator, and JSON arrays
+ ret = ret.replace(/%3A/g, ':'); // for big separator
+ ret = ret.replace(/%3B/g, ';'); // for param separator
+ ret = ret.replace(/%3D/g, '='); // for params (k=v)
+ ret = ret.replace(/%5B/g, '['); // for JSON arrays
+ ret = ret.replace(/%5D/g, ']'); // for JSON arrays
+ return ret;
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/query/parseQuery.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/query/parseQuery.ts
new file mode 100644
index 00000000000..029ad4fc4fc
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/query/parseQuery.ts
@@ -0,0 +1,132 @@
+import {
+ CaseParamsRW,
+ ParamArgument,
+ badParamValueChars,
+ paramKeyIsPublic,
+} from '../params_utils.js';
+import { assert } from '../util/util.js';
+
+import {
+ TestQuery,
+ TestQueryMultiFile,
+ TestQueryMultiTest,
+ TestQueryMultiCase,
+ TestQuerySingleCase,
+} from './query.js';
+import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './separators.js';
+import { validQueryPart } from './validQueryPart.js';
+
+export function parseQuery(s: string): TestQuery {
+ try {
+ return parseQueryImpl(s);
+ } catch (ex) {
+ ex.message += '\n on: ' + s;
+ throw ex;
+ }
+}
+
+function parseQueryImpl(s: string): TestQuery {
+ // Undo encodeURIComponentSelectively
+ s = decodeURIComponent(s);
+
+ // bigParts are: suite, group, test, params (note kBigSeparator could appear in params)
+ const [suite, fileString, testString, paramsString] = s.split(kBigSeparator, 4);
+ assert(fileString !== undefined, `filter string must have at least one ${kBigSeparator}`);
+
+ const { parts: file, wildcard: filePathHasWildcard } = parseBigPart(fileString, kPathSeparator);
+
+ if (testString === undefined) {
+ // Query is file-level
+ assert(
+ filePathHasWildcard,
+ `File-level query without wildcard ${kWildcard}. Did you want a file-level query \
+(append ${kPathSeparator}${kWildcard}) or test-level query (append ${kBigSeparator}${kWildcard})?`
+ );
+ return new TestQueryMultiFile(suite, file);
+ }
+ assert(!filePathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);
+
+ const { parts: test, wildcard: testPathHasWildcard } = parseBigPart(testString, kPathSeparator);
+
+ if (paramsString === undefined) {
+ // Query is test-level
+ assert(
+ testPathHasWildcard,
+ `Test-level query without wildcard ${kWildcard}; did you want a test-level query \
+(append ${kPathSeparator}${kWildcard}) or case-level query (append ${kBigSeparator}${kWildcard})?`
+ );
+ assert(file.length > 0, 'File part of test-level query was empty (::)');
+ return new TestQueryMultiTest(suite, file, test);
+ }
+
+ // Query is case-level
+ assert(!testPathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);
+
+ const { parts: paramsParts, wildcard: paramsHasWildcard } = parseBigPart(
+ paramsString,
+ kParamSeparator
+ );
+
+ assert(test.length > 0, 'Test part of case-level query was empty (::)');
+
+ const params: CaseParamsRW = {};
+ for (const paramPart of paramsParts) {
+ const [k, v] = parseSingleParam(paramPart);
+ assert(validQueryPart.test(k), 'param key names must match ' + validQueryPart);
+ params[k] = v;
+ }
+ if (paramsHasWildcard) {
+ return new TestQueryMultiCase(suite, file, test, params);
+ } else {
+ return new TestQuerySingleCase(suite, file, test, params);
+ }
+}
+
+// webgpu:a,b,* or webgpu:a,b,c:*
+const kExampleQueries = `\
+webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}${kWildcard} or \
+webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}c${kBigSeparator}${kWildcard}`;
+
+function parseBigPart(
+ s: string,
+ separator: typeof kParamSeparator | typeof kPathSeparator
+): { parts: string[]; wildcard: boolean } {
+ if (s === '') {
+ return { parts: [], wildcard: false };
+ }
+ const parts = s.split(separator);
+
+ let endsWithWildcard = false;
+ for (const [i, part] of parts.entries()) {
+ if (i === parts.length - 1) {
+ endsWithWildcard = part === kWildcard;
+ }
+ assert(
+ part.indexOf(kWildcard) === -1 || endsWithWildcard,
+ `Wildcard ${kWildcard} must be complete last part of a path (e.g. ${kExampleQueries})`
+ );
+ }
+ if (endsWithWildcard) {
+ // Remove the last element of the array (which is just the wildcard).
+ parts.length = parts.length - 1;
+ }
+ return { parts, wildcard: endsWithWildcard };
+}
+
+function parseSingleParam(paramSubstring: string): [string, ParamArgument] {
+ assert(paramSubstring !== '', 'Param in a query must not be blank (is there a trailing comma?)');
+ const i = paramSubstring.indexOf('=');
+ assert(i !== -1, 'Param in a query must be of form key=value');
+ const k = paramSubstring.substring(0, i);
+ assert(paramKeyIsPublic(k), 'Param in a query must not be private (start with _)');
+ const v = paramSubstring.substring(i + 1);
+ return [k, parseSingleParamValue(v)];
+}
+
+function parseSingleParamValue(s: string): ParamArgument {
+ assert(
+ !badParamValueChars.test(s),
+ `param value must not match ${badParamValueChars} - was ${s}`
+ );
+ return s === 'undefined' ? undefined : JSON.parse(s);
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/query/query.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/query/query.ts
new file mode 100644
index 00000000000..9b951fe69d9
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/query/query.ts
@@ -0,0 +1,123 @@
+import { CaseParams } from '../params_utils.js';
+import { assert } from '../util/util.js';
+
+import { encodeURIComponentSelectively } from './encode_selectively.js';
+import { kBigSeparator, kPathSeparator, kWildcard, kParamSeparator } from './separators.js';
+import { stringifyPublicParams } from './stringify_params.js';
+
+/**
+ * Represents a test query of some level.
+ *
+ * TestQuery types are immutable.
+ */
+export type TestQuery =
+ | TestQuerySingleCase
+ | TestQueryMultiCase
+ | TestQueryMultiTest
+ | TestQueryMultiFile;
+
+export type TestQueryLevel =
+ | 1 // MultiFile
+ | 2 // MultiTest
+ | 3 // MultiCase
+ | 4; // SingleCase
+
+/**
+ * A multi-file test query, like `s:*` or `s:a,b,*`.
+ *
+ * Immutable (makes copies of constructor args).
+ */
+export class TestQueryMultiFile {
+ readonly level: TestQueryLevel = 1;
+ readonly isMultiFile: boolean = true;
+ readonly suite: string;
+ readonly filePathParts: readonly string[];
+
+ constructor(suite: string, file: readonly string[]) {
+ this.suite = suite;
+ this.filePathParts = [...file];
+ }
+
+ toString(): string {
+ return encodeURIComponentSelectively(this.toStringHelper().join(kBigSeparator));
+ }
+
+ protected toStringHelper(): string[] {
+ return [this.suite, [...this.filePathParts, kWildcard].join(kPathSeparator)];
+ }
+}
+
+/**
+ * A multi-test test query, like `s:f:*` or `s:f:a,b,*`.
+ *
+ * Immutable (makes copies of constructor args).
+ */
+export class TestQueryMultiTest extends TestQueryMultiFile {
+ readonly level: TestQueryLevel = 2;
+ readonly isMultiFile: false = false;
+ readonly isMultiTest: boolean = true;
+ readonly testPathParts: readonly string[];
+
+ constructor(suite: string, file: readonly string[], test: readonly string[]) {
+ super(suite, file);
+ assert(file.length > 0, 'multi-test (or finer) query must have file-path');
+ this.testPathParts = [...test];
+ }
+
+ protected toStringHelper(): string[] {
+ return [
+ this.suite,
+ this.filePathParts.join(kPathSeparator),
+ [...this.testPathParts, kWildcard].join(kPathSeparator),
+ ];
+ }
+}
+
+/**
+ * A multi-case test query, like `s:f:t:*` or `s:f:t:a,b,*`.
+ *
+ * Immutable (makes copies of constructor args), except for param values
+ * (which aren't normally supposed to change; they're marked readonly in CaseParams).
+ */
+export class TestQueryMultiCase extends TestQueryMultiTest {
+ readonly level: TestQueryLevel = 3;
+ readonly isMultiTest: false = false;
+ readonly isMultiCase: boolean = true;
+ readonly params: CaseParams;
+
+ constructor(suite: string, file: readonly string[], test: readonly string[], params: CaseParams) {
+ super(suite, file, test);
+ assert(test.length > 0, 'multi-case (or finer) query must have test-path');
+ this.params = { ...params };
+ }
+
+ protected toStringHelper(): string[] {
+ const paramsParts = stringifyPublicParams(this.params);
+ return [
+ this.suite,
+ this.filePathParts.join(kPathSeparator),
+ this.testPathParts.join(kPathSeparator),
+ [...paramsParts, kWildcard].join(kParamSeparator),
+ ];
+ }
+}
+
+/**
+ * A multi-case test query, like `s:f:t:` or `s:f:t:a=1,b=1`.
+ *
+ * Immutable (makes copies of constructor args).
+ */
+export class TestQuerySingleCase extends TestQueryMultiCase {
+ readonly level: TestQueryLevel = 4;
+ readonly isMultiCase: false = false;
+
+ protected toStringHelper(): string[] {
+ const paramsParts = stringifyPublicParams(this.params);
+ return [
+ this.suite,
+ this.filePathParts.join(kPathSeparator),
+ this.testPathParts.join(kPathSeparator),
+ paramsParts.join(kParamSeparator),
+ ];
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/query/separators.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/query/separators.ts
new file mode 100644
index 00000000000..0c8f6ea9a94
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/query/separators.ts
@@ -0,0 +1,14 @@
+/** Separator between big parts: suite:file:test:case */
+export const kBigSeparator = ':';
+
+/** Separator between path,to,file or path,to,test */
+export const kPathSeparator = ',';
+
+/** Separator between k=v;k=v */
+export const kParamSeparator = ';';
+
+/** Separator between key and value in k=v */
+export const kParamKVSeparator = '=';
+
+/** Final wildcard, if query is not single-case */
+export const kWildcard = '*';
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/query/stringify_params.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/query/stringify_params.ts
new file mode 100644
index 00000000000..921667aceae
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/query/stringify_params.ts
@@ -0,0 +1,28 @@
+import {
+ CaseParams,
+ ParamArgument,
+ badParamValueChars,
+ paramKeyIsPublic,
+} from '../params_utils.js';
+import { assert } from '../util/util.js';
+
+import { kParamKVSeparator } from './separators.js';
+
+export function stringifyPublicParams(p: CaseParams): string[] {
+ return Object.keys(p)
+ .filter(k => paramKeyIsPublic(k))
+ .map(k => stringifySingleParam(k, p[k]));
+}
+
+export function stringifySingleParam(k: string, v: ParamArgument) {
+ return `${k}${kParamKVSeparator}${stringifySingleParamValue(v)}`;
+}
+
+function stringifySingleParamValue(v: ParamArgument): string {
+ const s = v === undefined ? 'undefined' : JSON.stringify(v);
+ assert(
+ !badParamValueChars.test(s),
+ `JSON.stringified param value must not match ${badParamValueChars} - was ${s}`
+ );
+ return s;
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/query/validQueryPart.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/query/validQueryPart.ts
new file mode 100644
index 00000000000..62184adb625
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/query/validQueryPart.ts
@@ -0,0 +1,2 @@
+/** Applies to group parts, test parts, params keys. */
+export const validQueryPart = /^[a-zA-Z0-9_]+$/;
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/filter_by_group.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/filter_by_group.ts
deleted file mode 100644
index 021c4078ae2..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/filter_by_group.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { TestSpecOrTestOrCaseID } from '../id.js';
-import { ReadmeFile, TestFileLoader, TestSpec } from '../loader.js';
-
-import { TestFilter } from './internal.js';
-import { TestFilterResult } from './test_filter_result.js';
-
-export class FilterByGroup implements TestFilter {
- private readonly suite: string;
- private readonly specPathPrefix: string;
-
- constructor(suite: string, groupPrefix: string) {
- this.suite = suite;
- this.specPathPrefix = groupPrefix;
- }
-
- matches(id: TestSpecOrTestOrCaseID): boolean {
- return id.spec.suite === this.suite && this.pathMatches(id.spec.path);
- }
-
- async iterate(loader: TestFileLoader): Promise<TestFilterResult[]> {
- const specs = await loader.listing(this.suite);
- const entries: TestFilterResult[] = [];
-
- const suite = this.suite;
- for (const { path, description } of specs) {
- if (this.pathMatches(path)) {
- const isReadme = path === '' || path.endsWith('/');
- const spec = isReadme
- ? ({ description } as ReadmeFile)
- : ((await loader.import(`${suite}/${path}.spec.js`)) as TestSpec);
- entries.push({ id: { suite, path }, spec });
- }
- }
-
- return entries;
- }
-
- definitelyOneFile(): boolean {
- // FilterByGroup could always possibly match multiple files, because it represents a prefix,
- // e.g. "a:b" not "a:b:".
- return false;
- }
-
- idIfSingle(): undefined {
- // FilterByGroup could be one whole suite, but we only want whole files, tests, or cases.
- return undefined;
- }
-
- private pathMatches(path: string): boolean {
- return path.startsWith(this.specPathPrefix);
- }
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/filter_one_file.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/filter_one_file.ts
deleted file mode 100644
index c6cc9969458..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/filter_one_file.ts
+++ /dev/null
@@ -1,153 +0,0 @@
-import { TestCaseID, TestSpecID, TestSpecOrTestOrCaseID, testSpecEquals } from '../id.js';
-import { TestFileLoader, TestSpec } from '../loader.js';
-import { TestSpecRecorder } from '../logger.js';
-import { ParamSpec, paramsEquals, paramsSupersets } from '../params_utils.js';
-import { RunCase, RunCaseIterable } from '../test_group.js';
-
-import { TestFilter } from './internal.js';
-import { TestFilterResult } from './test_filter_result.js';
-
-abstract class FilterOneFile implements TestFilter {
- protected readonly specId: TestSpecID;
-
- constructor(specId: TestSpecID) {
- this.specId = specId;
- }
-
- abstract getCases(spec: TestSpec): RunCaseIterable;
-
- async iterate(loader: TestFileLoader): Promise<TestFilterResult[]> {
- const spec = (await loader.import(
- `${this.specId.suite}/${this.specId.path}.spec.js`
- )) as TestSpec;
- return [
- {
- id: this.specId,
- spec: {
- description: spec.description,
- g: this.getCases(spec),
- },
- },
- ];
- }
-
- definitelyOneFile(): true {
- return true;
- }
-
- abstract idIfSingle(): TestSpecOrTestOrCaseID | undefined;
- abstract matches(id: TestSpecOrTestOrCaseID): boolean;
-}
-
-type TestGroupFilter = (testcase: TestCaseID) => boolean;
-function filterTestGroup(group: RunCaseIterable, filter: TestGroupFilter): RunCaseIterable {
- return {
- *iterate(log: TestSpecRecorder): Iterable<RunCase> {
- for (const rc of group.iterate(log)) {
- if (filter(rc.id)) {
- yield rc;
- }
- }
- },
- };
-}
-
-export class FilterByTestMatch extends FilterOneFile {
- private readonly testPrefix: string;
-
- constructor(specId: TestSpecID, testPrefix: string) {
- super(specId);
- this.testPrefix = testPrefix;
- }
-
- getCases(spec: TestSpec): RunCaseIterable {
- return filterTestGroup(spec.g, testcase => this.testMatches(testcase.test));
- }
-
- idIfSingle(): TestSpecOrTestOrCaseID | undefined {
- if (this.testPrefix.length !== 0) {
- return undefined;
- }
- // This is one whole spec file.
- return { spec: this.specId };
- }
-
- matches(id: TestSpecOrTestOrCaseID): boolean {
- if (id.test === undefined) {
- return false;
- }
- return testSpecEquals(id.spec, this.specId) && this.testMatches(id.test);
- }
-
- private testMatches(test: string): boolean {
- return test.startsWith(this.testPrefix);
- }
-}
-
-export class FilterByParamsMatch extends FilterOneFile {
- private readonly test: string;
- private readonly params: ParamSpec | null;
-
- constructor(specId: TestSpecID, test: string, params: ParamSpec | null) {
- super(specId);
- this.test = test;
- this.params = params;
- }
-
- getCases(spec: TestSpec): RunCaseIterable {
- return filterTestGroup(spec.g, testcase => this.caseMatches(testcase.test, testcase.params));
- }
-
- idIfSingle(): TestSpecOrTestOrCaseID | undefined {
- if (this.params !== null) {
- return undefined;
- }
- // This is one whole test.
- return { spec: this.specId, test: this.test };
- }
-
- matches(id: TestSpecOrTestOrCaseID): boolean {
- if (id.test === undefined) {
- return false;
- }
- return testSpecEquals(id.spec, this.specId) && this.caseMatches(id.test, id.params);
- }
-
- private caseMatches(test: string, params: ParamSpec | null | undefined): boolean {
- if (params === undefined) {
- return false;
- }
- return test === this.test && paramsSupersets(params, this.params);
- }
-}
-
-export class FilterByParamsExact extends FilterOneFile {
- private readonly test: string;
- private readonly params: ParamSpec | null;
-
- constructor(specId: TestSpecID, test: string, params: ParamSpec | null) {
- super(specId);
- this.test = test;
- this.params = params;
- }
-
- getCases(spec: TestSpec): RunCaseIterable {
- return filterTestGroup(spec.g, testcase => this.caseMatches(testcase.test, testcase.params));
- }
-
- idIfSingle(): TestSpecOrTestOrCaseID | undefined {
- // This is one single test case.
- return { spec: this.specId, test: this.test, params: this.params };
- }
-
- matches(id: TestSpecOrTestOrCaseID): boolean {
- if (id.test === undefined || id.params === undefined) {
- return false;
- }
- return testSpecEquals(id.spec, this.specId) && this.caseMatches(id.test, id.params);
- }
-
- private caseMatches(test: string, params: ParamSpec | null): boolean {
- return test === this.test && paramsEquals(params, this.params);
- }
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/internal.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/internal.ts
deleted file mode 100644
index 5f22b4d763a..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/internal.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { TestSpecOrTestOrCaseID } from '../id.js';
-import { TestFileLoader } from '../loader.js';
-
-import { TestFilterResult } from './test_filter_result.js';
-
-export interface TestFilter {
- // Iterates over the test cases matched by the filter.
- iterate(loader: TestFileLoader): Promise<TestFilterResult[]>;
-
- // Iff the filter could not possibly match multiple files, returns true.
- definitelyOneFile(): boolean;
-
- // If the filter can accept one spec, one test, or one case, returns its ID.
- idIfSingle(): TestSpecOrTestOrCaseID | undefined;
-
- matches(id: TestSpecOrTestOrCaseID): boolean;
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/load_filter.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/load_filter.ts
deleted file mode 100644
index 08096ffd056..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/load_filter.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { allowedTestNameCharacters } from '../allowed_characters.js';
-import { TestFileLoader } from '../loader.js';
-import { ParamSpec } from '../params_utils.js';
-import { assert, unreachable } from '../util/util.js';
-
-import { FilterByGroup } from './filter_by_group.js';
-import { FilterByParamsExact, FilterByParamsMatch, FilterByTestMatch } from './filter_one_file.js';
-import { TestFilter } from './internal.js';
-import { TestFilterResult } from './test_filter_result.js';
-
-// Each filter is of one of the forms below (urlencoded).
-export function makeFilter(filter: string): TestFilter {
- const i1 = filter.indexOf(':');
- assert(i1 !== -1, 'Test queries must fully specify their suite name (e.g. "webgpu:")');
-
- const suite = filter.substring(0, i1);
- const i2 = filter.indexOf(':', i1 + 1);
- if (i2 === -1) {
- // - webgpu:
- // - webgpu:buf
- // - webgpu:buffers/
- // - webgpu:buffers/map
- const groupPrefix = filter.substring(i1 + 1);
- return new FilterByGroup(suite, groupPrefix);
- }
-
- const path = filter.substring(i1 + 1, i2);
- const endOfTestName = new RegExp('[^' + allowedTestNameCharacters + ']');
- const i3sub = filter.substring(i2 + 1).search(endOfTestName);
- if (i3sub === -1) {
- // - webgpu:buffers/mapWriteAsync:
- // - webgpu:buffers/mapWriteAsync:b
- const testPrefix = filter.substring(i2 + 1);
- return new FilterByTestMatch({ suite, path }, testPrefix);
- }
-
- const i3 = i2 + 1 + i3sub;
- const test = filter.substring(i2 + 1, i3);
- const token = filter.charAt(i3);
-
- let params = null;
- if (i3 + 1 < filter.length) {
- params = JSON.parse(filter.substring(i3 + 1)) as ParamSpec;
- }
-
- if (token === '~') {
- // - webgpu:buffers/mapWriteAsync:basic~
- // - webgpu:buffers/mapWriteAsync:basic~{}
- // - webgpu:buffers/mapWriteAsync:basic~{filter:"params"}
- return new FilterByParamsMatch({ suite, path }, test, params);
- } else if (token === '=') {
- // - webgpu:buffers/mapWriteAsync:basic=
- // - webgpu:buffers/mapWriteAsync:basic={}
- // - webgpu:buffers/mapWriteAsync:basic={exact:"params"}
- return new FilterByParamsExact({ suite, path }, test, params);
- } else {
- unreachable("invalid character after test name; must be '~' or '='");
- }
-}
-
-export function loadFilter(loader: TestFileLoader, filter: string): Promise<TestFilterResult[]> {
- return makeFilter(filter).iterate(loader);
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/test_filter_result.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/test_filter_result.ts
deleted file mode 100644
index 934d94eb331..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/test_filter/test_filter_result.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { TestSpecID } from '../id.js';
-import { TestSpecOrReadme } from '../loader.js';
-
-// Result of iterating a test filter. Contains a loaded spec (.spec.ts) file and its id.
-export interface TestFilterResult {
- readonly id: TestSpecID;
- readonly spec: TestSpecOrReadme;
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/test_group.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/test_group.ts
index 1bf00efdbc0..706a2334f33 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/test_group.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/test_group.ts
@@ -1,43 +1,66 @@
-import { allowedTestNameCharacters } from './allowed_characters.js';
import { Fixture } from './fixture.js';
-import { TestCaseID } from './id.js';
-import { LiveTestCaseResult, TestCaseRecorder, TestSpecRecorder } from './logger.js';
-import { ParamSpec, ParamSpecIterable, extractPublicParams, paramsEquals } from './params_utils.js';
-import { checkPublicParamType } from './url_query.js';
+import { TestCaseRecorder } from './logging/test_case_recorder.js';
+import {
+ CaseParams,
+ CaseParamsIterable,
+ extractPublicParams,
+ publicParamsEquals,
+} from './params_utils.js';
+import { kPathSeparator } from './query/separators.js';
+import { stringifyPublicParams } from './query/stringify_params.js';
+import { validQueryPart } from './query/validQueryPart.js';
import { assert } from './util/util.js';
+export type RunFn = (rec: TestCaseRecorder) => Promise<void>;
+
+export interface TestCaseID {
+ readonly test: readonly string[];
+ readonly params: CaseParams;
+}
+
export interface RunCase {
readonly id: TestCaseID;
- run(debug?: boolean): Promise<LiveTestCaseResult>;
- injectResult(result: LiveTestCaseResult): void;
+ run: RunFn;
}
-export interface RunCaseIterable {
- iterate(rec: TestSpecRecorder): Iterable<RunCase>;
+// Interface for defining tests
+export interface TestGroupBuilder<F extends Fixture> {
+ test(name: string): TestBuilderWithName<F, never>;
+}
+export function makeTestGroup<F extends Fixture>(fixture: FixtureClass<F>): TestGroupBuilder<F> {
+ return new TestGroup(fixture);
}
-type FixtureClass<F extends Fixture> = new (log: TestCaseRecorder, params: ParamSpec) => F;
-type TestFn<F extends Fixture> = (t: F) => Promise<void> | void;
+// Interface for running tests
+export interface RunCaseIterable {
+ iterate(): Iterable<RunCase>;
+ checkCaseNamesAndDuplicates(): void;
+}
+export function makeTestGroupForUnitTesting<F extends Fixture>(
+ fixture: FixtureClass<F>
+): TestGroup<F> {
+ return new TestGroup(fixture);
+}
-const validNames = new RegExp('^[' + allowedTestNameCharacters + ']+$');
+type FixtureClass<F extends Fixture> = new (log: TestCaseRecorder, params: CaseParams) => F;
+type TestFn<F extends Fixture, P extends {}> = (t: F & { params: P }) => Promise<void> | void;
-export class TestGroup<F extends Fixture> implements RunCaseIterable {
+class TestGroup<F extends Fixture> implements RunCaseIterable, TestGroupBuilder<F> {
private fixture: FixtureClass<F>;
private seen: Set<string> = new Set();
- private tests: Array<Test<F>> = [];
+ private tests: Array<TestBuilder<F, never>> = [];
constructor(fixture: FixtureClass<F>) {
this.fixture = fixture;
}
- *iterate(log: TestSpecRecorder): Iterable<RunCase> {
+ *iterate(): Iterable<RunCase> {
for (const test of this.tests) {
- yield* test.iterate(log);
+ yield* test.iterate();
}
}
private checkName(name: string): void {
- assert(validNames.test(name), `Invalid test name ${name}; must match [${validNames}]+`);
assert(
// Shouldn't happen due to the rule above. Just makes sure that treated
// unencoded strings as encoded strings is OK.
@@ -50,90 +73,110 @@ export class TestGroup<F extends Fixture> implements RunCaseIterable {
}
// TODO: This could take a fixture, too, to override the one for the group.
- test(name: string, fn: TestFn<F>): Test<F> {
- // Replace spaces with underscores for readability.
- assert(name.indexOf('_') === -1, 'Invalid test name ${name}: contains underscore (use space)');
- name = name.replace(/ /g, '_');
-
+ test(name: string): TestBuilderWithName<F, never> {
this.checkName(name);
- const test = new Test<F>(name, this.fixture, fn);
+ const parts = name.split(kPathSeparator);
+ for (const p of parts) {
+ assert(validQueryPart.test(p), `Invalid test name part ${p}; must match ${validQueryPart}`);
+ }
+
+ const test = new TestBuilder<F, never>(parts, this.fixture);
this.tests.push(test);
return test;
}
+
+ checkCaseNamesAndDuplicates(): void {
+ for (const test of this.tests) {
+ test.checkCaseNamesAndDuplicates();
+ }
+ }
+}
+
+interface TestBuilderWithName<F extends Fixture, P extends {}> extends TestBuilderWithParams<F, P> {
+ params<NewP extends {}>(specs: Iterable<NewP>): TestBuilderWithParams<F, NewP>;
}
-// This test is created when it's inserted, but may be parameterized afterward (.params()).
-class Test<F extends Fixture> {
- readonly name: string;
- readonly fixture: FixtureClass<F>;
- readonly fn: TestFn<F>;
- private cases: ParamSpecIterable | null = null;
+interface TestBuilderWithParams<F extends Fixture, P extends {}> {
+ fn(fn: TestFn<F, P>): void;
+}
+
+class TestBuilder<F extends Fixture, P extends {}> {
+ private readonly testPath: string[];
+ private readonly fixture: FixtureClass<F>;
+ private testFn: TestFn<F, P> | undefined;
+ private cases?: CaseParamsIterable = undefined;
- constructor(name: string, fixture: FixtureClass<F>, fn: TestFn<F>) {
- this.name = name;
+ constructor(testPath: string[], fixture: FixtureClass<F>) {
+ this.testPath = testPath;
this.fixture = fixture;
- this.fn = fn;
}
- params(specs: ParamSpecIterable): void {
- assert(this.cases === null, 'test case is already parameterized');
- const cases = Array.from(specs);
- const seen: ParamSpec[] = [];
- // This is n^2.
- for (const spec of cases) {
- const publicParams = extractPublicParams(spec);
+ fn(fn: TestFn<F, P>): void {
+ this.testFn = fn;
+ }
- // Check type of public params: can only be (currently):
- // number, string, boolean, undefined, number[]
- for (const v of Object.values(publicParams)) {
- checkPublicParamType(v);
- }
+ checkCaseNamesAndDuplicates(): void {
+ if (this.cases === undefined) {
+ return;
+ }
- assert(!seen.some(x => paramsEquals(x, publicParams)), 'Duplicate test case params');
- seen.push(publicParams);
+ // This is n^2.
+ const seen: CaseParams[] = [];
+ for (const testcase of this.cases) {
+ // stringifyPublicParams also checks for invalid params values
+ const testcaseString = stringifyPublicParams(testcase);
+ assert(
+ !seen.some(x => publicParamsEquals(x, testcase)),
+ `Duplicate public test case params: ${testcaseString}`
+ );
+ seen.push(testcase);
}
- this.cases = cases;
}
- *iterate(rec: TestSpecRecorder): IterableIterator<RunCase> {
- for (const params of this.cases || [null]) {
- yield new RunCaseSpecific(rec, this.name, params, this.fixture, this.fn);
+ params<NewP extends {}>(casesIterable: Iterable<NewP>): TestBuilderWithParams<F, NewP> {
+ assert(this.cases === undefined, 'test case is already parameterized');
+ this.cases = Array.from(casesIterable);
+
+ return (this as unknown) as TestBuilderWithParams<F, NewP>;
+ }
+
+ *iterate(): IterableIterator<RunCase> {
+ assert(this.testFn !== undefined, 'No test function (.fn()) for test');
+ for (const params of this.cases || [{}]) {
+ yield new RunCaseSpecific(this.testPath, params, this.fixture, this.testFn);
}
}
}
class RunCaseSpecific<F extends Fixture> implements RunCase {
readonly id: TestCaseID;
- private readonly params: ParamSpec | null;
- private readonly recorder: TestSpecRecorder;
+
+ private readonly params: CaseParams | null;
private readonly fixture: FixtureClass<F>;
- private readonly fn: TestFn<F>;
+ private readonly fn: TestFn<F, never>;
constructor(
- recorder: TestSpecRecorder,
- test: string,
- params: ParamSpec | null,
+ testPath: string[],
+ params: CaseParams,
fixture: FixtureClass<F>,
- fn: TestFn<F>
+ fn: TestFn<F, never>
) {
- this.id = { test, params: params ? extractPublicParams(params) : null };
+ this.id = { test: testPath, params: extractPublicParams(params) };
this.params = params;
- this.recorder = recorder;
this.fixture = fixture;
this.fn = fn;
}
- async run(debug: boolean): Promise<LiveTestCaseResult> {
- const [rec, res] = this.recorder.record(this.id.test, this.id.params);
- rec.start(debug);
-
+ async run(rec: TestCaseRecorder): Promise<void> {
+ rec.start();
try {
const inst = new this.fixture(rec, this.params || {});
try {
await inst.init();
- await this.fn(inst);
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+ await this.fn(inst as any);
} finally {
// Runs as long as constructor succeeded, even if initialization or the test failed.
await inst.finalize();
@@ -141,16 +184,10 @@ class RunCaseSpecific<F extends Fixture> implements RunCase {
} catch (ex) {
// There was an exception from constructor, init, test, or finalize.
// An error from init or test may have been a SkipTestCase.
- // An error from finalize may have been an eventualAsyncExpectation failure.
+ // An error from finalize may have been an eventualAsyncExpectation failure
+ // or unexpected validation/OOM error from the GPUDevice.
rec.threw(ex);
}
-
rec.finish();
- return res;
- }
-
- injectResult(result: LiveTestCaseResult): void {
- const [, res] = this.recorder.record(this.id.test, this.id.params);
- Object.assign(res, result);
}
}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/test_suite_listing.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/test_suite_listing.ts
new file mode 100644
index 00000000000..c3c6896229a
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/test_suite_listing.ts
@@ -0,0 +1,16 @@
+// A listing of all specs within a single suite. This is the (awaited) type of
+// `groups` in '{cts,unittests}/listing.ts' and `listing` in the auto-generated
+// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings).
+export type TestSuiteListing = TestSuiteListingEntry[];
+
+export type TestSuiteListingEntry = TestSuiteListingEntrySpec | TestSuiteListingEntryReadme;
+
+interface TestSuiteListingEntrySpec {
+ readonly file: string[];
+ readonly description: string;
+}
+
+interface TestSuiteListingEntryReadme {
+ readonly file: string[];
+ readonly readme: string;
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/tree.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/tree.ts
index 514fc505a55..9b74afb10b4 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/tree.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/tree.ts
@@ -1,82 +1,437 @@
-import { Logger } from './logger.js';
-import { stringifyPublicParams } from './params_utils.js';
-import { TestFilterResult } from './test_filter/test_filter_result.js';
-import { RunCase } from './test_group.js';
+import { TestFileLoader } from './file_loader.js';
+import { TestCaseRecorder } from './logging/test_case_recorder.js';
+import { CaseParamsRW } from './params_utils.js';
+import { compareQueries, Ordering } from './query/compare.js';
+import {
+ TestQuery,
+ TestQueryMultiCase,
+ TestQuerySingleCase,
+ TestQueryMultiFile,
+ TestQueryMultiTest,
+} from './query/query.js';
+import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './query/separators.js';
+import { stringifySingleParam } from './query/stringify_params.js';
+import { RunCase, RunFn } from './test_group.js';
+import { assert } from './util/util.js';
-export interface FilterResultTreeNode {
+// `loadTreeForQuery()` loads a TestTree for a given queryToLoad.
+// The resulting tree is a linked-list all the way from `suite:*` to queryToLoad,
+// and under queryToLoad is a tree containing every case matched by queryToLoad.
+//
+// `subqueriesToExpand` influences the `collapsible` flag on nodes in the resulting tree.
+// A node is considered "collapsible" if none of the subqueriesToExpand is a StrictSubset
+// of that node.
+//
+// In WebKit/Blink-style web_tests, an expectation file marks individual cts.html "variants" as
+// "Failure", "Crash", etc.
+// By passing in the list of expectations as the subqueriesToExpand, we can programmatically
+// subdivide the cts.html "variants" list to be able to implement arbitrarily-fine suppressions
+// (instead of having to suppress entire test files, which would lose a lot of coverage).
+//
+// `iterateCollapsedQueries()` produces the list of queries for the variants list.
+//
+// Though somewhat complicated, this system has important benefits:
+// - Avoids having to suppress entire test files, which would cause large test coverage loss.
+// - Minimizes the number of page loads needed for fine-grained suppressions.
+// (In the naive case, we could do one page load per test case - but the test suite would
+// take impossibly long to run.)
+// - Enables developers to put any number of tests in one file as appropriate, without worrying
+// about expectation granularity.
+
+export interface TestSubtree<T extends TestQuery = TestQuery> {
+ /**
+ * Readable "relative" name for display in standalone runner.
+ * Not always the exact relative name, because sometimes there isn't
+ * one (e.g. s:f:* relative to s:f,*), but something that is readable.
+ */
+ readonly readableRelativeName: string;
+ readonly query: T;
+ readonly children: Map<string, TestTreeNode>;
+ readonly collapsible: boolean;
description?: string;
- runCase?: RunCase;
- children?: Map<string, FilterResultTreeNode>;
}
-// e.g. iteratePath('a/b/c/d', ':') yields ['a/', 'a/b/', 'a/b/c/', 'a/b/c/d:']
-function* iteratePath(path: string, terminator: string): IterableIterator<string> {
- const parts = path.split('/');
- if (parts.length > 1) {
- let partial = parts[0] + '/';
- yield partial;
- for (let i = 1; i < parts.length - 1; ++i) {
- partial += parts[i] + '/';
- yield partial;
+export interface TestTreeLeaf {
+ /**
+ * Readable "relative" name for display in standalone runner.
+ */
+ readonly readableRelativeName: string;
+ readonly query: TestQuerySingleCase;
+ readonly run: RunFn;
+}
+
+export type TestTreeNode = TestSubtree | TestTreeLeaf;
+
+export class TestTree {
+ readonly root: TestSubtree;
+
+ constructor(root: TestSubtree) {
+ this.root = root;
+ }
+
+ iterateCollapsedQueries(): IterableIterator<TestQuery> {
+ return TestTree.iterateSubtreeCollapsedQueries(this.root);
+ }
+
+ iterateLeaves(): IterableIterator<TestTreeLeaf> {
+ return TestTree.iterateSubtreeLeaves(this.root);
+ }
+
+ /**
+ * If a parent and its child are at different levels, then
+ * generally the parent has only one child, i.e.:
+ * a,* { a,b,* { a,b:* { ... } } }
+ * Collapse that down into:
+ * a,* { a,b:* { ... } }
+ * which is less needlessly verbose when displaying the tree in the standalone runner.
+ */
+ dissolveLevelBoundaries(): void {
+ const newRoot = dissolveLevelBoundaries(this.root);
+ assert(newRoot === this.root);
+ }
+
+ toString(): string {
+ return TestTree.subtreeToString('(root)', this.root, '');
+ }
+
+ static *iterateSubtreeCollapsedQueries(subtree: TestSubtree): IterableIterator<TestQuery> {
+ for (const [, child] of subtree.children) {
+ if ('children' in child && !child.collapsible) {
+ yield* TestTree.iterateSubtreeCollapsedQueries(child);
+ } else {
+ yield child.query;
+ }
}
- // Path ends in '/' (so is a README).
- if (parts[parts.length - 1] === '') {
- return;
+ }
+
+ static *iterateSubtreeLeaves(subtree: TestSubtree): IterableIterator<TestTreeLeaf> {
+ for (const [, child] of subtree.children) {
+ if ('children' in child) {
+ yield* TestTree.iterateSubtreeLeaves(child);
+ } else {
+ yield child;
+ }
}
}
- yield path + terminator;
-}
-export function treeFromFilterResults(
- log: Logger,
- listing: IterableIterator<TestFilterResult>
-): FilterResultTreeNode {
- function getOrInsert(n: FilterResultTreeNode, k: string): FilterResultTreeNode {
- const children = n.children!;
- if (children.has(k)) {
- return children.get(k)!;
+ static subtreeToString(name: string, tree: TestTreeNode, indent: string): string {
+ const collapsible = 'run' in tree ? '>' : tree.collapsible ? '+' : '-';
+ let s = indent + `${collapsible} ${JSON.stringify(name)} => ${tree.query}`;
+ if ('children' in tree) {
+ if (tree.description !== undefined) {
+ s += `\n${indent} | ${JSON.stringify(tree.description)}`;
+ }
+
+ for (const [name, child] of tree.children) {
+ s += '\n' + TestTree.subtreeToString(name, child, indent + ' ');
+ }
}
- const v = { children: new Map() };
- children.set(k, v);
- return v;
+ return s;
}
+}
+
+// TODO: Consider having subqueriesToExpand actually impact the depth-order of params in the tree.
+export async function loadTreeForQuery(
+ loader: TestFileLoader,
+ queryToLoad: TestQuery,
+ subqueriesToExpand: TestQuery[]
+): Promise<TestTree> {
+ const suite = queryToLoad.suite;
+ const specs = await loader.listing(suite);
+
+ const subqueriesToExpandEntries = Array.from(subqueriesToExpand.entries());
+ const seenSubqueriesToExpand: boolean[] = new Array(subqueriesToExpand.length);
+ seenSubqueriesToExpand.fill(false);
+
+ const isCollapsible = (subquery: TestQuery) =>
+ subqueriesToExpandEntries.every(([i, toExpand]) => {
+ const ordering = compareQueries(toExpand, subquery);
- const tree = { children: new Map() };
- for (const f of listing) {
- const files = getOrInsert(tree, f.id.suite + ':');
- if (f.id.path === '') {
- // This is a suite README.
- files.description = f.spec.description.trim();
+ // If toExpand == subquery, no expansion is needed (but it's still "seen").
+ if (ordering === Ordering.Equal) seenSubqueriesToExpand[i] = true;
+ return ordering !== Ordering.StrictSubset;
+ });
+
+ // L0 = suite-level, e.g. suite:*
+ // L1 = file-level, e.g. suite:a,b:*
+ // L2 = test-level, e.g. suite:a,b:c,d:*
+ // L3 = case-level, e.g. suite:a,b:c,d:
+ let foundCase = false;
+ // L0 is suite:*
+ const subtreeL0 = makeTreeForSuite(suite);
+ isCollapsible(subtreeL0.query); // mark seenSubqueriesToExpand
+ for (const entry of specs) {
+ if (entry.file.length === 0 && 'readme' in entry) {
+ // Suite-level readme.
+ assert(subtreeL0.description === undefined);
+ subtreeL0.description = entry.readme.trim();
continue;
}
- let tests = files;
- for (const path of iteratePath(f.id.path, ':')) {
- tests = getOrInsert(tests, f.id.suite + ':' + path);
- }
- if (f.spec.description) {
- // This is a directory README or spec file.
- tests.description = f.spec.description.trim();
+ {
+ const queryL1 = new TestQueryMultiFile(suite, entry.file);
+ const orderingL1 = compareQueries(queryL1, queryToLoad);
+ if (orderingL1 === Ordering.Unordered) {
+ // File path is not matched by this query.
+ continue;
+ }
}
- if (!('g' in f.spec)) {
- // This is a directory README.
+ if ('readme' in entry) {
+ // Entry is a README that is an ancestor or descendant of the query.
+ // (It's included for display in the standalone runner.)
+
+ // readmeSubtree is suite:a,b,*
+ // (This is always going to dedup with a file path, if there are any test spec files under
+ // the directory that has the README).
+ const readmeSubtree: TestSubtree<TestQueryMultiFile> = addSubtreeForDirPath(
+ subtreeL0,
+ entry.file
+ );
+ assert(readmeSubtree.description === undefined);
+ readmeSubtree.description = entry.readme.trim();
continue;
}
+ // Entry is a spec file.
+
+ const spec = await loader.importSpecFile(queryToLoad.suite, entry.file);
+ const description = spec.description.trim();
+ // subtreeL1 is suite:a,b:*
+ const subtreeL1: TestSubtree<TestQueryMultiTest> = addSubtreeForFilePath(
+ subtreeL0,
+ entry.file,
+ description,
+ isCollapsible
+ );
- const [tRec] = log.record(f.id);
- const fId = f.id.suite + ':' + f.id.path;
- for (const t of f.spec.g.iterate(tRec)) {
- let cases = tests;
- for (const path of iteratePath(t.id.test, '~')) {
- cases = getOrInsert(cases, fId + ':' + path);
+ // TODO: If tree generation gets too slow, avoid actually iterating the cases in a file
+ // if there's no need to (based on the subqueriesToExpand).
+ for (const t of spec.g.iterate()) {
+ {
+ const queryL3 = new TestQuerySingleCase(suite, entry.file, t.id.test, t.id.params);
+ const orderingL3 = compareQueries(queryL3, queryToLoad);
+ if (orderingL3 === Ordering.Unordered || orderingL3 === Ordering.StrictSuperset) {
+ // Case is not matched by this query.
+ continue;
+ }
}
- const p = stringifyPublicParams(t.id.params);
- cases.children!.set(fId + ':' + t.id.test + '=' + p, {
- runCase: t,
- });
+ // subtreeL2 is suite:a,b:c,d:*
+ const subtreeL2: TestSubtree<TestQueryMultiCase> = addSubtreeForTestPath(
+ subtreeL1,
+ t.id.test,
+ isCollapsible
+ );
+
+ // Leaf for case is suite:a,b:c,d:x=1;y=2
+ addLeafForCase(subtreeL2, t, isCollapsible);
+
+ foundCase = true;
}
}
+
+ for (const [i, sq] of subqueriesToExpandEntries) {
+ const seen = seenSubqueriesToExpand[i];
+ assert(
+ seen,
+ `subqueriesToExpand entry did not match anything \
+(can happen due to overlap with another subquery): ${sq.toString()}`
+ );
+ }
+ assert(foundCase, 'Query does not match any cases');
+
+ return new TestTree(subtreeL0);
+}
+
+function makeTreeForSuite(suite: string): TestSubtree<TestQueryMultiFile> {
+ return {
+ readableRelativeName: suite + kBigSeparator,
+ query: new TestQueryMultiFile(suite, []),
+ children: new Map(),
+ collapsible: false,
+ };
+}
+
+function addSubtreeForDirPath(
+ tree: TestSubtree<TestQueryMultiFile>,
+ file: string[]
+): TestSubtree<TestQueryMultiFile> {
+ const subqueryFile: string[] = [];
+ // To start, tree is suite:*
+ // This loop goes from that -> suite:a,* -> suite:a,b,*
+ for (const part of file) {
+ subqueryFile.push(part);
+ tree = getOrInsertSubtree(part, tree, () => {
+ const query = new TestQueryMultiFile(tree.query.suite, subqueryFile);
+ return { readableRelativeName: part + kPathSeparator + kWildcard, query, collapsible: false };
+ });
+ }
return tree;
}
+
+function addSubtreeForFilePath(
+ tree: TestSubtree<TestQueryMultiFile>,
+ file: string[],
+ description: string,
+ checkCollapsible: (sq: TestQuery) => boolean
+): TestSubtree<TestQueryMultiTest> {
+ // To start, tree is suite:*
+ // This goes from that -> suite:a,* -> suite:a,b,*
+ tree = addSubtreeForDirPath(tree, file);
+ // This goes from that -> suite:a,b:*
+ const subtree = getOrInsertSubtree('', tree, () => {
+ const query = new TestQueryMultiTest(tree.query.suite, tree.query.filePathParts, []);
+ assert(file.length > 0, 'file path is empty');
+ return {
+ readableRelativeName: file[file.length - 1] + kBigSeparator + kWildcard,
+ query,
+ description,
+ collapsible: checkCollapsible(query),
+ };
+ });
+ return subtree;
+}
+
+function addSubtreeForTestPath(
+ tree: TestSubtree<TestQueryMultiTest>,
+ test: readonly string[],
+ isCollapsible: (sq: TestQuery) => boolean
+): TestSubtree<TestQueryMultiCase> {
+ const subqueryTest: string[] = [];
+ // To start, tree is suite:a,b:*
+ // This loop goes from that -> suite:a,b:c,* -> suite:a,b:c,d,*
+ for (const part of test) {
+ subqueryTest.push(part);
+ tree = getOrInsertSubtree(part, tree, () => {
+ const query = new TestQueryMultiTest(
+ tree.query.suite,
+ tree.query.filePathParts,
+ subqueryTest
+ );
+ return {
+ readableRelativeName: part + kPathSeparator + kWildcard,
+ query,
+ collapsible: isCollapsible(query),
+ };
+ });
+ }
+ // This goes from that -> suite:a,b:c,d:*
+ return getOrInsertSubtree('', tree, () => {
+ const query = new TestQueryMultiCase(
+ tree.query.suite,
+ tree.query.filePathParts,
+ subqueryTest,
+ {}
+ );
+ assert(subqueryTest.length > 0, 'subqueryTest is empty');
+ return {
+ readableRelativeName: subqueryTest[subqueryTest.length - 1] + kBigSeparator + kWildcard,
+ kWildcard,
+ query,
+ collapsible: isCollapsible(query),
+ };
+ });
+}
+
+function addLeafForCase(
+ tree: TestSubtree<TestQueryMultiTest>,
+ t: RunCase,
+ checkCollapsible: (sq: TestQuery) => boolean
+): void {
+ const query = tree.query;
+ let name: string = '';
+ const subqueryParams: CaseParamsRW = {};
+
+ // To start, tree is suite:a,b:c,d:*
+ // This loop goes from that -> suite:a,b:c,d:x=1;* -> suite:a,b:c,d:x=1;y=2;*
+ for (const [k, v] of Object.entries(t.id.params)) {
+ name = stringifySingleParam(k, v);
+ subqueryParams[k] = v;
+
+ tree = getOrInsertSubtree(name, tree, () => {
+ const subquery = new TestQueryMultiCase(
+ query.suite,
+ query.filePathParts,
+ query.testPathParts,
+ subqueryParams
+ );
+ return {
+ readableRelativeName: name + kParamSeparator + kWildcard,
+ query: subquery,
+ collapsible: checkCollapsible(subquery),
+ };
+ });
+ }
+
+ // This goes from that -> suite:a,b:c,d:x=1;y=2
+ const subquery = new TestQuerySingleCase(
+ query.suite,
+ query.filePathParts,
+ query.testPathParts,
+ subqueryParams
+ );
+ checkCollapsible(subquery); // mark seenSubqueriesToExpand
+ insertLeaf(tree, subquery, t);
+}
+
+function getOrInsertSubtree<T extends TestQuery>(
+ key: string,
+ parent: TestSubtree,
+ createSubtree: () => Omit<TestSubtree<T>, 'children'>
+): TestSubtree<T> {
+ let v: TestSubtree<T>;
+ const child = parent.children.get(key);
+ if (child !== undefined) {
+ assert('children' in child); // Make sure cached subtree is not actually a leaf
+ v = child as TestSubtree<T>;
+ } else {
+ v = { ...createSubtree(), children: new Map() };
+ parent.children.set(key, v);
+ }
+ return v;
+}
+
+function insertLeaf(parent: TestSubtree, query: TestQuerySingleCase, t: RunCase) {
+ const key = '';
+ const leaf: TestTreeLeaf = {
+ readableRelativeName: readableNameForCase(query),
+ query,
+ run: (rec: TestCaseRecorder) => t.run(rec),
+ };
+ assert(!parent.children.has(key));
+ parent.children.set(key, leaf);
+}
+
+function dissolveLevelBoundaries(tree: TestTreeNode): TestTreeNode {
+ if ('children' in tree) {
+ if (tree.children.size === 1 && tree.description === undefined) {
+ // Loops exactly once
+ for (const [, child] of tree.children) {
+ if (child.query.level > tree.query.level) {
+ const newtree = dissolveLevelBoundaries(child);
+
+ return newtree;
+ }
+ }
+ }
+
+ for (const [k, child] of tree.children) {
+ const newChild = dissolveLevelBoundaries(child);
+ if (newChild !== child) {
+ tree.children.set(k, newChild);
+ }
+ }
+ }
+ return tree;
+}
+
+/** Generate a readable relative name for a case (used in standalone). */
+function readableNameForCase(query: TestQuerySingleCase): string {
+ const paramsKeys = Object.keys(query.params);
+ if (paramsKeys.length === 0) {
+ return query.testPathParts[query.testPathParts.length - 1] + kBigSeparator;
+ } else {
+ const lastKey = paramsKeys[paramsKeys.length - 1];
+ return stringifySingleParam(lastKey, query.params[lastKey]);
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/url_query.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/url_query.ts
deleted file mode 100644
index b963ce3277c..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/url_query.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { TestCaseID, TestSpecID } from './id.js';
-import { ParamArgument, stringifyPublicParams } from './params_utils.js';
-import { unreachable } from './util/util.js';
-
-export function encodeSelectively(s: string): string {
- let ret = encodeURIComponent(s);
- ret = ret.replace(/%22/g, '"');
- ret = ret.replace(/%2C/g, ',');
- ret = ret.replace(/%2F/g, '/');
- ret = ret.replace(/%3A/g, ':');
- ret = ret.replace(/%3D/g, '=');
- ret = ret.replace(/%5B/g, '[');
- ret = ret.replace(/%5D/g, ']');
- ret = ret.replace(/%7B/g, '{');
- ret = ret.replace(/%7D/g, '}');
- return ret;
-}
-
-export function checkPublicParamType(v: ParamArgument): void {
- if (typeof v === 'number' || typeof v === 'string' || typeof v === 'boolean' || v === undefined) {
- return;
- }
- if (v instanceof Array) {
- for (const x of v) {
- if (typeof x !== 'number') {
- break;
- }
- }
- return;
- }
- unreachable('Invalid type for test case params ' + v);
-}
-
-export function makeQueryString(spec: TestSpecID, testcase?: TestCaseID): string {
- let s = spec.suite + ':';
- s += spec.path + ':';
- if (testcase !== undefined) {
- s += testcase.test + '=';
- s += stringifyPublicParams(testcase.params);
- }
- return encodeSelectively(s);
-}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/collect_garbage.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/util/collect_garbage.ts
index d1978315000..3cffa03a43e 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/collect_garbage.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/util/collect_garbage.ts
@@ -1,8 +1,10 @@
-// tslint:disable-next-line: no-any
+import { resolveOnTimeout } from './util.js';
+
+/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
declare const Components: any;
-export function attemptGarbageCollection(): void {
- // tslint:disable-next-line: no-any
+export async function attemptGarbageCollection(): Promise<void> {
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const w: any = self;
if (w.GCController) {
w.GCController.collect();
@@ -19,6 +21,7 @@ export function attemptGarbageCollection(): void {
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
return;
+ /* eslint-disable-next-line no-empty */
} catch (e) {}
if (w.gc) {
@@ -34,12 +37,14 @@ export function attemptGarbageCollection(): void {
let i: number;
function gcRec(n: number): void {
if (n < 1) return;
- // tslint:disable-next-line: no-any
- let temp: any = { i: 'ab' + i + i / 100000 };
+ let temp: object | string = { i: 'ab' + i + i / 100000 };
temp = temp + 'foo';
+ temp; // dummy use of unused variable
gcRec(n - 1);
}
for (i = 0; i < 1000; i++) {
gcRec(10);
}
+
+ return resolveOnTimeout(35); // Let the event loop run a few frames in case it helps.
}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/util/stack.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/util/stack.ts
index b0591f00aab..583ea4b811c 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/util/stack.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/util/stack.ts
@@ -1,33 +1,17 @@
-// Takes a stack trace, and extracts only the first continuous range of lines
-// containing '/(webgpu|unittests)/', which should provide only the useful part
-// of the stack to the caller (for logging).
-export function getStackTrace(e: Error): string {
+// Returns the stack trace of an Error, but without the extra boilerplate at the bottom
+// (e.g. RunCaseSpecific, processTicksAndRejections, etc.), for logging.
+export function extractImportantStackTrace(e: Error): string {
if (!e.stack) {
return '';
}
-
- const parts = e.stack.split('\n');
-
- const stack = [];
- const moreStack = [];
- let found = false;
- const commonRegex = /[\/\\](webgpu|unittests)[\/\\]/;
- for (let i = 0; i < parts.length; ++i) {
- const part = parts[i].trim();
- const isSuites = commonRegex.test(part); // approximate
- if (found && !isSuites) {
- moreStack.push(part);
- }
- if (isSuites) {
- if (moreStack.length) {
- stack.push(...moreStack);
- moreStack.length = 0;
- }
- stack.push(part);
- found = true;
+ const lines = e.stack.split('\n');
+ for (let i = lines.length - 1; i >= 0; --i) {
+ const line = lines[i];
+ if (line.indexOf('.spec.') !== -1) {
+ return lines.slice(0, i + 1).join('\n');
}
}
- return stack.join('\n');
+ return e.stack;
}
// *** Examples ***
diff --git a/chromium/third_party/webgpu-cts/src/src/common/framework/util/util.ts b/chromium/third_party/webgpu-cts/src/src/common/framework/util/util.ts
index 3695fc0e0df..1d42d86ffcc 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/framework/util/util.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/framework/util/util.ts
@@ -1,8 +1,17 @@
import { timeout } from './timeout.js';
-export function assert(condition: boolean, msg?: string): asserts condition {
+export function assert(condition: boolean, msg?: string | (() => string)): asserts condition {
if (!condition) {
- throw new Error(msg);
+ throw new Error(msg && (typeof msg === 'string' ? msg : msg()));
+ }
+}
+
+export async function assertReject(p: Promise<unknown>, msg?: string): Promise<void> {
+ try {
+ await p;
+ unreachable(msg);
+ } catch (ex) {
+ // Assertion OK
}
}
@@ -11,17 +20,26 @@ export function unreachable(msg?: string): never {
}
// performance.now() is available in all browsers, but not in scope by default in Node.
-// tslint:disable-next-line no-var-requires
const perf = typeof performance !== 'undefined' ? performance : require('perf_hooks').performance;
export function now(): number {
return perf.now();
}
+export function resolveOnTimeout(ms: number): Promise<void> {
+ return new Promise(resolve => {
+ timeout(() => {
+ resolve();
+ }, ms);
+ });
+}
+
+export class PromiseTimeoutError extends Error {}
+
export function rejectOnTimeout(ms: number, msg: string): Promise<never> {
- return new Promise((resolve, reject) => {
+ return new Promise((_resolve, reject) => {
timeout(() => {
- reject(new Error(msg));
+ reject(new PromiseTimeoutError(msg));
}, ms);
});
}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/runtime/cmdline.ts b/chromium/third_party/webgpu-cts/src/src/common/runtime/cmdline.ts
index 3934df3f6bc..45ca87425eb 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/runtime/cmdline.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/runtime/cmdline.ts
@@ -1,12 +1,13 @@
-// tslint:disable: no-console
+/* eslint no-console: "off" */
+/* eslint no-process-exit: "off" */
import * as fs from 'fs';
import * as process from 'process';
-import { TestSpecID } from '../framework/id.js';
-import { TestLoader } from '../framework/loader.js';
-import { LiveTestCaseResult, Logger } from '../framework/logger.js';
-import { makeQueryString } from '../framework/url_query.js';
+import { DefaultTestFileLoader } from '../framework/file_loader.js';
+import { Logger } from '../framework/logging/logger.js';
+import { LiveTestCaseResult } from '../framework/logging/result.js';
+import { parseQuery } from '../framework/query/parseQuery.js';
import { assert, unreachable } from '../framework/util/util.js';
function usage(rc: number): never {
@@ -28,7 +29,7 @@ if (!fs.existsSync('src/common/runtime/cmdline.ts')) {
let verbose = false;
let debug = false;
let printJSON = false;
-const filterArgs = [];
+const queries: string[] = [];
for (const a of process.argv.slice(2)) {
if (a.startsWith('-')) {
if (a === '--verbose') {
@@ -41,49 +42,52 @@ for (const a of process.argv.slice(2)) {
usage(1);
}
} else {
- filterArgs.push(a);
+ queries.push(a);
}
}
-if (filterArgs.length === 0) {
+if (queries.length === 0) {
usage(0);
}
(async () => {
try {
- const loader = new TestLoader();
- const files = await loader.loadTestsFromCmdLine(filterArgs);
+ const loader = new DefaultTestFileLoader();
+ assert(queries.length === 1, 'currently, there must be exactly one query on the cmd line');
+ const testcases = await loader.loadCases(parseQuery(queries[0]));
- const log = new Logger();
+ const log = new Logger(debug);
- const failed: Array<[TestSpecID, LiveTestCaseResult]> = [];
- const warned: Array<[TestSpecID, LiveTestCaseResult]> = [];
- const skipped: Array<[TestSpecID, LiveTestCaseResult]> = [];
+ const failed: Array<[string, LiveTestCaseResult]> = [];
+ const warned: Array<[string, LiveTestCaseResult]> = [];
+ const skipped: Array<[string, LiveTestCaseResult]> = [];
let total = 0;
- for (const f of files) {
- if (!('g' in f.spec)) {
- continue;
+
+ for (const testcase of testcases) {
+ const name = testcase.query.toString();
+ const [rec, res] = log.record(name);
+ await testcase.run(rec);
+
+ if (verbose) {
+ printResults([[name, res]]);
}
- const [rec] = log.record(f.id);
- for (const t of f.spec.g.iterate(rec)) {
- const res = await t.run(debug);
- if (verbose) {
- printResults([[f.id, res]]);
- }
-
- total++;
- if (res.status === 'pass') {
- } else if (res.status === 'fail') {
- failed.push([f.id, res]);
- } else if (res.status === 'warn') {
- warned.push([f.id, res]);
- } else if (res.status === 'skip') {
- skipped.push([f.id, res]);
- } else {
+ total++;
+ switch (res.status) {
+ case 'pass':
+ break;
+ case 'fail':
+ failed.push([name, res]);
+ break;
+ case 'warn':
+ warned.push([name, res]);
+ break;
+ case 'skip':
+ skipped.push([name, res]);
+ break;
+ default:
unreachable('unrecognized status');
- }
}
}
@@ -111,13 +115,11 @@ if (filterArgs.length === 0) {
}
const passed = total - warned.length - failed.length - skipped.length;
- function pct(x: number): string {
- return ((100 * x) / total).toFixed(2);
- }
- function rpt(x: number): string {
+ const pct = (x: number) => ((100 * x) / total).toFixed(2);
+ const rpt = (x: number) => {
const xs = x.toString().padStart(1 + Math.log10(total), ' ');
return `${xs} / ${total} = ${pct(x).padStart(6, ' ')}%`;
- }
+ };
console.log('');
console.log(`** Summary **
Passed w/o warnings = ${rpt(passed)}
@@ -134,9 +136,9 @@ Failed = ${rpt(failed.length)}`);
}
})();
-function printResults(results: Array<[TestSpecID, LiveTestCaseResult]>): void {
- for (const [id, r] of results) {
- console.log(`[${r.status}] ${makeQueryString(id, r)} (${r.timems}ms). Log:`);
+function printResults(results: Array<[string, LiveTestCaseResult]>): void {
+ for (const [name, r] of results) {
+ console.log(`[${r.status}] ${name} (${r.timems}ms). Log:`);
if (r.logs) {
for (const l of r.logs) {
console.log(' - ' + l.toJSON().replace(/\n/g, '\n '));
diff --git a/chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker-worker.ts b/chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker-worker.ts
index 19e4d623b22..62c66849b29 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker-worker.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker-worker.ts
@@ -1,28 +1,25 @@
-import { TestLoader } from '../../framework/loader.js';
-import { Logger } from '../../framework/logger.js';
+import { DefaultTestFileLoader } from '../../framework/file_loader.js';
+import { Logger } from '../../framework/logging/logger.js';
+import { parseQuery } from '../../framework/query/parseQuery.js';
import { assert } from '../../framework/util/util.js';
-// tslint:disable-next-line: no-any
-declare var self: any; // should be DedicatedWorkerGlobalScope
+/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+declare const self: any; // should be DedicatedWorkerGlobalScope
-const log = new Logger();
-const loader = new TestLoader();
+const loader = new DefaultTestFileLoader();
self.onmessage = async (ev: MessageEvent) => {
- const { query, debug } = ev.data;
+ const query: string = ev.data.query;
+ const debug: boolean = ev.data.debug;
- const files = Array.from(await loader.loadTests([query]));
- assert(files.length === 1, 'worker query resulted in != 1 files');
+ const log = new Logger(debug);
- const f = files[0];
- const [rec] = log.record(f.id);
- assert('g' in f.spec, 'worker query resulted in README');
+ const testcases = Array.from(await loader.loadCases(parseQuery(query)));
+ assert(testcases.length === 1, 'worker query resulted in != 1 cases');
- const cases = Array.from(f.spec.g.iterate(rec));
- assert(cases.length === 1, 'worker query resulted in != 1 cases');
- const c = cases[0];
-
- const result = await c.run(debug);
+ const testcase = testcases[0];
+ const [rec, result] = log.record(testcase.query.toString());
+ await testcase.run(rec);
self.postMessage({ query, result });
};
diff --git a/chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker.ts b/chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker.ts
index 251a405ed73..cb526a0b43d 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/runtime/helper/test_worker.ts
@@ -1,14 +1,15 @@
-import {
- LiveTestCaseResult,
- LogMessageWithStack,
- TransferredTestCaseResult,
-} from '../../framework/logger.js';
+import { LogMessageWithStack } from '../../framework/logging/log_message.js';
+import { TransferredTestCaseResult, LiveTestCaseResult } from '../../framework/logging/result.js';
+import { TestCaseRecorder } from '../../framework/logging/test_case_recorder.js';
export class TestWorker {
- private worker: Worker;
- private resolvers = new Map<string, (result: LiveTestCaseResult) => void>();
+ private readonly debug: boolean;
+ private readonly worker: Worker;
+ private readonly resolvers = new Map<string, (result: LiveTestCaseResult) => void>();
+
+ constructor(debug: boolean) {
+ this.debug = debug;
- constructor() {
const selfPath = import.meta.url;
const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/'));
const workerPath = selfPathDir + '/test_worker-worker.js';
@@ -28,10 +29,11 @@ export class TestWorker {
};
}
- run(query: string, debug: boolean = false): Promise<LiveTestCaseResult> {
- this.worker.postMessage({ query, debug });
- return new Promise(resolve => {
+ async run(rec: TestCaseRecorder, query: string): Promise<void> {
+ this.worker.postMessage({ query, debug: this.debug });
+ const workerResult = await new Promise<LiveTestCaseResult>(resolve => {
this.resolvers.set(query, resolve);
});
+ rec.injectResult(workerResult);
}
}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/runtime/standalone.ts b/chromium/third_party/webgpu-cts/src/src/common/runtime/standalone.ts
index 578418b4017..1af0e63474d 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/runtime/standalone.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/runtime/standalone.ts
@@ -1,10 +1,11 @@
// Implements the standalone test runner (see also: /standalone/index.html).
-import { TestLoader } from '../framework/loader.js';
-import { LiveTestCaseResult, Logger } from '../framework/logger.js';
-import { RunCase } from '../framework/test_group.js';
-import { FilterResultTreeNode, treeFromFilterResults } from '../framework/tree.js';
-import { encodeSelectively } from '../framework/url_query.js';
+import { DefaultTestFileLoader } from '../framework/file_loader.js';
+import { Logger } from '../framework/logging/logger.js';
+import { parseQuery } from '../framework/query/parseQuery.js';
+import { TestQueryLevel } from '../framework/query/query.js';
+import { TestTreeNode, TestSubtree, TestTreeLeaf } from '../framework/tree.js';
+import { assert } from '../framework/util/util.js';
import { optionEnabled } from './helper/options.js';
import { TestWorker } from './helper/test_worker.js';
@@ -15,12 +16,13 @@ window.onbeforeunload = () => {
};
let haveSomeResults = false;
-const log = new Logger();
const runnow = optionEnabled('runnow');
const debug = optionEnabled('debug');
-const worker = optionEnabled('worker') ? new TestWorker() : undefined;
+const logger = new Logger(debug);
+
+const worker = optionEnabled('worker') ? new TestWorker(debug) : undefined;
const resultsVis = document.getElementById('resultsVis')!;
const resultsJSON = document.getElementById('resultsJSON')!;
@@ -29,25 +31,28 @@ type RunSubtree = () => Promise<void>;
// DOM generation
-function makeTreeNodeHTML(name: string, tree: FilterResultTreeNode): [HTMLElement, RunSubtree] {
- if (tree.children) {
- return makeSubtreeHTML(name, tree);
+function makeTreeNodeHTML(
+ tree: TestTreeNode,
+ parentLevel: TestQueryLevel
+): [HTMLElement, RunSubtree] {
+ if ('children' in tree) {
+ return makeSubtreeHTML(tree, parentLevel);
} else {
- return makeCaseHTML(name, tree.runCase!);
+ return makeCaseHTML(tree);
}
}
-function makeCaseHTML(name: string, t: RunCase): [HTMLElement, RunSubtree] {
+function makeCaseHTML(t: TestTreeLeaf): [HTMLElement, RunSubtree] {
const div = $('<div>').addClass('testcase');
+ const name = t.query.toString();
const runSubtree = async () => {
haveSomeResults = true;
- let res: LiveTestCaseResult;
+ const [rec, res] = logger.record(name);
if (worker) {
- res = await worker.run(name, debug);
- t.injectResult(res);
+ await worker.run(rec, name);
} else {
- res = await t.run(debug);
+ await t.run(rec);
}
casetime.text(res.timems.toFixed(4) + ' ms');
@@ -57,62 +62,58 @@ function makeCaseHTML(name: string, t: RunCase): [HTMLElement, RunSubtree] {
if (res.logs) {
caselogs.empty();
for (const l of res.logs) {
- const caselog = $('<div>')
- .addClass('testcaselog')
- .appendTo(caselogs);
+ const caselog = $('<div>').addClass('testcaselog').appendTo(caselogs);
$('<button>')
.addClass('testcaselogbtn')
.attr('alt', 'Log stack to console')
.attr('title', 'Log stack to console')
.appendTo(caselog)
.on('click', () => {
- // tslint:disable-next-line: no-console
+ /* eslint-disable-next-line no-console */
console.log(l);
});
- $('<pre>')
- .addClass('testcaselogtext')
- .appendTo(caselog)
- .text(l.toJSON());
+ $('<pre>').addClass('testcaselogtext').appendTo(caselog).text(l.toJSON());
}
}
};
- const casehead = makeTreeNodeHeaderHTML(name, undefined, runSubtree);
+ const caselogs = $('<div>').addClass('testcaselogs');
+ const casehead = makeTreeNodeHeaderHTML(t, runSubtree, 2, checked => {
+ checked ? caselogs.show() : caselogs.hide();
+ });
div.append(casehead);
- const casetime = $('<div>')
- .addClass('testcasetime')
- .html('ms')
- .appendTo(casehead);
- const caselogs = $('<div>')
- .addClass('testcaselogs')
- .appendTo(div);
+ const casetime = $('<div>').addClass('testcasetime').html('ms').appendTo(casehead);
+ caselogs.appendTo(div);
return [div[0], runSubtree];
}
-function makeSubtreeHTML(name: string, subtree: FilterResultTreeNode): [HTMLElement, RunSubtree] {
+function makeSubtreeHTML(n: TestSubtree, parentLevel: TestQueryLevel): [HTMLElement, RunSubtree] {
const div = $('<div>').addClass('subtree');
- const header = makeTreeNodeHeaderHTML(name, subtree.description, () => {
- return runSubtree();
+ const subtreeHTML = $('<div>').addClass('subtreechildren');
+ const runSubtree = makeSubtreeChildrenHTML(subtreeHTML[0], n.children.values(), n.query.level);
+
+ const header = makeTreeNodeHeaderHTML(n, runSubtree, parentLevel, checked => {
+ checked ? subtreeHTML.show() : subtreeHTML.hide();
});
+
div.append(header);
+ div.append(subtreeHTML);
- const subtreeHTML = $('<div>')
- .addClass('subtreechildren')
- .appendTo(div);
- const runSubtree = makeSubtreeChildrenHTML(subtreeHTML[0], subtree.children!);
+ div[0].classList.add(['', 'multifile', 'multitest', 'multicase'][n.query.level]);
return [div[0], runSubtree];
}
function makeSubtreeChildrenHTML(
div: HTMLElement,
- children: Map<string, FilterResultTreeNode>
+ children: Iterable<TestTreeNode>,
+ parentLevel: TestQueryLevel
): RunSubtree {
const runSubtreeFns: RunSubtree[] = [];
- for (const [name, subtree] of children) {
- const [subtreeHTML, runSubtree] = makeTreeNodeHTML(name, subtree);
+ for (const subtree of children) {
+ const [subtreeHTML, runSubtree] = makeTreeNodeHTML(subtree, parentLevel);
div.append(subtreeHTML);
runSubtreeFns.push(runSubtree);
}
@@ -125,26 +126,38 @@ function makeSubtreeChildrenHTML(
}
function makeTreeNodeHeaderHTML(
- name: string,
- description: string | undefined,
- runSubtree: RunSubtree
+ n: TestTreeNode,
+ runSubtree: RunSubtree,
+ parentLevel: TestQueryLevel,
+ onChange: (checked: boolean) => void
): HTMLElement {
+ const isLeaf = 'run' in n;
const div = $('<div>').addClass('nodeheader');
- const nameEncoded = encodeSelectively(name);
- let nameHTML;
- {
- const i = nameEncoded.indexOf('{');
- const n1 = i === -1 ? nameEncoded : nameEncoded.slice(0, i + 1);
- const n2 = i === -1 ? '' : nameEncoded.slice(i + 1);
- nameHTML = n1.replace(/:/g, ':<wbr>') + '<wbr>' + n2.replace(/,/g, ',<wbr>');
+ const href = `?${worker ? 'worker&' : ''}${debug ? 'debug&' : ''}q=${n.query.toString()}`;
+ if (onChange) {
+ const checkbox = $('<input>')
+ .attr('type', 'checkbox')
+ .addClass('collapsebtn')
+ .change(function (this) {
+ onChange((this as HTMLInputElement).checked);
+ })
+ .attr('alt', 'Expand')
+ .attr('title', 'Expand')
+ .appendTo(div);
+
+ // Collapse s:f:* or s:f:t:* or s:f:t:c by default.
+ if (n.query.level > rootQueryLevel && n.query.level > parentLevel) {
+ onChange(false);
+ } else {
+ checkbox.prop('checked', true); // (does not fire onChange)
+ }
}
-
- const href = `?${worker ? 'worker&' : ''}${debug ? 'debug&' : ''}q=${nameEncoded}`;
+ const runtext = isLeaf ? 'Run case' : 'Run subtree';
$('<button>')
- .addClass('noderun')
- .attr('alt', 'Run subtree')
- .attr('title', 'Run subtree')
+ .addClass(isLeaf ? 'leafrun' : 'subtreerun')
+ .attr('alt', runtext)
+ .attr('title', runtext)
.on('click', async () => {
await runSubtree();
updateJSON();
@@ -156,35 +169,73 @@ function makeTreeNodeHeaderHTML(
.attr('alt', 'Open')
.attr('title', 'Open')
.appendTo(div);
- const nodetitle = $('<div>')
- .addClass('nodetitle')
- .appendTo(div);
- $('<span>')
+ const nodetitle = $('<div>').addClass('nodetitle').appendTo(div);
+ const nodename = $('<span>')
.addClass('nodename')
- .html(nameHTML)
+ .text(n.readableRelativeName)
.appendTo(nodetitle);
- if (description) {
+ if ('run' in n) {
+ nodename.addClass('leafname');
+ }
+ $('<input>')
+ .attr('type', 'text')
+ .prop('readonly', true)
+ .addClass('nodequery')
+ .val(n.query.toString())
+ .appendTo(nodetitle);
+ if ('description' in n && n.description) {
$('<div>')
.addClass('nodedescription')
- .html(description.replace(/\n/g, '<br>'))
+ .html(n.description.replace(/\n\n/g, '<br><br>'))
.appendTo(nodetitle);
}
return div[0];
}
function updateJSON(): void {
- resultsJSON.textContent = log.asJSON(2);
+ resultsJSON.textContent = logger.asJSON(2);
}
+let rootQueryLevel: TestQueryLevel = 1;
+
(async () => {
- const loader = new TestLoader();
+ const loader = new DefaultTestFileLoader();
- // TODO: everything after this point is very similar across the three runtimes.
// TODO: start populating page before waiting for everything to load?
- const files = await loader.loadTestsFromQuery(window.location.search);
- const tree = treeFromFilterResults(log, files);
+ const qs = new URLSearchParams(window.location.search).getAll('q');
+ if (qs.length === 0) {
+ qs.push('webgpu:*');
+ }
- const runSubtree = makeSubtreeChildrenHTML(resultsVis, tree.children!);
+ // Update the URL bar to match the exact current options.
+ {
+ let url = window.location.protocol + '//' + window.location.host + window.location.pathname;
+ url +=
+ '?' +
+ new URLSearchParams([
+ ['runnow', runnow ? '1' : '0'],
+ ['worker', worker ? '1' : '0'],
+ ['debug', debug ? '1' : '0'],
+ ]).toString() +
+ '&' +
+ qs.map(q => 'q=' + q).join('&');
+ window.history.replaceState(null, '', url);
+ }
+
+ assert(qs.length === 1, 'currently, there must be exactly one ?q=');
+ const rootQuery = parseQuery(qs[0]);
+ rootQueryLevel = rootQuery.level;
+ const tree = await loader.loadTree(rootQuery);
+
+ tree.dissolveLevelBoundaries();
+
+ const [el, runSubtree] = makeSubtreeHTML(tree.root, 1);
+ resultsVis.append(el);
+
+ $('#expandall').change(function (this) {
+ const checked = (this as HTMLInputElement).checked;
+ $('.collapsebtn').prop('checked', checked).trigger('change');
+ });
if (runnow) {
runSubtree();
diff --git a/chromium/third_party/webgpu-cts/src/src/common/runtime/wpt.ts b/chromium/third_party/webgpu-cts/src/src/common/runtime/wpt.ts
index bc2ac7b8f06..5600b7e9cd3 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/runtime/wpt.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/runtime/wpt.ts
@@ -1,7 +1,9 @@
-import { TestLoader } from '../framework/loader.js';
-import { LiveTestCaseResult, Logger } from '../framework/logger.js';
-import { makeQueryString } from '../framework/url_query.js';
+import { DefaultTestFileLoader } from '../framework/file_loader.js';
+import { Logger } from '../framework/logging/logger.js';
+import { parseQuery } from '../framework/query/parseQuery.js';
+import { TestTreeLeaf } from '../framework/tree.js';
import { AsyncMutex } from '../framework/util/async_mutex.js';
+import { assert } from '../framework/util/util.js';
import { optionEnabled } from './helper/options.js';
import { TestWorker } from './helper/test_worker.js';
@@ -15,51 +17,48 @@ declare interface WptTestObject {
declare function async_test(f: (this: WptTestObject) => Promise<void>, name: string): void;
(async () => {
- const loader = new TestLoader();
- const files = await loader.loadTestsFromQuery(window.location.search);
+ const loader = new DefaultTestFileLoader();
+ const qs = new URLSearchParams(window.location.search).getAll('q');
+ assert(qs.length === 1, 'currently, there must be exactly one ?q=');
+ const testcases = await loader.loadCases(parseQuery(qs[0]));
- const worker = optionEnabled('worker') ? new TestWorker() : undefined;
+ await addWPTTests(testcases);
+})();
+
+// Note: `async_test`s must ALL be added within the same task. This function *must not* be async.
+function addWPTTests(testcases: IterableIterator<TestTreeLeaf>): Promise<Logger> {
+ const worker = optionEnabled('worker') ? new TestWorker(false) : undefined;
- const log = new Logger();
+ const log = new Logger(false);
const mutex = new AsyncMutex();
const running: Array<Promise<void>> = [];
- for (const f of files) {
- if (!('g' in f.spec)) {
- continue;
- }
+ for (const testcase of testcases) {
+ const name = testcase.query.toString();
+ const wpt_fn = function (this: WptTestObject): Promise<void> {
+ const p = mutex.with(async () => {
+ const [rec, res] = log.record(name);
+ if (worker) {
+ await worker.run(rec, name);
+ } else {
+ await testcase.run(rec);
+ }
- const [rec] = log.record(f.id);
- for (const t of f.spec.g.iterate(rec)) {
- const name = makeQueryString(f.id, t.id);
-
- // Note: apparently, async_tests must ALL be added within the same task.
- async_test(function(this: WptTestObject): Promise<void> {
- const p = mutex.with(async () => {
- let r: LiveTestCaseResult;
- if (worker) {
- r = await worker.run(name);
- t.injectResult(r);
- } else {
- r = await t.run();
+ this.step(() => {
+ // Unfortunately, it seems not possible to surface any logs for warn/skip.
+ if (res.status === 'fail') {
+ throw (res.logs || []).map(s => s.toJSON()).join('\n\n');
}
-
- this.step(() => {
- // Unfortunately, it seems not possible to surface any logs for warn/skip.
- if (r.status === 'fail') {
- throw (r.logs || []).map(s => s.toJSON()).join('\n\n');
- }
- });
- this.done();
});
+ this.done();
+ });
- running.push(p);
- return p;
- }, name);
- }
+ running.push(p);
+ return p;
+ };
+
+ async_test(wpt_fn, name);
}
- await Promise.all(running);
- const resultsElem = document.getElementById('results') as HTMLElement;
- resultsElem.textContent = log.asJSON(2);
-})();
+ return Promise.all(running).then(() => log);
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/templates/cts.html b/chromium/third_party/webgpu-cts/src/src/common/templates/cts.html
index a4169922466..3c37875fe3b 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/templates/cts.html
+++ b/chromium/third_party/webgpu-cts/src/src/common/templates/cts.html
@@ -25,24 +25,4 @@
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
-<style>
-#results {
- font-family: monospace;
- width: 100%;
- height: 15em;
-}
-
-/* Test Name column */
-#results > tbody > tr > td:nth-child(2) {
- word-break: break-word;
-}
-
-/* Message column */
-#results > tbody > tr > td:nth-child(3) {
- white-space: pre-wrap;
- word-break: break-word;
-}
-</style>
-
-<textarea id=results></textarea>
<script type=module src=/webgpu/common/runtime/wpt.js></script>
diff --git a/chromium/third_party/webgpu-cts/src/src/common/tools/.eslintrc.json b/chromium/third_party/webgpu-cts/src/src/common/tools/.eslintrc.json
new file mode 100644
index 00000000000..0a79eae4c5b
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/common/tools/.eslintrc.json
@@ -0,0 +1,8 @@
+{
+ "rules": {
+ "no-console": "off",
+ "no-process-exit": "off",
+ "node/no-unpublished-require": "off",
+ "@typescript-eslint/no-var-requires": "off"
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/tools/crawl.ts b/chromium/third_party/webgpu-cts/src/src/common/tools/crawl.ts
index d6d3edbe4ce..6e7ffc61fc6 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/tools/crawl.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/tools/crawl.ts
@@ -2,59 +2,58 @@
// This crawls the file tree under src/suites/${suite} to generate a (non-hierarchical) static
// listing file that can then be used in the browser to load the modules containing the tests.
-// tslint:disable: no-console
-
import * as fs from 'fs';
import * as path from 'path';
-const fg = require('fast-glob');
+import { SpecFile } from '../framework/file_loader.js';
+import { TestSuiteListingEntry, TestSuiteListing } from '../framework/test_suite_listing.js';
+import { assert, unreachable } from '../framework/util/util.js';
-import { TestSuiteListingEntry } from '../framework/listing.js';
-import { TestSpec } from '../framework/loader.js';
-import { assert } from '../framework/util/util.js';
+const fg = require('fast-glob');
-const specSuffix = '.spec.ts';
+const specFileSuffix = '.spec.ts';
export async function crawl(suite: string): Promise<TestSuiteListingEntry[]> {
- const specDir = 'src/' + suite;
- if (!fs.existsSync(specDir)) {
- console.error(`Could not find ${specDir}`);
+ const suiteDir = 'src/' + suite;
+ if (!fs.existsSync(suiteDir)) {
+ console.error(`Could not find ${suiteDir}`);
process.exit(1);
}
- const specFiles = await fg(`${specDir}/**/{README.txt,*${specSuffix}}`, { onlyFiles: true });
- specFiles.sort();
+ const glob = `${suiteDir}/**/{README.txt,*${specFileSuffix}}`;
+ const filesToEnumerate: string[] = await fg(glob, { onlyFiles: true });
+ filesToEnumerate.sort();
+
+ const entries: TestSuiteListingEntry[] = [];
+ for (const file of filesToEnumerate) {
+ const f = file.substring((suiteDir + '/').length); // Suite-relative file path
+ if (f.endsWith(specFileSuffix)) {
+ const filepathWithoutExtension = f.substring(0, f.length - specFileSuffix.length);
+ const filename = `../../../${suiteDir}/${filepathWithoutExtension}.spec.js`;
- const groups: TestSuiteListingEntry[] = [];
- for (const file of specFiles) {
- const f = file.substring((specDir + '/').length);
- if (f.endsWith(specSuffix)) {
- const testPath = f.substring(0, f.length - specSuffix.length);
- const filename = `../../../${specDir}/${testPath}.spec.js`;
- const mod = (await import(filename)) as TestSpec;
+ const mod = (await import(filename)) as SpecFile;
assert(mod.description !== undefined, 'Test spec file missing description: ' + filename);
assert(mod.g !== undefined, 'Test spec file missing TestGroup definition: ' + filename);
- groups.push({
- path: testPath,
- description: mod.description.trim(),
- });
+
+ mod.g.checkCaseNamesAndDuplicates();
+
+ const path = filepathWithoutExtension.split('/');
+ entries.push({ file: path, description: mod.description.trim() });
} else if (path.basename(file) === 'README.txt') {
- const group = f.substring(0, f.length - 'README.txt'.length);
- const description = fs.readFileSync(file, 'utf8').trim();
- groups.push({
- path: group,
- description,
- });
+ const filepathWithoutExtension = f.substring(0, f.length - '/README.txt'.length);
+ const readme = fs.readFileSync(file, 'utf8').trim();
+
+ const path = filepathWithoutExtension ? filepathWithoutExtension.split('/') : [];
+ entries.push({ file: path, readme });
} else {
- console.error('Unrecognized file: ' + file);
- process.exit(1);
+ unreachable(`glob ${glob} matched an unrecognized filename ${file}`);
}
}
- return groups;
+ return entries;
}
-export function makeListing(filename: string): Promise<TestSuiteListingEntry[]> {
+export function makeListing(filename: string): Promise<TestSuiteListing> {
const suite = path.basename(path.dirname(filename));
return crawl(suite);
}
diff --git a/chromium/third_party/webgpu-cts/src/src/common/tools/gen_listings.ts b/chromium/third_party/webgpu-cts/src/src/common/tools/gen_listings.ts
index f24cfd45c7d..0aff1e4f505 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/tools/gen_listings.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/tools/gen_listings.ts
@@ -1,5 +1,3 @@
-// tslint:disable: no-console
-
import * as fs from 'fs';
import * as path from 'path';
import * as process from 'process';
@@ -38,6 +36,7 @@ export const listing = ${JSON.stringify(listing, undefined, 2)};
);
try {
fs.unlinkSync(outFile + '.map');
+ /* eslint-disable-next-line no-empty */
} catch (ex) {}
}
})();
diff --git a/chromium/third_party/webgpu-cts/src/src/common/tools/gen_wpt_cts_html.ts b/chromium/third_party/webgpu-cts/src/src/common/tools/gen_wpt_cts_html.ts
index c669871a352..4f74f9b15b9 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/tools/gen_wpt_cts_html.ts
+++ b/chromium/third_party/webgpu-cts/src/src/common/tools/gen_wpt_cts_html.ts
@@ -1,11 +1,8 @@
-// tslint:disable: no-console
-
import { promises as fs } from 'fs';
-import { listing } from '../../webgpu/listing.js';
-import { generateMinimalQueryList } from '../framework/generate_minimal_query_list.js';
-import { TestSuiteListingEntry } from '../framework/listing.js';
-import { TestLoader } from '../framework/loader.js';
+import { DefaultTestFileLoader } from '../framework/file_loader.js';
+import { TestQueryMultiTest, TestQueryMultiFile } from '../framework/query/query.js';
+import { assert } from '../framework/util/util.js';
function printUsageAndExit(rc: number): void {
console.error(`\
@@ -48,11 +45,11 @@ const [
(async () => {
if (process.argv.length === 4) {
- const entries = (await listing) as TestSuiteListingEntry[];
+ const entries = await (await import('../../webgpu/listing.js')).listing;
const lines = entries
// Exclude READMEs.
- .filter(l => l.path.length !== 0 && !l.path.endsWith('/'))
- .map(l => '?q=webgpu:' + l.path);
+ .filter(l => !('readme' in l))
+ .map(l => '?q=' + new TestQueryMultiTest('webgpu', l.file, []).toString());
await generateFile(lines);
} else {
// Prefixes sorted from longest to shortest
@@ -60,9 +57,9 @@ const [
.split('\n')
.filter(a => a.length)
.sort((a, b) => b.length - a.length);
- const expectationLines = (await fs.readFile(expectationsFile, 'utf8'))
- .split('\n')
- .filter(l => l.length);
+ const expectationLines = new Set(
+ (await fs.readFile(expectationsFile, 'utf8')).split('\n').filter(l => l.length)
+ );
const expectations: Map<string, string[]> = new Map();
for (const prefix of argsPrefixes) {
@@ -78,17 +75,28 @@ const [
continue expLoop;
}
}
- throw new Error('All input lines must start with one of the prefixes. ' + exp);
+ console.log('note: ignored expectation: ' + exp);
}
- const loader = new TestLoader();
- const files = Array.from(await loader.loadTestsFromCmdLine([suite + ':']));
-
- const lines = [];
+ const loader = new DefaultTestFileLoader();
+ const lines: Array<string | undefined> = [];
for (const prefix of argsPrefixes) {
- lines.push(undefined);
- for (const q of await generateMinimalQueryList(files, expectations.get(prefix)!)) {
- lines.push(prefix + q);
+ const rootQuery = new TestQueryMultiFile(suite, []);
+ const tree = await loader.loadTree(rootQuery, expectations.get(prefix)!);
+
+ lines.push(undefined); // output blank line between prefixes
+ for (const q of tree.iterateCollapsedQueries()) {
+ const urlQueryString = prefix + q.toString(); // "?worker=0&q=..."
+ // Check for a safe-ish path length limit. Filename must be <= 255, and on Windows the whole
+ // path must be <= 259. Leave room for e.g.:
+ // 'c:\b\s\w\xxxxxxxx\layout-test-results\external\wpt\webgpu\cts_worker=0_q=...-actual.txt'
+ assert(
+ urlQueryString.length < 185,
+ 'Generated test variant would produce too-long -actual.txt filename. \
+Try broadening suppressions to avoid long test variant names. ' +
+ urlQueryString
+ );
+ lines.push(urlQueryString);
}
}
await generateFile(lines);
diff --git a/chromium/third_party/webgpu-cts/src/src/common/tools/setup-ts-in-node.js b/chromium/third_party/webgpu-cts/src/src/common/tools/setup-ts-in-node.js
index 0616dab35db..d5f773140e6 100644
--- a/chromium/third_party/webgpu-cts/src/src/common/tools/setup-ts-in-node.js
+++ b/chromium/third_party/webgpu-cts/src/src/common/tools/setup-ts-in-node.js
@@ -4,7 +4,7 @@ require('ts-node').register({
module: 'commonjs',
},
transpileOnly: true,
-})
+});
// Redirect imports of .js files to .ts files
const Module = require('module');
diff --git a/chromium/third_party/webgpu-cts/src/src/demo/README.txt b/chromium/third_party/webgpu-cts/src/src/demo/README.txt
new file mode 100644
index 00000000000..3b5654080ec
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/demo/README.txt
@@ -0,0 +1 @@
+Demo test suite for manually testing test runners.
diff --git a/chromium/third_party/webgpu-cts/src/src/demo/a.spec.ts b/chromium/third_party/webgpu-cts/src/src/demo/a.spec.ts
new file mode 100644
index 00000000000..82160c3c1a5
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/demo/a.spec.ts
@@ -0,0 +1,6 @@
+export const description = 'Description for a.spec.ts';
+
+import { makeTestGroup } from '../common/framework/test_group.js';
+import { UnitTest } from '../unittests/unit_test.js';
+
+export const g = makeTestGroup(UnitTest);
diff --git a/chromium/third_party/webgpu-cts/src/src/demo/a/README.txt b/chromium/third_party/webgpu-cts/src/src/demo/a/README.txt
new file mode 100644
index 00000000000..62c18e3cc36
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/demo/a/README.txt
@@ -0,0 +1 @@
+README for a/
diff --git a/chromium/third_party/webgpu-cts/src/src/demo/a/b.spec.ts b/chromium/third_party/webgpu-cts/src/src/demo/a/b.spec.ts
new file mode 100644
index 00000000000..7e066591dd5
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/demo/a/b.spec.ts
@@ -0,0 +1,6 @@
+export const description = 'Description for b.spec.ts';
+
+import { makeTestGroup } from '../../common/framework/test_group.js';
+import { UnitTest } from '../../unittests/unit_test.js';
+
+export const g = makeTestGroup(UnitTest);
diff --git a/chromium/third_party/webgpu-cts/src/src/demo/a/b/README.txt b/chromium/third_party/webgpu-cts/src/src/demo/a/b/README.txt
new file mode 100644
index 00000000000..eed2f44bbd7
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/demo/a/b/README.txt
@@ -0,0 +1 @@
+README for a/b/
diff --git a/chromium/third_party/webgpu-cts/src/src/demo/a/b/c.spec.ts b/chromium/third_party/webgpu-cts/src/src/demo/a/b/c.spec.ts
new file mode 100644
index 00000000000..5358a11c381
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/demo/a/b/c.spec.ts
@@ -0,0 +1,39 @@
+export const description = 'Description for c.spec.ts';
+
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { unreachable } from '../../../common/framework/util/util.js';
+import { UnitTest } from '../../../unittests/unit_test.js';
+
+export const g = makeTestGroup(UnitTest);
+
+g.test('f').fn(() => {});
+
+g.test('f,g').fn(() => {});
+
+g.test('f,g,h')
+ .params([{}, { x: 0 }, { x: 0, y: 0 }])
+ .fn(() => {});
+
+g.test('case_depth_2_in_single_child_test')
+ .params([{ x: 0, y: 0 }])
+ .fn(() => {});
+
+g.test('statuses,debug').fn(t => {
+ t.debug('debug');
+});
+
+g.test('statuses,skip').fn(t => {
+ t.skip('skip');
+});
+
+g.test('statuses,warn').fn(t => {
+ t.warn('warn');
+});
+
+g.test('statuses,fail').fn(t => {
+ t.fail('fail');
+});
+
+g.test('statuses,throw').fn(() => {
+ unreachable('unreachable');
+});
diff --git a/chromium/third_party/webgpu-cts/src/src/demo/a/b/d.spec.ts b/chromium/third_party/webgpu-cts/src/src/demo/a/b/d.spec.ts
new file mode 100644
index 00000000000..1412e53baf1
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/demo/a/b/d.spec.ts
@@ -0,0 +1,8 @@
+export const description = 'Description for d.spec.ts';
+
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { UnitTest } from '../../../unittests/unit_test.js';
+
+export const g = makeTestGroup(UnitTest);
+
+g.test('test_depth_2,in_single_child_file').fn(() => {});
diff --git a/chromium/third_party/webgpu-cts/src/src/demo/file_depth_2/in_single_child_dir/r.spec.ts b/chromium/third_party/webgpu-cts/src/src/demo/file_depth_2/in_single_child_dir/r.spec.ts
new file mode 100644
index 00000000000..2a1adc6f507
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/demo/file_depth_2/in_single_child_dir/r.spec.ts
@@ -0,0 +1,6 @@
+export const description = 'Description for r.spec.ts';
+
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { UnitTest } from '../../../unittests/unit_test.js';
+
+export const g = makeTestGroup(UnitTest);
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/async_mutex.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/async_mutex.spec.ts
index e663bd40224..dc1bb0d1657 100644
--- a/chromium/third_party/webgpu-cts/src/src/unittests/async_mutex.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/async_mutex.spec.ts
@@ -2,27 +2,30 @@ export const description = `
Tests for AsyncMutex.
`;
-import { TestGroup } from '../common/framework/test_group.js';
+import { makeTestGroup } from '../common/framework/test_group.js';
import { AsyncMutex } from '../common/framework/util/async_mutex.js';
import { objectEquals } from '../common/framework/util/util.js';
import { UnitTest } from './unit_test.js';
-export const g = new TestGroup(UnitTest);
+export const g = makeTestGroup(UnitTest);
-g.test('basic', async t => {
+/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
+g.test('basic').fn(async t => {
const mutex = new AsyncMutex();
await mutex.with(async () => {});
});
-g.test('serial', async t => {
+/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
+g.test('serial').fn(async t => {
const mutex = new AsyncMutex();
await mutex.with(async () => {});
await mutex.with(async () => {});
await mutex.with(async () => {});
});
-g.test('parallel', async t => {
+/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
+g.test('parallel').fn(async t => {
const mutex = new AsyncMutex();
await Promise.all([
mutex.with(async () => {}),
@@ -31,7 +34,7 @@ g.test('parallel', async t => {
]);
});
-g.test('parallel/many', async t => {
+g.test('parallel,many').fn(async t => {
const mutex = new AsyncMutex();
const actual: number[] = [];
const expected = [];
@@ -45,13 +48,13 @@ g.test('parallel/many', async t => {
t.expect(objectEquals(actual, expected));
});
-g.test('return', async t => {
+g.test('return').fn(async t => {
const mutex = new AsyncMutex();
const ret = await mutex.with(async () => 123);
t.expect(ret === 123);
});
-g.test('return/parallel', async t => {
+g.test('return,parallel').fn(async t => {
const mutex = new AsyncMutex();
const ret = await Promise.all([
mutex.with(async () => 1),
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/basic.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/basic.spec.ts
index f8cb768b641..fc4a75d7bbf 100644
--- a/chromium/third_party/webgpu-cts/src/src/unittests/basic.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/basic.spec.ts
@@ -2,28 +2,36 @@ export const description = `
Basic unit tests for test framework.
`;
-import { TestGroup } from '../common/framework/test_group.js';
+import { makeTestGroup } from '../common/framework/test_group.js';
import { UnitTest } from './unit_test.js';
-export const g = new TestGroup(UnitTest);
-
-g.test('test/sync', t => {});
-
-g.test('test/async', async t => {});
-
-g.test('testp/sync', t => {
- t.debug(JSON.stringify(t.params));
-}).params([{}]);
-
-g.test('testp/async', async t => {
- t.debug(JSON.stringify(t.params));
-}).params([{}]);
-
-g.test('testp/private', t => {
- const { a, b, _result } = t.params;
- t.expect(a + b === _result);
-}).params([
- { a: 1, b: 2, _result: 3 }, //
- { a: 4, b: -3, _result: 1 },
-]);
+export const g = makeTestGroup(UnitTest);
+
+/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
+g.test('test,sync').fn(t => {});
+
+/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
+g.test('test,async').fn(async t => {});
+
+g.test('test_with_params,sync')
+ .params([{}])
+ .fn(t => {
+ t.debug(JSON.stringify(t.params));
+ });
+
+g.test('test_with_params,async')
+ .params([{}])
+ .fn(async t => {
+ t.debug(JSON.stringify(t.params));
+ });
+
+g.test('test_with_params,private_params')
+ .params([
+ { a: 1, b: 2, _result: 3 }, //
+ { a: 4, b: -3, _result: 1 },
+ ])
+ .fn(t => {
+ const { a, b, _result } = t.params;
+ t.expect(a + b === _result);
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/getStackTrace.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/getStackTrace.spec.ts
index 2966e640f7f..532a10ce7b0 100644
--- a/chromium/third_party/webgpu-cts/src/src/unittests/getStackTrace.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/getStackTrace.spec.ts
@@ -2,51 +2,38 @@ export const description = `
Tests for getStackTrace.
`;
-import { TestGroup } from '../common/framework/test_group.js';
-import { getStackTrace } from '../common/framework/util/stack.js';
+import { makeTestGroup } from '../common/framework/test_group.js';
+import { extractImportantStackTrace } from '../common/framework/util/stack.js';
import { UnitTest } from './unit_test.js';
-export const g = new TestGroup(UnitTest);
+export const g = makeTestGroup(UnitTest);
-g.test('stacks', t => {
- const lines: number = t.params._expectedLines;
-
- const ex = new Error();
- ex.stack = t.params._stack;
- t.expect(ex.stack === t.params._stack);
- const stringified = getStackTrace(ex);
- const parts = stringified.split('\n');
-
- t.expect(parts.length === lines);
- const fst = parts[0];
- const lst = parts[parts.length - 1];
- t.expect(fst.indexOf('/unittests/') !== -1 || fst.indexOf('\\unittests\\') !== -1);
- t.expect(lst.indexOf('/unittests/') !== -1 || lst.indexOf('\\unittests\\') !== -1);
-}).params([
- {
- case: 'node_fail',
- _expectedLines: 1,
- _stack: `Error:
+g.test('stacks')
+ .params([
+ {
+ case: 'node_fail',
+ _expectedLines: 3,
+ _stack: `Error:
at CaseRecorder.fail (/Users/kainino/src/cts/src/common/framework/logger.ts:99:30)
at RunCaseSpecific.exports.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/logger.spec.ts:80:7)
at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)
at processTicksAndRejections (internal/process/task_queues.js:86:5)`,
- },
- {
- // TODO: make sure this test case actually matches what happens on windows
- case: 'node_fail_backslash',
- _expectedLines: 1,
- _stack: `Error:
+ },
+ {
+ // TODO: make sure this test case actually matches what happens on windows
+ case: 'node_fail_backslash',
+ _expectedLines: 3,
+ _stack: `Error:
at CaseRecorder.fail (C:\\Users\\kainino\\src\\cts\\src\\common\\framework\\logger.ts:99:30)
at RunCaseSpecific.exports.g.test.t [as fn] (C:\\Users\\kainino\\src\\cts\\src\\unittests\\logger.spec.ts:80:7)
at RunCaseSpecific.run (C:\\Users\\kainino\\src\\cts\\src\\common\\framework\\test_group.ts:121:18)
at processTicksAndRejections (internal\\process\\task_queues.js:86:5)`,
- },
- {
- case: 'node_fail_processTicksAndRejections',
- _expectedLines: 3,
- _stack: `Error: expectation had no effect: suite1:foo:
+ },
+ {
+ case: 'node_fail_processTicksAndRejections',
+ _expectedLines: 5,
+ _stack: `Error: expectation had no effect: suite1:foo:
at Object.generateMinimalQueryList (/Users/kainino/src/cts/src/common/framework/generate_minimal_query_list.ts:72:24)
at testGenerateMinimalQueryList (/Users/kainino/src/cts/src/unittests/loading.spec.ts:289:25)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
@@ -55,64 +42,64 @@ g.test('stacks', t => {
at /Users/kainino/src/cts/src/common/runtime/cmdline.ts:62:25
at async Promise.all (index 29)
at /Users/kainino/src/cts/src/common/runtime/cmdline.ts:78:5`,
- },
- {
- case: 'node_throw',
- _expectedLines: 1,
- _stack: `Error: hello
+ },
+ {
+ case: 'node_throw',
+ _expectedLines: 2,
+ _stack: `Error: hello
at RunCaseSpecific.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/test_group.spec.ts:51:11)
at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)
at processTicksAndRejections (internal/process/task_queues.js:86:5)`,
- },
- {
- case: 'firefox_fail',
- _expectedLines: 1,
- _stack: `fail@http://localhost:8080/out/common/framework/logger.js:104:30
+ },
+ {
+ case: 'firefox_fail',
+ _expectedLines: 3,
+ _stack: `fail@http://localhost:8080/out/common/framework/logger.js:104:30
expect@http://localhost:8080/out/common/framework/default_fixture.js:59:16
@http://localhost:8080/out/unittests/util.spec.js:35:5
run@http://localhost:8080/out/common/framework/test_group.js:119:18`,
- },
- {
- case: 'firefox_throw',
- _expectedLines: 1,
- _stack: `@http://localhost:8080/out/unittests/test_group.spec.js:48:11
+ },
+ {
+ case: 'firefox_throw',
+ _expectedLines: 1,
+ _stack: `@http://localhost:8080/out/unittests/test_group.spec.js:48:11
run@http://localhost:8080/out/common/framework/test_group.js:119:18`,
- },
- {
- case: 'safari_fail',
- _expectedLines: 1,
- _stack: `fail@http://localhost:8080/out/common/framework/logger.js:104:39
+ },
+ {
+ case: 'safari_fail',
+ _expectedLines: 3,
+ _stack: `fail@http://localhost:8080/out/common/framework/logger.js:104:39
expect@http://localhost:8080/out/common/framework/default_fixture.js:59:20
http://localhost:8080/out/unittests/util.spec.js:35:11
http://localhost:8080/out/common/framework/test_group.js:119:20
asyncFunctionResume@[native code]
[native code]
promiseReactionJob@[native code]`,
- },
- {
- case: 'safari_throw',
- _expectedLines: 1,
- _stack: `http://localhost:8080/out/unittests/test_group.spec.js:48:20
+ },
+ {
+ case: 'safari_throw',
+ _expectedLines: 1,
+ _stack: `http://localhost:8080/out/unittests/test_group.spec.js:48:20
http://localhost:8080/out/common/framework/test_group.js:119:20
asyncFunctionResume@[native code]
[native code]
promiseReactionJob@[native code]`,
- },
- {
- case: 'chrome_fail',
- _expectedLines: 1,
- _stack: `Error
+ },
+ {
+ case: 'chrome_fail',
+ _expectedLines: 4,
+ _stack: `Error
at CaseRecorder.fail (http://localhost:8080/out/common/framework/logger.js:104:30)
at DefaultFixture.expect (http://localhost:8080/out/common/framework/default_fixture.js:59:16)
at RunCaseSpecific.fn (http://localhost:8080/out/unittests/util.spec.js:35:5)
at RunCaseSpecific.run (http://localhost:8080/out/common/framework/test_group.js:119:18)
at async runCase (http://localhost:8080/out/common/runtime/standalone.js:37:17)
at async http://localhost:8080/out/common/runtime/standalone.js:102:7`,
- },
- {
- case: 'chrome_throw',
- _expectedLines: 5,
- _stack: `Error: hello
+ },
+ {
+ case: 'chrome_throw',
+ _expectedLines: 6,
+ _stack: `Error: hello
at RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:48:11)
at RunCaseSpecific.run (http://localhost:8080/out/common/framework/test_group.js:119:18)"
at async Promise.all (index 0)
@@ -121,11 +108,11 @@ promiseReactionJob@[native code]`,
at async RunCaseSpecific.run (http://localhost:8080/out/common/framework/test_group.js:119:7)
at async runCase (http://localhost:8080/out/common/runtime/standalone.js:37:17)
at async http://localhost:8080/out/common/runtime/standalone.js:102:7`,
- },
- {
- case: 'multiple_lines',
- _expectedLines: 7,
- _stack: `Error: hello
+ },
+ {
+ case: 'multiple_lines',
+ _expectedLines: 8,
+ _stack: `Error: hello
at RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:48:11)
at RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:48:11)
at RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:48:11)
@@ -136,5 +123,16 @@ promiseReactionJob@[native code]`,
at async RunCaseSpecific.run (http://localhost:8080/out/common/framework/test_group.js:119:7)
at async runCase (http://localhost:8080/out/common/runtime/standalone.js:37:17)
at async http://localhost:8080/out/common/runtime/standalone.js:102:7`,
- },
-]);
+ },
+ ])
+ .fn(t => {
+ const ex = new Error();
+ ex.stack = t.params._stack;
+ t.expect(ex.stack === t.params._stack);
+ const stringified = extractImportantStackTrace(ex);
+ const parts = stringified.split('\n');
+
+ t.expect(parts.length === t.params._expectedLines);
+ const last = parts[parts.length - 1];
+ t.expect(last.indexOf('/unittests/') !== -1 || last.indexOf('\\unittests\\') !== -1);
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/listing.ts b/chromium/third_party/webgpu-cts/src/src/unittests/listing.ts
index ba26ed77bd4..2d6f4cf8ecf 100644
--- a/chromium/third_party/webgpu-cts/src/src/unittests/listing.ts
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/listing.ts
@@ -1,4 +1,4 @@
-import { TestSuiteListing } from '../common/framework/listing.js';
+import { TestSuiteListing } from '../common/framework/test_suite_listing.js';
import { makeListing } from '../common/tools/crawl.js';
export const listing: Promise<TestSuiteListing> = makeListing(__filename);
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/loaders_and_trees.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/loaders_and_trees.spec.ts
new file mode 100644
index 00000000000..5ca7e7e5d3b
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/loaders_and_trees.spec.ts
@@ -0,0 +1,360 @@
+export const description = `
+Tests for queries/filtering, loading, and running.
+`;
+
+import { TestFileLoader, SpecFile } from '../common/framework/file_loader.js';
+import { Logger } from '../common/framework/logging/logger.js';
+import { Status } from '../common/framework/logging/result.js';
+import { parseQuery } from '../common/framework/query/parseQuery.js';
+import {
+ TestQuery,
+ TestQuerySingleCase,
+ TestQueryMultiCase,
+ TestQueryMultiTest,
+ TestQueryMultiFile,
+} from '../common/framework/query/query.js';
+import { makeTestGroup, makeTestGroupForUnitTesting } from '../common/framework/test_group.js';
+import { TestSuiteListing, TestSuiteListingEntry } from '../common/framework/test_suite_listing.js';
+import { TestTreeLeaf } from '../common/framework/tree.js';
+import { assert, objectEquals } from '../common/framework/util/util.js';
+
+import { UnitTest } from './unit_test.js';
+
+const listingData: { [k: string]: TestSuiteListingEntry[] } = {
+ suite1: [
+ { file: [], readme: 'desc 1a' },
+ { file: ['foo'], description: 'desc 1b' },
+ { file: ['bar'], readme: 'desc 1c' },
+ { file: ['bar', 'buzz', 'buzz'], description: 'desc 1d' },
+ { file: ['baz'], description: 'desc 1e' },
+ ],
+ suite2: [
+ { file: [], readme: 'desc 2a' },
+ { file: ['foof'], description: 'desc 2b' },
+ ],
+};
+
+const specsData: { [k: string]: SpecFile } = {
+ 'suite1/foo.spec.js': {
+ description: 'desc 1b',
+ g: (() => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('hello').fn(() => {});
+ g.test('bonjour').fn(() => {});
+ g.test('hola').fn(() => {});
+ return g;
+ })(),
+ },
+ 'suite1/bar/biz.spec.js': {
+ description: 'desc 1f',
+ g: makeTestGroupForUnitTesting(UnitTest),
+ },
+ 'suite1/bar/bez.spec.js': {
+ description: 'desc 1g',
+ g: makeTestGroupForUnitTesting(UnitTest),
+ },
+ 'suite1/bar/buzz/buzz.spec.js': {
+ description: 'desc 1d',
+ g: (() => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('zap').fn(() => {});
+ return g;
+ })(),
+ },
+ 'suite1/baz.spec.js': {
+ description: 'desc 1e',
+ g: (() => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('wye')
+ .params([{}, { x: 1 }])
+ .fn(() => {});
+ g.test('zed')
+ .params([
+ { a: 1, b: 2, _c: 0 },
+ { b: 3, a: 1, _c: 0 },
+ ])
+ .fn(() => {});
+ return g;
+ })(),
+ },
+ 'suite2/foof.spec.js': {
+ description: 'desc 2b',
+ g: (() => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('blah').fn(t => {
+ t.debug('OK');
+ });
+ g.test('bleh')
+ .params([{ a: 1 }])
+ .fn(t => {
+ t.debug('OK');
+ t.debug('OK');
+ });
+ g.test('bluh,a').fn(t => {
+ t.fail('bye');
+ });
+ return g;
+ })(),
+ },
+};
+
+class FakeTestFileLoader extends TestFileLoader {
+ async listing(suite: string): Promise<TestSuiteListing> {
+ return listingData[suite];
+ }
+
+ async import(path: string): Promise<SpecFile> {
+ assert(path in specsData, '[test] mock file ' + path + ' does not exist');
+ return specsData[path];
+ }
+}
+
+class LoadingTest extends UnitTest {
+ static readonly loader = new FakeTestFileLoader();
+
+ async load(query: string): Promise<TestTreeLeaf[]> {
+ return Array.from(await LoadingTest.loader.loadCases(parseQuery(query)));
+ }
+
+ async loadNames(query: string): Promise<string[]> {
+ return (await this.load(query)).map(c => c.query.toString());
+ }
+}
+
+export const g = makeTestGroup(LoadingTest);
+
+g.test('suite').fn(async t => {
+ t.shouldReject('Error', t.load('suite1'));
+ t.shouldReject('Error', t.load('suite1:'));
+});
+
+g.test('group').fn(async t => {
+ t.expect((await t.load('suite1:*')).length === 8);
+ t.expect((await t.load('suite1:foo,*')).length === 3); // x:foo,* matches x:foo:
+ t.expect((await t.load('suite1:bar,*')).length === 1);
+ t.expect((await t.load('suite1:bar,buzz,buzz,*')).length === 1);
+
+ t.shouldReject('Error', t.load('suite1:f*'));
+
+ {
+ const s = new TestQueryMultiFile('suite1', ['bar', 'buzz']).toString();
+ t.expect((await t.load(s)).length === 1);
+ }
+});
+
+g.test('test').fn(async t => {
+ t.shouldReject('Error', t.load('suite1::'));
+ t.shouldReject('Error', t.load('suite1:bar:'));
+ t.shouldReject('Error', t.load('suite1:bar,:'));
+
+ t.shouldReject('Error', t.load('suite1::*'));
+ t.shouldReject('Error', t.load('suite1:bar,:*'));
+ t.shouldReject('Error', t.load('suite1:bar:*'));
+
+ t.expect((await t.load('suite1:foo:*')).length === 3);
+ t.expect((await t.load('suite1:bar,buzz,buzz:*')).length === 1);
+ t.expect((await t.load('suite1:baz:*')).length === 4);
+
+ t.expect((await t.load('suite2:foof:bluh,*')).length === 1);
+ t.expect((await t.load('suite2:foof:bluh,a,*')).length === 1);
+
+ {
+ const s = new TestQueryMultiTest('suite2', ['foof'], ['bluh']).toString();
+ t.expect((await t.load(s)).length === 1);
+ }
+});
+
+g.test('case').fn(async t => {
+ t.shouldReject('Error', t.load('suite1:foo::'));
+ t.shouldReject('Error', t.load('suite1:bar:zed,:'));
+
+ t.shouldReject('Error', t.load('suite1:foo:h*'));
+
+ t.shouldReject('Error', t.load('suite1:foo::*'));
+ t.shouldReject('Error', t.load('suite1:baz::*'));
+ t.shouldReject('Error', t.load('suite1:baz:zed,:*'));
+
+ t.shouldReject('Error', t.load('suite1:baz:zed:'));
+ t.shouldReject('Error', t.load('suite1:baz:zed:a=1;b=2*'));
+ t.shouldReject('Error', t.load('suite1:baz:zed:a=1;b=2;'));
+ t.shouldReject('SyntaxError', t.load('suite1:baz:zed:a=1;b=2,')); // tries to parse '2,' as JSON
+ t.shouldReject('Error', t.load('suite1:baz:zed:a=1,b=2')); // '=' not allowed in value '1,b=2'
+ t.shouldReject('Error', t.load('suite1:baz:zed:b=2*'));
+ t.shouldReject('Error', t.load('suite1:baz:zed:b=2;a=1;_c=0'));
+ t.shouldReject('Error', t.load('suite1:baz:zed:a=1,*'));
+
+ t.expect((await t.load('suite1:baz:zed:*')).length === 2);
+ t.expect((await t.load('suite1:baz:zed:a=1;*')).length === 2);
+ t.expect((await t.load('suite1:baz:zed:a=1;b=2')).length === 1);
+ t.expect((await t.load('suite1:baz:zed:a=1;b=2;*')).length === 1);
+ t.expect((await t.load('suite1:baz:zed:b=2;*')).length === 1);
+ t.expect((await t.load('suite1:baz:zed:b=2;a=1')).length === 1);
+ t.expect((await t.load('suite1:baz:zed:b=2;a=1;*')).length === 1);
+ t.expect((await t.load('suite1:baz:zed:b=3;a=1')).length === 1);
+ t.expect((await t.load('suite1:baz:zed:a=1;b=3')).length === 1);
+ t.expect((await t.load('suite1:foo:hello:')).length === 1);
+
+ {
+ const s = new TestQueryMultiCase('suite1', ['baz'], ['zed'], { a: 1, b: 2 }).toString();
+ t.expect((await t.load(s)).length === 1);
+ }
+ {
+ const s = new TestQuerySingleCase('suite1', ['baz'], ['zed'], { a: 1, b: 2 }).toString();
+ t.expect((await t.load(s)).length === 1);
+ }
+});
+
+g.test('end2end').fn(async t => {
+ const l = await t.load('suite2:foof:*');
+ assert(l.length === 3, 'listing length');
+
+ const log = new Logger(true);
+
+ const exp = async (
+ i: number,
+ query: TestQuery,
+ status: Status,
+ logs: (s: string[]) => boolean
+ ) => {
+ t.expect(objectEquals(l[i].query, query));
+ const name = l[i].query.toString();
+ const [rec, res] = log.record(name);
+ await l[i].run(rec);
+
+ t.expect(log.results.get(name) === res);
+ t.expect(res.status === status);
+ t.expect(res.timems > 0);
+ assert(res.logs !== undefined); // only undefined while pending
+ t.expect(logs(res.logs.map(l => JSON.stringify(l))));
+ };
+
+ await exp(0, new TestQuerySingleCase('suite2', ['foof'], ['blah'], {}), 'pass', logs =>
+ objectEquals(logs, ['"DEBUG: OK"'])
+ );
+ await exp(1, new TestQuerySingleCase('suite2', ['foof'], ['bleh'], { a: 1 }), 'pass', logs =>
+ objectEquals(logs, ['"DEBUG: OK"', '"DEBUG: OK"'])
+ );
+ await exp(
+ 2,
+ new TestQuerySingleCase('suite2', ['foof'], ['bluh', 'a'], {}),
+ 'fail',
+ logs =>
+ logs.length === 1 &&
+ logs[0].startsWith('"EXPECTATION FAILED: Error: bye\\n') &&
+ logs[0].indexOf('loaders_and_trees.spec.') !== -1
+ );
+});
+
+async function testIterateCollapsed(
+ t: LoadingTest,
+ expectations: string[],
+ expectedResult: 'throws' | string[]
+) {
+ const treePromise = LoadingTest.loader.loadTree(
+ new TestQueryMultiFile('suite1', []),
+ expectations
+ );
+ if (expectedResult === 'throws') {
+ t.shouldReject('Error', treePromise, 'loadTree should have thrown Error');
+ return;
+ }
+ const tree = await treePromise;
+ const actual = Array.from(tree.iterateCollapsedQueries(), q => q.toString());
+ if (!objectEquals(actual, expectedResult)) {
+ t.fail(
+ `iterateCollapsed failed:
+ got [${actual.join(', ')}]
+ exp [${expectedResult.join(', ')}]
+${tree.toString()}`
+ );
+ }
+}
+
+g.test('print').fn(async () => {
+ const tree = await LoadingTest.loader.loadTree(new TestQueryMultiFile('suite1', []));
+ tree.toString();
+});
+
+g.test('iterateCollapsed').fn(async t => {
+ // Expectations have no effect
+ await testIterateCollapsed(t, [], ['suite1:foo:*', 'suite1:bar,buzz,buzz:*', 'suite1:baz:*']);
+ await testIterateCollapsed(
+ t,
+ ['suite1:*'],
+ ['suite1:foo:*', 'suite1:bar,buzz,buzz:*', 'suite1:baz:*']
+ );
+ await testIterateCollapsed(
+ t,
+ ['suite1:foo:*'],
+ ['suite1:foo:*', 'suite1:bar,buzz,buzz:*', 'suite1:baz:*']
+ );
+ await testIterateCollapsed(
+ t,
+ ['suite1:bar,buzz,buzz:*'],
+ ['suite1:foo:*', 'suite1:bar,buzz,buzz:*', 'suite1:baz:*']
+ );
+
+ // Expectations have some effect
+ await testIterateCollapsed(
+ t,
+ ['suite1:baz:wye:*'],
+ ['suite1:foo:*', 'suite1:bar,buzz,buzz:*', 'suite1:baz:wye:*', 'suite1:baz:zed,*']
+ );
+ await testIterateCollapsed(
+ t,
+ ['suite1:baz:zed:*'],
+ ['suite1:foo:*', 'suite1:bar,buzz,buzz:*', 'suite1:baz:wye,*', 'suite1:baz:zed:*']
+ );
+ await testIterateCollapsed(
+ t,
+ ['suite1:baz:wye:*', 'suite1:baz:zed:*'],
+ ['suite1:foo:*', 'suite1:bar,buzz,buzz:*', 'suite1:baz:wye:*', 'suite1:baz:zed:*']
+ );
+ await testIterateCollapsed(
+ t,
+ ['suite1:baz:wye:'],
+ [
+ 'suite1:foo:*',
+ 'suite1:bar,buzz,buzz:*',
+ 'suite1:baz:wye:',
+ 'suite1:baz:wye:x=1;*',
+ 'suite1:baz:zed,*',
+ ]
+ );
+ await testIterateCollapsed(
+ t,
+ ['suite1:baz:wye:x=1'],
+ [
+ 'suite1:foo:*',
+ 'suite1:bar,buzz,buzz:*',
+ 'suite1:baz:wye:',
+ 'suite1:baz:wye:x=1',
+ 'suite1:baz:zed,*',
+ ]
+ );
+ await testIterateCollapsed(
+ t,
+ ['suite1:foo:*', 'suite1:baz:wye:'],
+ [
+ 'suite1:foo:*',
+ 'suite1:bar,buzz,buzz:*',
+ 'suite1:baz:wye:',
+ 'suite1:baz:wye:x=1;*',
+ 'suite1:baz:zed,*',
+ ]
+ );
+
+ // Invalid expectation queries
+ await testIterateCollapsed(t, ['garbage'], 'throws');
+ await testIterateCollapsed(t, ['garbage*'], 'throws');
+ await testIterateCollapsed(t, ['suite1*'], 'throws');
+ await testIterateCollapsed(t, ['suite1:foo*'], 'throws');
+ await testIterateCollapsed(t, ['suite1:foo:ba*'], 'throws');
+
+ // Valid expectation queries but they don't match anything
+ await testIterateCollapsed(t, ['garbage:*'], 'throws');
+ await testIterateCollapsed(t, ['suite1:doesntexist:*'], 'throws');
+ await testIterateCollapsed(t, ['suite2:foo:*'], 'throws');
+ // Doesn't match anything because we collapse this unnecessary node into just 'suite1:foo:*'
+ await testIterateCollapsed(t, ['suite1:foo,*'], 'throws');
+});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/loading.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/loading.spec.ts
deleted file mode 100644
index c66728a3df2..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/unittests/loading.spec.ts
+++ /dev/null
@@ -1,348 +0,0 @@
-export const description = `
-Tests for queries/filtering, loading, and running.
-`;
-
-import { generateMinimalQueryList } from '../common/framework/generate_minimal_query_list.js';
-import { TestSuiteListing, TestSuiteListingEntry } from '../common/framework/listing.js';
-import { TestFileLoader, TestLoader, TestSpecOrReadme } from '../common/framework/loader.js';
-import { Logger } from '../common/framework/logger.js';
-import { paramsEquals } from '../common/framework/params_utils.js';
-import { TestFilterResult } from '../common/framework/test_filter/test_filter_result.js';
-import { RunCase, TestGroup } from '../common/framework/test_group.js';
-import { makeQueryString } from '../common/framework/url_query.js';
-import { assert, objectEquals } from '../common/framework/util/util.js';
-
-import { UnitTest } from './unit_test.js';
-
-const listingData: { [k: string]: TestSuiteListingEntry[] } = {
- suite1: [
- { path: '', description: 'desc 1a' },
- { path: 'foo', description: 'desc 1b' },
- { path: 'bar/', description: 'desc 1c' },
- { path: 'bar/buzz', description: 'desc 1d' },
- { path: 'baz', description: 'desc 1e' },
- ],
- suite2: [
- { path: '', description: 'desc 2a' },
- { path: 'foof', description: 'desc 2b' },
- ],
-};
-
-const specsData: { [k: string]: TestSpecOrReadme } = {
- 'suite1/README.txt': { description: 'desc 1a' },
- 'suite1/foo.spec.js': {
- description: 'desc 1b',
- g: (() => {
- const g = new TestGroup(UnitTest);
- g.test('hello', () => {});
- g.test('bonjour', () => {});
- g.test('hola', () => {});
- return g;
- })(),
- },
- 'suite1/bar/README.txt': { description: 'desc 1c' },
- 'suite1/bar/biz.spec.js': {
- description: 'desc 1f',
- g: new TestGroup(UnitTest),
- },
- 'suite1/bar/bez.spec.js': {
- description: 'desc 1g',
- g: new TestGroup(UnitTest),
- },
- 'suite1/bar/buzz.spec.js': {
- description: 'desc 1d',
- g: (() => {
- const g = new TestGroup(UnitTest);
- g.test('zap', () => {});
- return g;
- })(),
- },
- 'suite1/baz.spec.js': {
- description: 'desc 1e',
- g: (() => {
- const g = new TestGroup(UnitTest);
- g.test('wye', () => {}).params([
- {}, //
- { x: 1 },
- ]);
- g.test('zed', () => {}).params([
- { a: 1, b: 2, _c: 0 }, //
- { a: 1, b: 3, _c: 0 },
- ]);
- return g;
- })(),
- },
- 'suite2/foof.spec.js': {
- description: 'desc 2b',
- g: (() => {
- const g = new TestGroup(UnitTest);
- g.test('blah', t => {
- t.debug('OK');
- });
- g.test('bleh', t => {
- t.debug('OK');
- t.debug('OK');
- }).params([{}]);
- g.test('bluh', t => {
- t.fail('bye');
- });
- return g;
- })(),
- },
-};
-
-class FakeTestFileLoader implements TestFileLoader {
- async listing(suite: string): Promise<TestSuiteListing> {
- return listingData[suite];
- }
-
- async import(path: string): Promise<TestSpecOrReadme> {
- assert(specsData.hasOwnProperty(path), '[test] mock file ' + path + ' does not exist');
- return specsData[path];
- }
-}
-
-class LoadingTest extends UnitTest {
- static readonly loader: TestLoader = new TestLoader(new FakeTestFileLoader());
-
- async load(filters: string[]): Promise<TestFilterResult[]> {
- return Array.from(await LoadingTest.loader.loadTestsFromCmdLine(filters));
- }
-
- async singleGroup(query: string): Promise<RunCase[]> {
- const [rec] = new Logger().record({ suite: '', path: '' });
- const a = await this.load([query]);
- assert(a.length === 1, 'more than one group');
- const spec = a[0].spec;
- assert('g' in spec, 'group undefined');
- return Array.from(spec.g.iterate(rec));
- }
-}
-
-export const g = new TestGroup(LoadingTest);
-
-g.test('whole suite', async t => {
- t.shouldReject('Error', t.load(['suite1']));
- t.expect((await t.load(['suite1:'])).length === 5);
-});
-
-g.test('partial suite', async t => {
- t.expect((await t.load(['suite1:f'])).length === 1);
- t.expect((await t.load(['suite1:fo'])).length === 1);
- t.expect((await t.load(['suite1:foo'])).length === 1);
- t.expect((await t.load(['suite1:foof'])).length === 0);
- t.expect((await t.load(['suite1:ba'])).length === 3);
- t.expect((await t.load(['suite1:bar'])).length === 2);
- t.expect((await t.load(['suite1:bar/'])).length === 2);
- t.expect((await t.load(['suite1:bar/b'])).length === 1);
-});
-
-g.test('whole group', async t => {
- t.shouldReject('Error', t.load(['suite1::']));
- t.shouldReject('Error', t.load(['suite1:bar:']));
- t.shouldReject('Error', t.load(['suite1:bar/:']));
- t.expect((await t.singleGroup('suite1:bar/buzz:')).length === 1);
- t.expect((await t.singleGroup('suite1:baz:')).length === 4);
-
- {
- const foo = (await t.load(['suite1:foo:']))[0];
- t.expect(foo.id.suite === 'suite1');
- t.expect(foo.id.path === 'foo');
- assert('g' in foo.spec, 'foo group');
- const [rec] = new Logger().record({ suite: '', path: '' });
- t.expect(Array.from(foo.spec.g.iterate(rec)).length === 3);
- }
-});
-
-g.test('partial group', async t => {
- t.expect((await t.singleGroup('suite1:foo:h')).length === 2);
- t.expect((await t.singleGroup('suite1:foo:he')).length === 1);
- t.expect((await t.singleGroup('suite1:foo:hello')).length === 1);
- t.expect((await t.singleGroup('suite1:baz:zed')).length === 2);
-});
-
-g.test('partial test/exact', async t => {
- t.expect((await t.singleGroup('suite1:foo:hello=')).length === 1);
- t.expect((await t.singleGroup('suite1:baz:zed=')).length === 0);
- t.expect((await t.singleGroup('suite1:baz:zed=')).length === 0);
- t.expect((await t.singleGroup('suite1:baz:zed={}')).length === 0);
- t.expect((await t.singleGroup('suite1:baz:zed={"a":1,"b":2}')).length === 1);
- t.expect((await t.singleGroup('suite1:baz:zed={"b":2,"a":1}')).length === 1);
- t.expect((await t.singleGroup('suite1:baz:zed={"a":1,"b":2,"_c":0}')).length === 0);
-});
-
-g.test('partial test/makeQueryString', async t => {
- const s = makeQueryString(
- { suite: 'suite1', path: 'baz' },
- { test: 'zed', params: { a: 1, b: 2 } }
- );
- t.expect((await t.singleGroup(s)).length === 1);
-});
-
-g.test('partial test/match', async t => {
- t.expect((await t.singleGroup('suite1:baz:zed~')).length === 2);
- t.expect((await t.singleGroup('suite1:baz:zed~{}')).length === 2);
- t.expect((await t.singleGroup('suite1:baz:zed~{"a":1}')).length === 2);
- t.expect((await t.singleGroup('suite1:baz:zed~{"a":1,"b":2}')).length === 1);
- t.expect((await t.singleGroup('suite1:baz:zed~{"b":2,"a":1}')).length === 1);
- t.expect((await t.singleGroup('suite1:baz:zed~{"b":2}')).length === 1);
- t.expect((await t.singleGroup('suite1:baz:zed~{"a":2}')).length === 0);
- t.expect((await t.singleGroup('suite1:baz:zed~{"c":0}')).length === 0);
- t.expect((await t.singleGroup('suite1:baz:zed~{"_c":0}')).length === 0);
-});
-
-g.test('end2end', async t => {
- const l = await t.load(['suite2:foof']);
- assert(l.length === 1, 'listing length');
-
- t.expect(l[0].id.suite === 'suite2');
- t.expect(l[0].id.path === 'foof');
- t.expect(l[0].spec.description === 'desc 2b');
- assert('g' in l[0].spec);
- t.expect(l[0].spec.g.iterate instanceof Function);
-
- const log = new Logger();
- const [rec, res] = log.record(l[0].id);
- const rcs = Array.from(l[0].spec.g.iterate(rec));
- assert(rcs.length === 3, 'iterate length');
-
- t.expect(rcs[0].id.test === 'blah');
- t.expect(rcs[0].id.params === null);
-
- t.expect(rcs[1].id.test === 'bleh');
- t.expect(paramsEquals(rcs[1].id.params, {}));
-
- t.expect(log.results[0] === res);
- t.expect(res.spec === 'suite2:foof:');
- t.expect(res.cases.length === 0);
-
- {
- const cases = res.cases;
- const res0 = await rcs[0].run(true);
- assert(cases.length === 1, 'results cases length');
- t.expect(res.cases[0] === res0);
- t.expect(res0.test === 'blah');
- t.expect(res0.params === null);
- t.expect(res0.status === 'pass');
- t.expect(res0.timems >= 0);
- assert(res0.logs !== undefined, 'results case logs');
- t.expect(objectEquals(JSON.stringify(res0.logs), '["DEBUG: OK"]'));
- }
- {
- // Store cases off to a separate variable due to a typescript bug
- // where it can't detect that res.cases.length might change between
- // above and here.
- const cases = res.cases;
- const res1 = await rcs[1].run(true);
- assert(cases.length === 2, 'results cases length');
- t.expect(res.cases[1] === res1);
- t.expect(res1.test === 'bleh');
- t.expect(paramsEquals(res1.params, {}));
- t.expect(res1.status === 'pass');
- t.expect(res1.timems >= 0);
- assert(res1.logs !== undefined, 'results case logs');
- t.expect(objectEquals(JSON.stringify(res1.logs), '["DEBUG: OK","DEBUG: OK"]'));
- }
- {
- // Store cases off to a separate variable due to a typescript bug
- // where it can't detect that res.cases.length might change between
- // above and here.
- const cases = res.cases;
- const res2 = await rcs[2].run(true);
- assert(cases.length === 3, 'results cases length');
- t.expect(res.cases[2] === res2);
- t.expect(res2.test === 'bluh');
- t.expect(res2.params === null);
- t.expect(res2.status === 'fail');
- t.expect(res2.timems >= 0);
- assert(res2.logs !== undefined, 'results case logs');
- t.expect(res2.logs.length === 1);
- const l = res2.logs[0].toJSON();
- t.expect(l.startsWith('FAIL: bye\n'));
- t.expect(l.indexOf('loading.spec.') !== -1);
- }
-});
-
-const testGenerateMinimalQueryList = async (
- t: LoadingTest,
- expectations: string[],
- result: string[]
-) => {
- const l = await t.load(['suite1:']);
- const queries = await generateMinimalQueryList(l, expectations);
- t.expect(objectEquals(queries, result));
-};
-
-g.test('generateMinimalQueryList/errors', async t => {
- t.shouldReject('Error', testGenerateMinimalQueryList(t, ['garbage'], []));
- t.shouldReject('Error', testGenerateMinimalQueryList(t, ['suite1:'], []));
- t.shouldReject('Error', testGenerateMinimalQueryList(t, ['suite1:foo'], []));
- t.shouldReject('Error', testGenerateMinimalQueryList(t, ['suite1:foo:ba'], []));
- t.shouldReject('Error', testGenerateMinimalQueryList(t, ['suite2:foo:'], []));
-});
-
-g.test('generateMinimalQueryList', async t => {
- await testGenerateMinimalQueryList(
- t, //
- [],
- ['suite1:foo:', 'suite1:bar/buzz:', 'suite1:baz:']
- );
- await testGenerateMinimalQueryList(
- t, //
- ['suite1:foo:'],
- ['suite1:foo:', 'suite1:bar/buzz:', 'suite1:baz:']
- );
- await testGenerateMinimalQueryList(
- t, //
- ['suite1:bar/buzz:'],
- ['suite1:foo:', 'suite1:bar/buzz:', 'suite1:baz:']
- );
- await testGenerateMinimalQueryList(
- t, //
- ['suite1:baz:wye~'],
- ['suite1:foo:', 'suite1:bar/buzz:', 'suite1:baz:wye~', 'suite1:baz:zed~']
- );
- await testGenerateMinimalQueryList(
- t, //
- ['suite1:baz:zed~'],
- ['suite1:foo:', 'suite1:bar/buzz:', 'suite1:baz:wye~', 'suite1:baz:zed~']
- );
- await testGenerateMinimalQueryList(
- t, //
- ['suite1:baz:wye~', 'suite1:baz:zed~'],
- ['suite1:foo:', 'suite1:bar/buzz:', 'suite1:baz:wye~', 'suite1:baz:zed~']
- );
- await testGenerateMinimalQueryList(
- t, //
- ['suite1:baz:wye='],
- [
- 'suite1:foo:',
- 'suite1:bar/buzz:',
- 'suite1:baz:wye=',
- 'suite1:baz:wye={"x":1}',
- 'suite1:baz:zed~',
- ]
- );
- await testGenerateMinimalQueryList(
- t, //
- ['suite1:baz:wye={"x":1}'],
- [
- 'suite1:foo:',
- 'suite1:bar/buzz:',
- 'suite1:baz:wye=',
- 'suite1:baz:wye={"x":1}',
- 'suite1:baz:zed~',
- ]
- );
- await testGenerateMinimalQueryList(
- t, //
- ['suite1:foo:', 'suite1:baz:wye='],
- [
- 'suite1:foo:',
- 'suite1:bar/buzz:',
- 'suite1:baz:wye=',
- 'suite1:baz:wye={"x":1}',
- 'suite1:baz:zed~',
- ]
- );
-});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/logger.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/logger.spec.ts
index cc284b16d61..de1b02fbe47 100644
--- a/chromium/third_party/webgpu-cts/src/src/unittests/logger.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/logger.spec.ts
@@ -5,139 +5,143 @@ Also serves as a larger test of async test functions, and of the logging system.
`;
import { SkipTestCase } from '../common/framework/fixture.js';
-import { Logger } from '../common/framework/logger.js';
-import { paramsEquals } from '../common/framework/params_utils.js';
-import { TestGroup } from '../common/framework/test_group.js';
+import { Logger } from '../common/framework/logging/logger.js';
+import { makeTestGroup } from '../common/framework/test_group.js';
+import { assert } from '../common/framework/util/util.js';
import { UnitTest } from './unit_test.js';
-export const g = new TestGroup(UnitTest);
-
-g.test('construct', t => {
- const mylog = new Logger();
- const [testrec, testres] = mylog.record({ suite: 'a', path: 'foo/bar' });
- const [, res1] = testrec.record('baz', null);
- const params2 = {};
- const [, res2] = testrec.record('qux', params2);
-
- t.expect(testres.spec === 'a:foo/bar:');
- t.expect(testres.cases.length === 2);
- t.expect(testres.cases[0] === res1);
- t.expect(testres.cases[1] === res2);
- t.expect(res1.test === 'baz');
- t.expect(res1.params === null);
+export const g = makeTestGroup(UnitTest);
+
+g.test('construct').fn(t => {
+ const mylog = new Logger(true);
+ const [, res1] = mylog.record('one');
+ const [, res2] = mylog.record('two');
+
+ t.expect(mylog.results.get('one') === res1);
+ t.expect(mylog.results.get('two') === res2);
t.expect(res1.logs === undefined);
t.expect(res1.status === 'running');
t.expect(res1.timems < 0);
- t.expect(res2.test === 'qux');
- t.expect(paramsEquals(res2.params, params2));
t.expect(res2.logs === undefined);
t.expect(res2.status === 'running');
t.expect(res2.timems < 0);
});
-g.test('private params', t => {
- const mylog = new Logger();
- const [testrec] = mylog.record({ suite: 'a', path: 'foo/bar' });
- const [, res] = testrec.record('baz', { a: 1, _b: 2 });
-
- t.expect(paramsEquals(res.params, { a: 1 }));
-});
-
-g.test('empty', t => {
- const mylog = new Logger();
- const [testrec] = mylog.record({ suite: '', path: '' });
- const [rec, res] = testrec.record('baz', null);
+g.test('empty').fn(t => {
+ const mylog = new Logger(true);
+ const [rec, res] = mylog.record('one');
rec.start();
t.expect(res.status === 'running');
rec.finish();
+
t.expect(res.status === 'pass');
t.expect(res.timems >= 0);
});
-g.test('pass', t => {
- const mylog = new Logger();
- const [testrec] = mylog.record({ suite: '', path: '' });
- const [rec, res] = testrec.record('baz', null);
+g.test('pass').fn(t => {
+ const mylog = new Logger(true);
+ const [rec, res] = mylog.record('one');
rec.start();
rec.debug(new Error('hello'));
t.expect(res.status === 'running');
rec.finish();
+
t.expect(res.status === 'pass');
t.expect(res.timems >= 0);
});
-g.test('skip', t => {
- const mylog = new Logger();
- const [testrec] = mylog.record({ suite: '', path: '' });
- const [rec, res] = testrec.record('baz', null);
+g.test('skip').fn(t => {
+ const mylog = new Logger(true);
+ const [rec, res] = mylog.record('one');
rec.start();
- t.expect(res.status === 'running');
-
rec.skipped(new SkipTestCase());
rec.debug(new Error('hello'));
-
- t.expect(res.status === 'running');
rec.finish();
t.expect(res.status === 'skip');
t.expect(res.timems >= 0);
});
-g.test('warn', t => {
- const mylog = new Logger();
- const [testrec] = mylog.record({ suite: '', path: '' });
- const [rec, res] = testrec.record('baz', null);
+g.test('warn').fn(t => {
+ const mylog = new Logger(true);
+ const [rec, res] = mylog.record('one');
rec.start();
- t.expect(res.status === 'running');
-
- rec.warn(new Error());
+ rec.warn(new Error('hello'));
rec.skipped(new SkipTestCase());
-
- t.expect(res.status === 'running');
rec.finish();
t.expect(res.status === 'warn');
t.expect(res.timems >= 0);
});
-g.test('fail', t => {
- const mylog = new Logger();
- const [testrec] = mylog.record({ suite: '', path: '' });
- const [rec, res] = testrec.record('baz', null);
+g.test('fail,expectationFailed').fn(t => {
+ const mylog = new Logger(true);
+ const [rec, res] = mylog.record('one');
rec.start();
- t.expect(res.status === 'running');
-
- rec.fail(new Error('bye'));
+ rec.expectationFailed(new Error('bye'));
rec.warn(new Error());
rec.skipped(new SkipTestCase());
-
- t.expect(res.status === 'running');
rec.finish();
t.expect(res.status === 'fail');
t.expect(res.timems >= 0);
});
-g.test('debug', t => {
- const { debug, _logsCount } = t.params;
+g.test('fail,validationFailed').fn(t => {
+ const mylog = new Logger(true);
+ const [rec, res] = mylog.record('one');
+
+ rec.start();
+ rec.validationFailed(new Error('bye'));
+ rec.warn(new Error());
+ rec.skipped(new SkipTestCase());
+ rec.finish();
- const mylog = new Logger();
- const [testrec] = mylog.record({ suite: '', path: '' });
- const [rec, res] = testrec.record('baz', null);
+ t.expect(res.status === 'fail');
+ t.expect(res.timems >= 0);
+});
- rec.start(debug);
- rec.debug(new Error('hello'));
+g.test('fail,threw').fn(t => {
+ const mylog = new Logger(true);
+ const [rec, res] = mylog.record('one');
+
+ rec.start();
+ rec.threw(new Error('bye'));
+ rec.warn(new Error());
+ rec.skipped(new SkipTestCase());
rec.finish();
- t.expect(res.status === 'pass');
+
+ t.expect(res.status === 'fail');
t.expect(res.timems >= 0);
- t.expect(res.logs!.length === _logsCount);
-}).params([
- { debug: true, _logsCount: 1 }, //
- { debug: false, _logsCount: 0 },
-]);
+});
+
+g.test('debug')
+ .params([
+ { debug: true, _logsCount: 5 }, //
+ { debug: false, _logsCount: 3 },
+ ])
+ .fn(t => {
+ const { debug, _logsCount } = t.params;
+
+ const mylog = new Logger(debug);
+ const [rec, res] = mylog.record('one');
+
+ rec.start();
+ rec.debug(new Error('hello'));
+ rec.expectationFailed(new Error('bye'));
+ rec.warn(new Error());
+ rec.skipped(new SkipTestCase());
+ rec.debug(new Error('foo'));
+ rec.finish();
+
+ t.expect(res.status === 'fail');
+ t.expect(res.timems >= 0);
+ assert(res.logs !== undefined);
+ t.expect(res.logs.length === _logsCount);
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/make_filter.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/make_filter.spec.ts
deleted file mode 100644
index d7769d6cf35..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/unittests/make_filter.spec.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export const description = `
-Unit tests for makeFilter.
-`;
-
-import { TestGroup } from '../common/framework/test_group.js';
-
-import { UnitTest } from './unit_test.js';
-
-export const g = new TestGroup(UnitTest);
-
-// TODO: tests for makeFilter, in particular idIfSingle()
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/param_helpers.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/param_helpers.spec.ts
deleted file mode 100644
index ba2dbf4593e..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/unittests/param_helpers.spec.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-export const description = `
-Unit tests for parameterization helpers.
-`;
-
-import { pcombine, pexclude, pfilter, poptions } from '../common/framework/params.js';
-import { ParamSpec, ParamSpecIterable, paramsEquals } from '../common/framework/params_utils.js';
-import { TestGroup } from '../common/framework/test_group.js';
-
-import { UnitTest } from './unit_test.js';
-
-class ParamsTest extends UnitTest {
- expectSpecEqual(act: ParamSpecIterable, exp: ParamSpec[]): void {
- const a = Array.from(act);
- this.expect(a.length === exp.length && a.every((x, i) => paramsEquals(x, exp[i])));
- }
-}
-
-export const g = new TestGroup(ParamsTest);
-
-g.test('options', t => {
- t.expectSpecEqual(poptions('hello', [1, 2, 3]), [{ hello: 1 }, { hello: 2 }, { hello: 3 }]);
-});
-
-g.test('combine/none', t => {
- t.expectSpecEqual(pcombine(), []);
-});
-
-g.test('combine/zeroes and ones', t => {
- t.expectSpecEqual(pcombine([], []), []);
- t.expectSpecEqual(pcombine([], [{}]), []);
- t.expectSpecEqual(pcombine([{}], []), []);
- t.expectSpecEqual(pcombine([{}], [{}]), [{}]);
-});
-
-g.test('combine/mixed', t => {
- t.expectSpecEqual(
- pcombine(poptions('x', [1, 2]), poptions('y', ['a', 'b']), [{ p: 4 }, { q: 5 }], [{}]),
- [
- { x: 1, y: 'a', p: 4 },
- { x: 1, y: 'a', q: 5 },
- { x: 1, y: 'b', p: 4 },
- { x: 1, y: 'b', q: 5 },
- { x: 2, y: 'a', p: 4 },
- { x: 2, y: 'a', q: 5 },
- { x: 2, y: 'b', p: 4 },
- { x: 2, y: 'b', q: 5 },
- ]
- );
-});
-
-g.test('filter', t => {
- t.expectSpecEqual(
- pfilter(
- [
- { a: true, x: 1 },
- { a: false, y: 2 },
- ],
- p => p.a
- ),
- [{ a: true, x: 1 }]
- );
-});
-
-g.test('exclude', t => {
- t.expectSpecEqual(
- pexclude(
- [
- { a: true, x: 1 },
- { a: false, y: 2 },
- ],
- [{ a: true }, { a: false, y: 2 }]
- ),
- [{ a: true, x: 1 }]
- );
-});
-
-g.test('undefined', t => {
- t.expectSpecEqual([{ a: undefined }], [{}]);
- t.expectSpecEqual([{}], [{ a: undefined }]);
-});
-
-g.test('arrays', t => {
- t.expectSpecEqual([{ a: [1, 2] }], [{ a: [1, 2] }]);
-});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/params.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/params.spec.ts
deleted file mode 100644
index 65c486f9a09..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/unittests/params.spec.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-export const description = `
-Unit tests for parameterization.
-`;
-
-import { pcombine, pexclude, pfilter } from '../common/framework/params.js';
-import { ParamSpec } from '../common/framework/params_utils.js';
-import { TestGroup } from '../common/framework/test_group.js';
-
-import { TestGroupTest } from './test_group_test.js';
-import { UnitTest } from './unit_test.js';
-
-export const g = new TestGroup(TestGroupTest);
-
-g.test('none', t => {
- t.fail("this test shouldn't run");
-}).params([]);
-
-g.test('combine none', t => {
- t.fail("this test shouldn't run");
-}).params(pcombine([]));
-
-g.test('filter', t => {
- t.expect(t.params.a);
-}).params(
- pfilter(
- [
- { a: true, x: 1 }, //
- { a: false, y: 2 },
- ],
- p => p.a
- )
-);
-
-g.test('exclude', t => {
- t.expect(t.params.a);
-}).params(
- pexclude(
- [
- { a: true, x: 1 }, //
- { a: false, y: 2 },
- ],
- [
- { a: true }, //
- { a: false, y: 2 },
- ]
- )
-);
-
-g.test('generator', t0 => {
- const g = new TestGroup(UnitTest);
-
- const ran: ParamSpec[] = [];
-
- g.test('generator', t => {
- ran.push(t.params);
- }).params(
- (function*(): IterableIterator<ParamSpec> {
- for (let x = 0; x < 3; ++x) {
- for (let y = 0; y < 2; ++y) {
- yield { x, y };
- }
- }
- })()
- );
-
- t0.expectCases(g, [
- { test: 'generator', params: { x: 0, y: 0 } },
- { test: 'generator', params: { x: 0, y: 1 } },
- { test: 'generator', params: { x: 1, y: 0 } },
- { test: 'generator', params: { x: 1, y: 1 } },
- { test: 'generator', params: { x: 2, y: 0 } },
- { test: 'generator', params: { x: 2, y: 1 } },
- ]);
-});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/params_builder_and_utils.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/params_builder_and_utils.spec.ts
new file mode 100644
index 00000000000..086162f1228
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/params_builder_and_utils.spec.ts
@@ -0,0 +1,140 @@
+export const description = `
+Unit tests for parameterization helpers.
+`;
+
+import { poptions, params } from '../common/framework/params_builder.js';
+import {
+ CaseParams,
+ CaseParamsIterable,
+ publicParamsEquals,
+} from '../common/framework/params_utils.js';
+import { makeTestGroup } from '../common/framework/test_group.js';
+
+import { UnitTest } from './unit_test.js';
+
+class ParamsTest extends UnitTest {
+ expectSpecEqual(act: CaseParamsIterable, exp: CaseParams[]): void {
+ const a = Array.from(act);
+ this.expect(a.length === exp.length && a.every((x, i) => publicParamsEquals(x, exp[i])));
+ }
+}
+
+export const g = makeTestGroup(ParamsTest);
+
+g.test('options').fn(t => {
+ t.expectSpecEqual(poptions('hello', [1, 2, 3]), [{ hello: 1 }, { hello: 2 }, { hello: 3 }]);
+});
+
+g.test('params').fn(t => {
+ t.expectSpecEqual(params(), [{}]);
+});
+
+g.test('combine,zeroes_and_ones').fn(t => {
+ t.expectSpecEqual(params().combine([]).combine([]), []);
+ t.expectSpecEqual(params().combine([]).combine([{}]), []);
+ t.expectSpecEqual(params().combine([{}]).combine([]), []);
+ t.expectSpecEqual(params().combine([{}]).combine([{}]), [{}]);
+});
+
+g.test('combine,mixed').fn(t => {
+ t.expectSpecEqual(
+ params()
+ .combine(poptions('x', [1, 2]))
+ .combine(poptions('y', ['a', 'b']))
+ .combine([{ p: 4 }, { q: 5 }])
+ .combine([{}]),
+ [
+ { x: 1, y: 'a', p: 4 },
+ { x: 1, y: 'a', q: 5 },
+ { x: 1, y: 'b', p: 4 },
+ { x: 1, y: 'b', q: 5 },
+ { x: 2, y: 'a', p: 4 },
+ { x: 2, y: 'a', q: 5 },
+ { x: 2, y: 'b', p: 4 },
+ { x: 2, y: 'b', q: 5 },
+ ]
+ );
+});
+
+g.test('filter').fn(t => {
+ t.expectSpecEqual(
+ params()
+ .combine([
+ { a: true, x: 1 },
+ { a: false, y: 2 },
+ ])
+ .filter(p => p.a),
+ [{ a: true, x: 1 }]
+ );
+});
+
+g.test('unless').fn(t => {
+ t.expectSpecEqual(
+ params()
+ .combine([
+ { a: true, x: 1 },
+ { a: false, y: 2 },
+ ])
+ .unless(p => p.a),
+ [{ a: false, y: 2 }]
+ );
+});
+
+g.test('exclude').fn(t => {
+ t.expectSpecEqual(
+ params()
+ .combine([
+ { a: true, x: 1 },
+ { a: false, y: 2 },
+ ])
+ .exclude([{ a: true }, { a: false, y: 2 }]),
+ [{ a: true, x: 1 }]
+ );
+});
+
+g.test('expand').fn(t => {
+ t.expectSpecEqual(
+ params()
+ .combine([
+ { a: true, x: 1 },
+ { a: false, y: 2 },
+ ])
+ .expand(function* (p) {
+ if (p.a) {
+ yield* poptions('z', [3, 4]);
+ } else {
+ yield { w: 5 };
+ }
+ }),
+ [
+ { a: true, x: 1, z: 3 },
+ { a: true, x: 1, z: 4 },
+ { a: false, y: 2, w: 5 },
+ ]
+ );
+});
+
+g.test('expand,invalid').fn(t => {
+ const p = params()
+ .combine([{ x: 1 }])
+ .expand(function* (p) {
+ yield p; // causes key 'x' to be duplicated
+ });
+ t.shouldThrow('Error', () => {
+ Array.from(p);
+ });
+});
+
+g.test('undefined').fn(t => {
+ t.expect(!publicParamsEquals({ a: undefined }, {}));
+ t.expect(!publicParamsEquals({}, { a: undefined }));
+});
+
+g.test('private').fn(t => {
+ t.expect(publicParamsEquals({ _a: 0 }, {}));
+ t.expect(publicParamsEquals({}, { _a: 0 }));
+});
+
+g.test('arrays').fn(t => {
+ t.expectSpecEqual([{ a: [1, 2] }], [{ a: [1, 2] }]);
+});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/params_builder_toplevel.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/params_builder_toplevel.spec.ts
new file mode 100644
index 00000000000..aebbfb673cf
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/params_builder_toplevel.spec.ts
@@ -0,0 +1,95 @@
+export const description = `
+Unit tests for parameterization.
+`;
+
+import { params } from '../common/framework/params_builder.js';
+import { CaseParams } from '../common/framework/params_utils.js';
+import { makeTestGroup, makeTestGroupForUnitTesting } from '../common/framework/test_group.js';
+
+import { TestGroupTest } from './test_group_test.js';
+import { UnitTest } from './unit_test.js';
+
+export const g = makeTestGroup(TestGroupTest);
+
+g.test('none')
+ .params([])
+ .fn(t => {
+ t.fail("this test shouldn't run");
+ });
+
+g.test('combine_none')
+ .params(params().combine([]))
+ .fn(t => {
+ t.fail("this test shouldn't run");
+ });
+
+g.test('filter')
+ .params(
+ params()
+ .combine([
+ { a: true, x: 1 }, //
+ { a: false, y: 2 },
+ ])
+ .filter(p => p.a)
+ )
+ .fn(t => {
+ t.expect(t.params.a);
+ });
+
+g.test('unless')
+ .params(
+ params()
+ .combine([
+ { a: true, x: 1 }, //
+ { a: false, y: 2 },
+ ])
+ .unless(p => p.a)
+ )
+ .fn(t => {
+ t.expect(!t.params.a);
+ });
+
+g.test('exclude')
+ .params(
+ params()
+ .combine([
+ { a: true, x: 1 },
+ { a: false, y: 2 },
+ ])
+ .exclude([
+ { a: true }, //
+ { a: false, y: 2 },
+ ])
+ )
+ .fn(t => {
+ t.expect(t.params.a);
+ });
+
+g.test('generator').fn(t0 => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+
+ const ran: CaseParams[] = [];
+
+ g.test('generator')
+ .params(
+ (function* (): IterableIterator<CaseParams> {
+ for (let x = 0; x < 3; ++x) {
+ for (let y = 0; y < 2; ++y) {
+ yield { x, y };
+ }
+ }
+ })()
+ )
+ .fn(t => {
+ ran.push(t.params);
+ });
+
+ t0.expectCases(g, [
+ { test: ['generator'], params: { x: 0, y: 0 } },
+ { test: ['generator'], params: { x: 0, y: 1 } },
+ { test: ['generator'], params: { x: 1, y: 0 } },
+ { test: ['generator'], params: { x: 1, y: 1 } },
+ { test: ['generator'], params: { x: 2, y: 0 } },
+ { test: ['generator'], params: { x: 2, y: 1 } },
+ ]);
+});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/query_compare.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/query_compare.spec.ts
new file mode 100644
index 00000000000..f3e35753ea0
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/query_compare.spec.ts
@@ -0,0 +1,133 @@
+export const description = `
+Tests for TestQuery comparison
+`;
+
+import { compareQueries, Ordering } from '../common/framework/query/compare.js';
+import {
+ TestQuery,
+ TestQuerySingleCase,
+ TestQueryMultiFile,
+ TestQueryMultiTest,
+ TestQueryMultiCase,
+} from '../common/framework/query/query.js';
+import { makeTestGroup } from '../common/framework/test_group.js';
+
+import { UnitTest } from './unit_test.js';
+
+class F extends UnitTest {
+ expectQ(a: TestQuery, exp: '<' | '=' | '>' | '!', b: TestQuery) {
+ const [expOrdering, expInvOrdering] =
+ exp === '<'
+ ? [Ordering.StrictSubset, Ordering.StrictSuperset]
+ : exp === '='
+ ? [Ordering.Equal, Ordering.Equal]
+ : exp === '>'
+ ? [Ordering.StrictSuperset, Ordering.StrictSubset]
+ : [Ordering.Unordered, Ordering.Unordered];
+ {
+ const act = compareQueries(a, b);
+ this.expect(act === expOrdering, `${a} ${b} got ${act}, exp ${expOrdering}`);
+ }
+ {
+ const act = compareQueries(a, b);
+ this.expect(act === expOrdering, `${b} ${a} got ${act}, exp ${expInvOrdering}`);
+ }
+ }
+
+ expectWellOrdered(...qs: TestQuery[]) {
+ for (let i = 0; i < qs.length; ++i) {
+ this.expectQ(qs[i], '=', qs[i]);
+ for (let j = i + 1; j < qs.length; ++j) {
+ this.expectQ(qs[i], '>', qs[j]);
+ }
+ }
+ }
+
+ expectUnordered(...qs: TestQuery[]) {
+ for (let i = 0; i < qs.length; ++i) {
+ this.expectQ(qs[i], '=', qs[i]);
+ for (let j = i + 1; j < qs.length; ++j) {
+ this.expectQ(qs[i], '!', qs[j]);
+ }
+ }
+ }
+}
+
+export const g = makeTestGroup(F);
+
+// suite:* > suite:a,* > suite:a,b,* > suite:a,b:*
+// suite:a,b:* > suite:a,b:c,* > suite:a,b:c,d,* > suite:a,b:c,d:*
+// suite:a,b:c,d:* > suite:a,b:c,d:x=1;* > suite:a,b:c,d:x=1;y=2;* > suite:a,b:c,d:x=1;y=2
+// suite:a;* (unordered) suite:b;*
+g.test('well_ordered').fn(t => {
+ t.expectWellOrdered(
+ new TestQueryMultiFile('suite', []),
+ new TestQueryMultiFile('suite', ['a']),
+ new TestQueryMultiFile('suite', ['a', 'b']),
+ new TestQueryMultiTest('suite', ['a', 'b'], []),
+ new TestQueryMultiTest('suite', ['a', 'b'], ['c']),
+ new TestQueryMultiTest('suite', ['a', 'b'], ['c', 'd']),
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c', 'd'], {}),
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c', 'd'], { x: 1 }),
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c', 'd'], { x: 1, y: 2 }),
+ new TestQuerySingleCase('suite', ['a', 'b'], ['c', 'd'], { x: 1, y: 2 })
+ );
+ t.expectWellOrdered(
+ new TestQueryMultiFile('suite', []),
+ new TestQueryMultiFile('suite', ['a']),
+ new TestQueryMultiFile('suite', ['a', 'b']),
+ new TestQueryMultiTest('suite', ['a', 'b'], []),
+ new TestQueryMultiTest('suite', ['a', 'b'], ['c']),
+ new TestQueryMultiTest('suite', ['a', 'b'], ['c', 'd']),
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c', 'd'], {}),
+ new TestQuerySingleCase('suite', ['a', 'b'], ['c', 'd'], {})
+ );
+});
+
+g.test('unordered').fn(t => {
+ t.expectUnordered(
+ new TestQueryMultiFile('suite', ['a']), //
+ new TestQueryMultiFile('suite', ['x'])
+ );
+ t.expectUnordered(
+ new TestQueryMultiFile('suite', ['a', 'b']),
+ new TestQueryMultiFile('suite', ['a', 'x'])
+ );
+ t.expectUnordered(
+ new TestQueryMultiTest('suite', ['a', 'b'], ['c']),
+ new TestQueryMultiTest('suite', ['a', 'b'], ['x']),
+ new TestQueryMultiTest('suite', ['a'], []),
+ new TestQueryMultiTest('suite', ['a', 'x'], [])
+ );
+ t.expectUnordered(
+ new TestQueryMultiTest('suite', ['a', 'b'], ['c', 'd']),
+ new TestQueryMultiTest('suite', ['a', 'b'], ['c', 'x']),
+ new TestQueryMultiTest('suite', ['a'], []),
+ new TestQueryMultiTest('suite', ['a', 'x'], [])
+ );
+ t.expectUnordered(
+ new TestQueryMultiTest('suite', ['a', 'b'], ['c', 'd']),
+ new TestQueryMultiTest('suite', ['a', 'b'], ['c', 'x']),
+ new TestQueryMultiTest('suite', ['a'], []),
+ new TestQueryMultiTest('suite', ['a', 'x'], ['c'])
+ );
+ t.expectUnordered(
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c', 'd'], { x: 1 }),
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c', 'd'], { x: 9 }),
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c'], { x: 9 })
+ );
+ t.expectUnordered(
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c', 'd'], { x: 1, y: 2 }),
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c', 'd'], { x: 1, y: 8 }),
+ new TestQueryMultiCase('suite', ['a', 'b'], ['c'], { x: 1, y: 8 })
+ );
+ t.expectUnordered(
+ new TestQuerySingleCase('suite', ['a', 'b'], ['c', 'd'], { x: 1, y: 2 }),
+ new TestQuerySingleCase('suite', ['a', 'b'], ['c', 'd'], { x: 1, y: 8 }),
+ new TestQuerySingleCase('suite', ['a', 'b'], ['c'], { x: 1, y: 8 })
+ );
+ t.expectUnordered(
+ new TestQuerySingleCase('suite1', ['bar', 'buzz', 'buzz'], ['zap'], {}),
+ new TestQueryMultiTest('suite1', ['bar'], [])
+ );
+});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/test_filter.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/test_filter.spec.ts
deleted file mode 100644
index 4b752a66f82..00000000000
--- a/chromium/third_party/webgpu-cts/src/src/unittests/test_filter.spec.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-export const description = `
-Unit tests for test_filter .matches() methods.
-`;
-
-import { FilterByGroup } from '../common/framework/test_filter/filter_by_group.js';
-import {
- FilterByParamsExact,
- FilterByParamsMatch,
- FilterByTestMatch,
-} from '../common/framework/test_filter/filter_one_file.js';
-import { TestGroup } from '../common/framework/test_group.js';
-
-import { UnitTest } from './unit_test.js';
-
-export const g = new TestGroup(UnitTest);
-
-g.test('FilterByGroup/matches', t => {
- {
- const f = new FilterByGroup('ab', 'de/f');
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/fg' } }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/fg' }, test: 'x' }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/fg' }, test: 'x', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/fg' }, test: 'x', params: {} }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/fg/' }, test: 'x', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f/g' }, test: 'x', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f/g/' }, test: 'x', params: null }));
- }
- {
- const f = new FilterByGroup('ab', 'de/f/');
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/fg' } }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/fg' }, test: 'x' }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/fg' }, test: 'x', params: null }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/fg' }, test: 'x', params: {} }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/fg/' }, test: 'x', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f/g' }, test: 'x', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f/g/' }, test: 'x', params: null }));
- }
-});
-
-g.test('FilterByTestMatch/matches', t => {
- const f = new FilterByTestMatch({ suite: 'ab', path: 'de/f' }, 'xy');
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy' }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xyz', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xyz', params: {} }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xyz', params: { z: 1 } }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' } }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f/' }, test: 'xyz', params: null }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/fg' }, test: 'xyz', params: null }));
-});
-
-g.test('FilterByParamsMatch/matches', t => {
- {
- const f = new FilterByParamsMatch({ suite: 'ab', path: 'de/f' }, 'xy', null);
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: {} }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: { z: 1 } }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' } }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy' }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: undefined }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xyz', params: {} }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f/' }, test: 'xy', params: {} }));
- }
- {
- const f = new FilterByParamsMatch({ suite: 'ab', path: 'de/f' }, 'xy', {});
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: {} }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' } }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy' }));
- }
-});
-
-g.test('FilterByParamsExact', t => {
- const f = new FilterByParamsExact({ suite: 'ab', path: 'de/f' }, 'xy', {});
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: null }));
- t.expect(f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: {} }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy', params: { z: 1 } }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xyz', params: {} }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f/' }, test: 'xy', params: {} }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' } }));
- t.expect(!f.matches({ spec: { suite: 'ab', path: 'de/f' }, test: 'xy' }));
-});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/test_group.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/test_group.spec.ts
index 018a90360ef..f9dbb549442 100644
--- a/chromium/third_party/webgpu-cts/src/src/unittests/test_group.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/test_group.spec.ts
@@ -3,31 +3,33 @@ Unit tests for TestGroup.
`;
import { Fixture } from '../common/framework/fixture.js';
-import { poptions } from '../common/framework/params.js';
-import { TestGroup } from '../common/framework/test_group.js';
+import { makeTestGroup, makeTestGroupForUnitTesting } from '../common/framework/test_group.js';
import { assert } from '../common/framework/util/util.js';
import { TestGroupTest } from './test_group_test.js';
import { UnitTest } from './unit_test.js';
-export const g = new TestGroup(TestGroupTest);
+export const g = makeTestGroup(TestGroupTest);
-g.test('UnitTest fixture', async t0 => {
+g.test('UnitTest_fixture').fn(async t0 => {
let seen = 0;
+ /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
function count(t: Fixture): void {
seen++;
}
- const g = new TestGroup(UnitTest);
+ const g = makeTestGroupForUnitTesting(UnitTest);
- g.test('test', count);
- g.test('testp', count).params([{ a: 1 }]);
+ g.test('test').fn(count);
+ g.test('testp')
+ .params([{ a: 1 }])
+ .fn(count);
await t0.run(g);
t0.expect(seen === 2);
});
-g.test('custom fixture', async t0 => {
+g.test('custom_fixture').fn(async t0 => {
let seen = 0;
class Counter extends UnitTest {
count(): void {
@@ -35,21 +37,23 @@ g.test('custom fixture', async t0 => {
}
}
- const g = new TestGroup(Counter);
+ const g = makeTestGroupForUnitTesting(Counter);
- g.test('test', t => {
+ g.test('test').fn(t => {
t.count();
});
- g.test('testp', t => {
- t.count();
- }).params([{ a: 1 }]);
+ g.test('testp')
+ .params([{ a: 1 }])
+ .fn(t => {
+ t.count();
+ });
await t0.run(g);
t0.expect(seen === 2);
});
-g.test('stack', async t0 => {
- const g = new TestGroup(UnitTest);
+g.test('stack').fn(async t0 => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
const doNestedThrow1 = () => {
throw new Error('goodbye');
@@ -57,101 +61,169 @@ g.test('stack', async t0 => {
const doNestedThrow2 = () => doNestedThrow1();
- g.test('fail', t => {
+ g.test('fail').fn(t => {
t.fail();
});
- g.test('throw', t => {
+ /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
+ g.test('throw').fn(t => {
throw new Error('hello');
});
- g.test('throw nested', t => {
+ /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
+ g.test('throw_nested').fn(t => {
doNestedThrow2();
});
const res = await t0.run(g);
- const search = /unittests[\/\\]test_group\.spec\.[tj]s|suites[\/\\]unittests[\/\\]unit_test\.[tj]s/;
- for (const { logs } of res.cases) {
+ const search = /unittests[/\\]test_group\.spec\.[tj]s/;
+ t0.expect(res.size > 0);
+ for (const { logs } of res.values()) {
assert(logs !== undefined, 'expected logs');
- const l = logs[0].toJSON();
- t0.expect(search.test(l));
- const st = l.split('\n');
- t0.expect(search.test(st[st.length - 1]));
+ t0.expect(logs.some(l => search.test(l.toJSON())));
+ t0.expect(search.test(logs[logs.length - 1].toJSON()));
}
});
-g.test('duplicate test name', t => {
- const g = new TestGroup(UnitTest);
- g.test('abc', () => {});
+g.test('duplicate_test_name').fn(t => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('abc').fn(() => {});
t.shouldThrow('Error', () => {
- g.test('abc', () => {});
+ g.test('abc').fn(() => {});
});
});
-g.test('duplicate test params', t => {
- const g = new TestGroup(UnitTest);
+g.test('duplicate_test_params,none').fn(() => {
+ {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('abc')
+ .params([])
+ .fn(() => {});
+ g.checkCaseNamesAndDuplicates();
+ }
- t.shouldThrow('Error', () => {
- g.test('abc', () => {
- //
- }).params([
- { a: 1 }, //
- { a: 1 },
- ]);
- });
+ {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('abc').fn(() => {});
+ g.checkCaseNamesAndDuplicates();
+ }
+
+ {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('abc')
+ .params([
+ { a: 1 }, //
+ ])
+ .fn(() => {});
+ g.checkCaseNamesAndDuplicates();
+ }
});
-g.test('duplicate test params/with different private params', t => {
- const g = new TestGroup(UnitTest);
+g.test('duplicate_test_params,basic').fn(t => {
+ {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('abc')
+ .params([
+ { a: 1 }, //
+ { a: 1 },
+ ])
+ .fn(() => {});
+ t.shouldThrow('Error', () => {
+ g.checkCaseNamesAndDuplicates();
+ });
+ }
+ {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('abc')
+ .params([
+ { a: 1, b: 3 }, //
+ { b: 3, a: 1 },
+ ])
+ .fn(() => {});
+ t.shouldThrow('Error', () => {
+ g.checkCaseNamesAndDuplicates();
+ });
+ }
+});
- t.shouldThrow('Error', () => {
- g.test('abc', () => {
- //
- }).params([
+g.test('duplicate_test_params,with_different_private_params').fn(t => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('abc')
+ .params([
{ a: 1, _b: 1 }, //
{ a: 1, _b: 2 },
- ]);
+ ])
+ .fn(() => {});
+ t.shouldThrow('Error', () => {
+ g.checkCaseNamesAndDuplicates();
});
});
-const badChars = Array.from('"`~@#$+=\\|!^&*[]<>{}-\'.,');
-g.test('invalid test name', t => {
- const g = new TestGroup(UnitTest);
+g.test('invalid_test_name').fn(t => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
- t.shouldThrow('Error', () => {
- g.test('a' + t.params.char + 'b', () => {});
- });
-}).params(poptions('char', badChars));
+ const badChars = Array.from('"`~@#$+=\\|!^&*[]<>{}-\'. ');
+ for (const char of badChars) {
+ const name = 'a' + char + 'b';
+ t.shouldThrow(
+ 'Error',
+ () => {
+ g.test(name).fn(() => {});
+ },
+ name
+ );
+ }
+});
+
+g.test('param_value,valid').fn(() => {
+ const g = makeTestGroup(UnitTest);
+ g.test('a').params([{ x: JSON.stringify({ a: 1, b: 2 }) }]);
+});
+
+g.test('param_value,invalid').fn(t => {
+ for (const badChar of ';=*') {
+ const g = makeTestGroupForUnitTesting(UnitTest);
+ g.test('a').params([{ badChar }]);
+ t.shouldThrow('Error', () => {
+ g.checkCaseNamesAndDuplicates();
+ });
+ }
+});
-g.test('throws', async t0 => {
- const g = new TestGroup(UnitTest);
+g.test('throws').fn(async t0 => {
+ const g = makeTestGroupForUnitTesting(UnitTest);
- g.test('a', t => {
+ /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
+ g.test('a').fn(t => {
throw new Error();
});
const result = await t0.run(g);
- t0.expect(result.cases[0].status === 'fail');
+ const values = Array.from(result.values());
+ t0.expect(values.length === 1);
+ t0.expect(values[0].status === 'fail');
});
-g.test('shouldThrow', async t0 => {
+g.test('shouldThrow').fn(async t0 => {
t0.shouldThrow('TypeError', () => {
throw new TypeError();
});
- const g = new TestGroup(UnitTest);
+ const g = makeTestGroupForUnitTesting(UnitTest);
- g.test('a', t => {
+ g.test('a').fn(t => {
t.shouldThrow('Error', () => {
throw new TypeError();
});
});
const result = await t0.run(g);
- t0.expect(result.cases[0].status === 'fail');
+ const values = Array.from(result.values());
+ t0.expect(values.length === 1);
+ t0.expect(values[0].status === 'fail');
});
-g.test('shouldReject', async t0 => {
+g.test('shouldReject').fn(async t0 => {
t0.shouldReject(
'TypeError',
(async () => {
@@ -159,9 +231,9 @@ g.test('shouldReject', async t0 => {
})()
);
- const g = new TestGroup(UnitTest);
+ const g = makeTestGroupForUnitTesting(UnitTest);
- g.test('a', async t => {
+ g.test('a').fn(async t => {
t.shouldReject(
'Error',
(async () => {
@@ -172,5 +244,7 @@ g.test('shouldReject', async t0 => {
const result = await t0.run(g);
// Fails even though shouldReject doesn't fail until after the test function ends
- t0.expect(result.cases[0].status === 'fail');
+ const values = Array.from(result.values());
+ t0.expect(values.length === 1);
+ t0.expect(values[0].status === 'fail');
});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/test_group_test.ts b/chromium/third_party/webgpu-cts/src/src/unittests/test_group_test.ts
index 0572740e434..b4129583e12 100644
--- a/chromium/third_party/webgpu-cts/src/src/unittests/test_group_test.ts
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/test_group_test.ts
@@ -1,35 +1,23 @@
-import { Fixture } from '../common/framework/fixture.js';
-import { TestCaseID } from '../common/framework/id.js';
-import { LiveTestSpecResult, Logger } from '../common/framework/logger.js';
-import { paramsEquals } from '../common/framework/params_utils.js';
-import { TestGroup } from '../common/framework/test_group.js';
+import { Logger, LogResults } from '../common/framework/logging/logger.js';
+import { TestQuerySingleCase } from '../common/framework/query/query.js';
+import { RunCaseIterable, TestCaseID } from '../common/framework/test_group.js';
+import { objectEquals } from '../common/framework/util/util.js';
import { UnitTest } from './unit_test.js';
export class TestGroupTest extends UnitTest {
- async run<F extends Fixture>(g: TestGroup<F>): Promise<LiveTestSpecResult> {
- const [rec, res] = new Logger().record({ suite: '', path: '' });
- await Promise.all(Array.from(g.iterate(rec)).map(test => test.run()));
- return res;
- }
-
- enumerate<F extends Fixture>(g: TestGroup<F>): TestCaseID[] {
- const cases = [];
- const [rec] = new Logger().record({ suite: '', path: '' });
- for (const test of g.iterate(rec)) {
- cases.push(test.id);
+ async run(g: RunCaseIterable): Promise<LogResults> {
+ const logger = new Logger(true);
+ for (const rc of await Promise.all(g.iterate())) {
+ const query = new TestQuerySingleCase('xx', ['yy'], rc.id.test, rc.id.params);
+ const [rec] = logger.record(query.toString());
+ await rc.run(rec);
}
- return cases;
+ return logger.results;
}
- expectCases<F extends Fixture>(g: TestGroup<F>, cases: TestCaseID[]): void {
- const gcases = this.enumerate(g);
-
- if (this.expect(gcases.length === cases.length)) {
- for (let i = 0; i < cases.length; ++i) {
- this.expect(gcases[i].test === cases[i].test);
- this.expect(paramsEquals(gcases[i].params, cases[i].params));
- }
- }
+ expectCases(g: RunCaseIterable, cases: TestCaseID[]): void {
+ const gcases = Array.from(g.iterate()).map(rc => rc.id);
+ this.expect(objectEquals(gcases, cases));
}
}
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/test_query.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/test_query.spec.ts
new file mode 100644
index 00000000000..7f5e6d01801
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/test_query.spec.ts
@@ -0,0 +1,56 @@
+export const description = `
+Tests for TestQuery
+`;
+import {
+ TestQueryMultiFile,
+ TestQueryMultiTest,
+ TestQueryMultiCase,
+ TestQuerySingleCase,
+ TestQuery,
+} from '../common/framework/query/query.js';
+import { makeTestGroup } from '../common/framework/test_group.js';
+
+import { UnitTest } from './unit_test.js';
+
+class F extends UnitTest {
+ expectToString(q: TestQuery, exp: string) {
+ this.expect(q.toString() === exp);
+ }
+}
+
+export const g = makeTestGroup(F);
+
+g.test('constructor').fn(t => {
+ t.shouldThrow('Error', () => new TestQueryMultiTest('suite', [], []));
+
+ t.shouldThrow('Error', () => new TestQueryMultiCase('suite', ['a'], [], {}));
+ t.shouldThrow('Error', () => new TestQueryMultiCase('suite', [], ['c'], {}));
+ t.shouldThrow('Error', () => new TestQueryMultiCase('suite', [], [], {}));
+
+ t.shouldThrow('Error', () => new TestQuerySingleCase('suite', ['a'], [], {}));
+ t.shouldThrow('Error', () => new TestQuerySingleCase('suite', [], ['c'], {}));
+ t.shouldThrow('Error', () => new TestQuerySingleCase('suite', [], [], {}));
+});
+
+g.test('toString').fn(t => {
+ t.expectToString(new TestQueryMultiFile('s', []), 's:*');
+ t.expectToString(new TestQueryMultiFile('s', ['a']), 's:a,*');
+ t.expectToString(new TestQueryMultiFile('s', ['a', 'b']), 's:a,b,*');
+ t.expectToString(new TestQueryMultiTest('s', ['a', 'b'], []), 's:a,b:*');
+ t.expectToString(new TestQueryMultiTest('s', ['a', 'b'], ['c']), 's:a,b:c,*');
+ t.expectToString(new TestQueryMultiTest('s', ['a', 'b'], ['c', 'd']), 's:a,b:c,d,*');
+ t.expectToString(new TestQueryMultiCase('s', ['a', 'b'], ['c', 'd'], {}), 's:a,b:c,d:*');
+ t.expectToString(
+ new TestQueryMultiCase('s', ['a', 'b'], ['c', 'd'], { x: 1 }),
+ 's:a,b:c,d:x=1;*'
+ );
+ t.expectToString(
+ new TestQueryMultiCase('s', ['a', 'b'], ['c', 'd'], { x: 1, y: 2 }),
+ 's:a,b:c,d:x=1;y=2;*'
+ );
+ t.expectToString(
+ new TestQuerySingleCase('s', ['a', 'b'], ['c', 'd'], { x: 1, y: 2 }),
+ 's:a,b:c,d:x=1;y=2'
+ );
+ t.expectToString(new TestQuerySingleCase('s', ['a', 'b'], ['c', 'd'], {}), 's:a,b:c,d:');
+});
diff --git a/chromium/third_party/webgpu-cts/src/src/unittests/url_query.spec.ts b/chromium/third_party/webgpu-cts/src/src/unittests/url_query.spec.ts
index 9d47cf8d2f6..1a9e8fc3aaf 100644
--- a/chromium/third_party/webgpu-cts/src/src/unittests/url_query.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/unittests/url_query.spec.ts
@@ -2,27 +2,75 @@ export const description = `
Unit tests for URL queries.
`;
-import { TestGroup } from '../common/framework/test_group.js';
-import { makeQueryString } from '../common/framework/url_query.js';
+import {
+ TestQuery,
+ TestQuerySingleCase,
+ TestQueryMultiCase,
+ TestQueryMultiTest,
+ TestQueryMultiFile,
+} from '../common/framework/query/query.js';
+import { makeTestGroup } from '../common/framework/test_group.js';
import { UnitTest } from './unit_test.js';
-export const g = new TestGroup(UnitTest);
+class T extends UnitTest {
+ expectQueryString(q: TestQuery, exp: string): void {
+ const s = q.toString();
+ this.expect(s === exp, `got ${s} expected ${exp}`);
+ }
+}
-g.test('makeQueryString', t => {
- const s = makeQueryString({ suite: 'a', path: 'b/c' }, { test: 'd/e', params: { f: 'g', h: 3 } });
- t.expect(s === 'a:b/c:d/e={"f":"g","h":3}');
+export const g = makeTestGroup(T);
+
+g.test('stringifyQuery,single_case').fn(t => {
+ t.expectQueryString(
+ new TestQuerySingleCase('a', ['b_1', '2_c'], ['d_3', '4_e'], {
+ f: 'g',
+ _pri1: 0,
+ a: 3,
+ _pri2: 1,
+ }),
+ 'a:b_1,2_c:d_3,4_e:f="g";a=3'
+ );
+});
+
+g.test('stringifyQuery,multi_case').fn(t => {
+ t.expectQueryString(
+ new TestQueryMultiCase('a', ['b_1', '2_c'], ['d_3', '4_e'], {
+ f: 'g',
+ _pri1: 0,
+ a: 3,
+ _pri2: 1,
+ }),
+ 'a:b_1,2_c:d_3,4_e:f="g";a=3;*'
+ );
+
+ t.expectQueryString(
+ new TestQueryMultiCase('a', ['b_1', '2_c'], ['d_3', '4_e'], {}),
+ 'a:b_1,2_c:d_3,4_e:*'
+ );
});
-g.test('makeQueryString/private', t => {
- const s = makeQueryString({ suite: 'a', path: 'b' }, { test: 'c', params: { pub: 2, _pri: 3 } });
- t.expect(s === 'a:b:c={"pub":2}');
+g.test('stringifyQuery,multi_test').fn(t => {
+ t.expectQueryString(
+ new TestQueryMultiTest('a', ['b_1', '2_c'], ['d_3', '4_e']),
+ 'a:b_1,2_c:d_3,4_e,*'
+ );
+
+ t.expectQueryString(
+ new TestQueryMultiTest('a', ['b_1', '2_c'], []), //
+ 'a:b_1,2_c:*'
+ );
});
-g.test('makeQueryString/undefined', t => {
- const s = makeQueryString(
- { suite: 'a', path: 'b' },
- { test: 'c', params: { f: undefined, h: 3 } }
+g.test('stringifyQuery,multi_file').fn(t => {
+ t.expectQueryString(
+ new TestQueryMultiFile('a', ['b_1', '2_c']), //
+ 'a:b_1,2_c,*'
+ );
+
+ t.expectQueryString(
+ new TestQueryMultiFile('a', []), //
+ 'a:*'
);
- t.expect(s === 'a:b:c={"h":3}');
});
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/create_mapped.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/create_mapped.spec.ts
index 546abfff508..d99b7f50ae6 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/create_mapped.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/create_mapped.spec.ts
@@ -1,22 +1,23 @@
-export const description = ``;
+export const description = '';
-import { pbool, pcombine, poptions } from '../../../../common/framework/params.js';
-import { TestGroup } from '../../../../common/framework/test_group.js';
+import { params, pbool, poptions } from '../../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { MappingTest } from './mapping_test.js';
-export const g = new TestGroup(MappingTest);
+export const g = makeTestGroup(MappingTest);
-g.test('createBufferMapped', async t => {
- const size = t.params.size;
- const [buffer, arrayBuffer] = t.device.createBufferMapped({
- size,
- usage: GPUBufferUsage.COPY_SRC | (t.params.mappable ? GPUBufferUsage.MAP_WRITE : 0),
- });
- t.checkMapWrite(buffer, arrayBuffer, size);
-}).params(
- pcombine(
- poptions('size', [12, 512 * 1024]), //
- pbool('mappable')
+g.test('createBufferMapped')
+ .params(
+ params()
+ .combine(poptions('size', [12, 512 * 1024]))
+ .combine(pbool('mappable'))
)
-);
+ .fn(t => {
+ const { size, mappable } = t.params;
+ const [buffer, arrayBuffer] = t.device.createBufferMapped({
+ size,
+ usage: GPUBufferUsage.COPY_SRC | (mappable ? GPUBufferUsage.MAP_WRITE : 0),
+ });
+ t.checkMapWrite(buffer, arrayBuffer, size);
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map.spec.ts
index 34817452240..562de03d741 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map.spec.ts
@@ -1,52 +1,57 @@
-export const description = ``;
+export const description = '';
-import { pbool, pcombine, poptions } from '../../../../common/framework/params.js';
-import { TestGroup } from '../../../../common/framework/test_group.js';
+import { pbool, poptions, params } from '../../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { MappingTest } from './mapping_test.js';
-export const g = new TestGroup(MappingTest);
+export const g = makeTestGroup(MappingTest);
-g.test('mapWriteAsync', async t => {
- const size = t.params.size;
- const buffer = t.device.createBuffer({
- size,
- usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
- });
-
- const arrayBuffer = await buffer.mapWriteAsync();
- t.checkMapWrite(buffer, arrayBuffer, size);
-}).params(poptions('size', [12, 512 * 1024]));
-
-g.test('mapReadAsync', async t => {
- const size = t.params.size;
+g.test('mapWriteAsync')
+ .params(poptions('size', [12, 512 * 1024]))
+ .fn(async t => {
+ const { size } = t.params;
+ const buffer = t.device.createBuffer({
+ size,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
+ });
- const [buffer, init] = t.device.createBufferMapped({
- size,
- usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ const arrayBuffer = await buffer.mapWriteAsync();
+ t.checkMapWrite(buffer, arrayBuffer, size);
});
- const expected = new Uint32Array(new ArrayBuffer(size));
- const data = new Uint32Array(init);
- for (let i = 0; i < data.length; ++i) {
- data[i] = expected[i] = i + 1;
- }
- buffer.unmap();
-
- const actual = new Uint8Array(await buffer.mapReadAsync());
- t.expectBuffer(actual, new Uint8Array(expected.buffer));
-}).params(poptions('size', [12, 512 * 1024]));
-
-g.test('createBufferMapped', async t => {
- const size = t.params.size;
- const [buffer, arrayBuffer] = t.device.createBufferMapped({
- size,
- usage: GPUBufferUsage.COPY_SRC | (t.params.mappable ? GPUBufferUsage.MAP_WRITE : 0),
+g.test('mapReadAsync')
+ .params(poptions('size', [12, 512 * 1024]))
+ .fn(async t => {
+ const { size } = t.params;
+
+ const [buffer, init] = t.device.createBufferMapped({
+ size,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
+ });
+
+ const expected = new Uint32Array(new ArrayBuffer(size));
+ const data = new Uint32Array(init);
+ for (let i = 0; i < data.length; ++i) {
+ data[i] = expected[i] = i + 1;
+ }
+ buffer.unmap();
+
+ const actual = new Uint8Array(await buffer.mapReadAsync());
+ t.expectBuffer(actual, new Uint8Array(expected.buffer));
});
- t.checkMapWrite(buffer, arrayBuffer, size);
-}).params(
- pcombine(
- poptions('size', [12, 512 * 1024]), //
- pbool('mappable')
+
+g.test('createBufferMapped')
+ .params(
+ params()
+ .combine(poptions('size', [12, 512 * 1024]))
+ .combine(pbool('mappable'))
)
-);
+ .fn(async t => {
+ const { size, mappable } = t.params;
+ const [buffer, arrayBuffer] = t.device.createBufferMapped({
+ size,
+ usage: GPUBufferUsage.COPY_SRC | (mappable ? GPUBufferUsage.MAP_WRITE : 0),
+ });
+ t.checkMapWrite(buffer, arrayBuffer, size);
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_detach.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_detach.spec.ts
index 8835a379e19..5cad48e7303 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_detach.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_detach.spec.ts
@@ -1,6 +1,6 @@
-export const description = ``;
+export const description = '';
-import { TestGroup } from '../../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { GPUTest } from '../../../gpu_test.js';
class F extends GPUTest {
@@ -17,45 +17,51 @@ class F extends GPUTest {
}
}
-export const g = new TestGroup(F);
-
-g.test('mapWriteAsync', async t => {
- const buffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.MAP_WRITE });
- const arrayBuffer = await buffer.mapWriteAsync();
- t.checkDetach(buffer, arrayBuffer, t.params.unmap, t.params.destroy);
-}).params([
- { unmap: true, destroy: false }, //
- { unmap: false, destroy: true },
- { unmap: true, destroy: true },
-]);
-
-g.test('mapReadAsync', async t => {
- const buffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.MAP_READ });
- const arrayBuffer = await buffer.mapReadAsync();
- t.checkDetach(buffer, arrayBuffer, t.params.unmap, t.params.destroy);
-}).params([
- { unmap: true, destroy: false }, //
- { unmap: false, destroy: true },
- { unmap: true, destroy: true },
-]);
-
-g.test('create mapped', async t => {
- const desc = {
- size: 4,
- usage: GPUBufferUsage.MAP_WRITE,
- };
- const [buffer, arrayBuffer] = t.device.createBufferMapped(desc);
-
- const view = new Uint8Array(arrayBuffer);
- t.expect(arrayBuffer.byteLength === 4);
- t.expect(view.length === 4);
-
- if (t.params.unmap) buffer.unmap();
- if (t.params.destroy) buffer.destroy();
- t.expect(arrayBuffer.byteLength === 0, 'ArrayBuffer should be detached');
- t.expect(view.byteLength === 0, 'ArrayBufferView should be detached');
-}).params([
- { unmap: true, destroy: false },
- { unmap: false, destroy: true },
- { unmap: true, destroy: true },
-]);
+export const g = makeTestGroup(F);
+
+g.test('mapWriteAsync')
+ .params([
+ { unmap: true, destroy: false }, //
+ { unmap: false, destroy: true },
+ { unmap: true, destroy: true },
+ ])
+ .fn(async t => {
+ const buffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.MAP_WRITE });
+ const arrayBuffer = await buffer.mapWriteAsync();
+ t.checkDetach(buffer, arrayBuffer, t.params.unmap, t.params.destroy);
+ });
+
+g.test('mapReadAsync')
+ .params([
+ { unmap: true, destroy: false }, //
+ { unmap: false, destroy: true },
+ { unmap: true, destroy: true },
+ ])
+ .fn(async t => {
+ const buffer = t.device.createBuffer({ size: 4, usage: GPUBufferUsage.MAP_READ });
+ const arrayBuffer = await buffer.mapReadAsync();
+ t.checkDetach(buffer, arrayBuffer, t.params.unmap, t.params.destroy);
+ });
+
+g.test('create_mapped')
+ .params([
+ { unmap: true, destroy: false },
+ { unmap: false, destroy: true },
+ { unmap: true, destroy: true },
+ ])
+ .fn(async t => {
+ const desc = {
+ size: 4,
+ usage: GPUBufferUsage.MAP_WRITE,
+ };
+ const [buffer, arrayBuffer] = t.device.createBufferMapped(desc);
+
+ const view = new Uint8Array(arrayBuffer);
+ t.expect(arrayBuffer.byteLength === 4);
+ t.expect(view.length === 4);
+
+ if (t.params.unmap) buffer.unmap();
+ if (t.params.destroy) buffer.destroy();
+ t.expect(arrayBuffer.byteLength === 0, 'ArrayBuffer should be detached');
+ t.expect(view.byteLength === 0, 'ArrayBufferView should be detached');
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_oom.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_oom.spec.ts
index 3ea113677b4..cbc19d10090 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_oom.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/buffers/map_oom.spec.ts
@@ -1,29 +1,33 @@
-export const description = ``;
+export const description = '';
-import { TestGroup } from '../../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { GPUTest } from '../../../gpu_test.js';
-function getBufferDesc(): GPUBufferDescriptor {
+function getBufferDesc(usage: GPUBufferUsageFlags): GPUBufferDescriptor {
return {
size: Number.MAX_SAFE_INTEGER,
- usage: GPUBufferUsage.MAP_WRITE,
+ usage,
};
}
-export const g = new TestGroup(GPUTest);
+export const g = makeTestGroup(GPUTest);
-g.test('mapWriteAsync', async t => {
- const buffer = t.device.createBuffer(getBufferDesc());
- t.shouldReject('RangeError', buffer.mapWriteAsync());
+g.test('mapWriteAsync').fn(async t => {
+ const buffer = t.expectGPUError('out-of-memory', () => {
+ return t.device.createBuffer(getBufferDesc(GPUBufferUsage.MAP_WRITE));
+ });
+ t.shouldReject('OperationError', buffer.mapWriteAsync());
});
-g.test('mapReadAsync', async t => {
- const buffer = t.device.createBuffer(getBufferDesc());
- t.shouldReject('RangeError', buffer.mapReadAsync());
+g.test('mapReadAsync').fn(async t => {
+ const buffer = t.expectGPUError('out-of-memory', () => {
+ return t.device.createBuffer(getBufferDesc(GPUBufferUsage.MAP_READ));
+ });
+ t.shouldReject('OperationError', buffer.mapReadAsync());
});
-g.test('createBufferMapped', async t => {
+g.test('createBufferMapped').fn(async t => {
t.shouldThrow('RangeError', () => {
- t.device.createBufferMapped(getBufferDesc());
+ t.device.createBufferMapped(getBufferDesc(GPUBufferUsage.COPY_SRC));
});
});
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/basic.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/basic.spec.ts
index 1a9eec72703..54927a5e6ee 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/basic.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/basic.spec.ts
@@ -2,12 +2,12 @@ export const description = `
Basic tests.
`;
-import { TestGroup } from '../../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { GPUTest } from '../../../gpu_test.js';
-export const g = new TestGroup(GPUTest);
+export const g = makeTestGroup(GPUTest);
-g.test('empty', async t => {
+g.test('empty').fn(async t => {
const encoder = t.device.createCommandEncoder();
const cmd = encoder.finish();
t.device.defaultQueue.submit([cmd]);
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/compute/basic.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/compute/basic.spec.ts
index 00357959d33..856794f7fb6 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/compute/basic.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/compute/basic.spec.ts
@@ -2,12 +2,12 @@ export const description = `
Basic command buffer compute tests.
`;
-import { TestGroup } from '../../../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
import { GPUTest } from '../../../../gpu_test.js';
-export const g = new TestGroup(GPUTest);
+export const g = makeTestGroup(GPUTest);
-g.test('memcpy', async t => {
+g.test('memcpy').fn(async t => {
const data = new Uint32Array([0x01020304]);
const [src, srcData] = t.device.createBufferMapped({
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/copies.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/copies.spec.ts
index 3b11273ccc1..d794dfc60c8 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/copies.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/copies.spec.ts
@@ -2,12 +2,12 @@ export const description = `
copy{Buffer,Texture}To{Buffer,Texture} tests.
`;
-import { TestGroup } from '../../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { GPUTest } from '../../../gpu_test.js';
-export const g = new TestGroup(GPUTest);
+export const g = makeTestGroup(GPUTest);
-g.test('b2b', async t => {
+g.test('b2b').fn(async t => {
const data = new Uint32Array([0x01020304]);
const [src, map] = t.device.createBufferMapped({
@@ -29,7 +29,7 @@ g.test('b2b', async t => {
t.expectContents(dst, data);
});
-g.test('b2t2b', async t => {
+g.test('b2t2b').fn(async t => {
const data = new Uint32Array([0x01020304]);
const [src, map] = t.device.createBufferMapped({
@@ -66,7 +66,7 @@ g.test('b2t2b', async t => {
t.expectContents(dst, data);
});
-g.test('b2t2t2b', async t => {
+g.test('b2t2t2b').fn(async t => {
const data = new Uint32Array([0x01020304]);
const [src, map] = t.device.createBufferMapped({
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/basic.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/basic.spec.ts
index ca837240e10..eb86f02188c 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/basic.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/basic.spec.ts
@@ -2,12 +2,12 @@ export const description = `
Basic command buffer rendering tests.
`;
-import { TestGroup } from '../../../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
import { GPUTest } from '../../../../gpu_test.js';
-export const g = new TestGroup(GPUTest);
+export const g = makeTestGroup(GPUTest);
-g.test('clear', async t => {
+g.test('clear').fn(async t => {
const dst = t.device.createBuffer({
size: 4,
usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/rendering.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/rendering.spec.ts
index 76d71cbdc45..8952dcdf4a8 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/rendering.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/rendering.spec.ts
@@ -1,11 +1,11 @@
-export const description = ``;
+export const description = '';
-import { TestGroup } from '../../../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
import { GPUTest } from '../../../../gpu_test.js';
-export const g = new TestGroup(GPUTest);
+export const g = makeTestGroup(GPUTest);
-g.test('fullscreen quad', async t => {
+g.test('fullscreen_quad').fn(async t => {
const dst = t.device.createBuffer({
size: 4,
usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/storeop.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/storeop.spec.ts
index 704054b2ca5..6418f6cd88c 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/storeop.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/command_buffer/render/storeop.spec.ts
@@ -1,79 +1,74 @@
export const description = `
renderPass store op test that drawn quad is either stored or cleared based on storeop`;
-import { TestGroup } from '../../../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
import { GPUTest } from '../../../../gpu_test.js';
-export const g = new TestGroup(GPUTest);
+export const g = makeTestGroup(GPUTest);
-g.test('storeOp controls whether 1x1 drawn quad is stored', async t => {
- const renderTexture = t.device.createTexture({
- size: { width: 1, height: 1, depth: 1 },
- format: 'r8unorm',
- usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.OUTPUT_ATTACHMENT,
- });
+g.test('storeOp_controls_whether_1x1_drawn_quad_is_stored')
+ .params([
+ { storeOp: 'store', _expected: 1 }, //
+ { storeOp: 'clear', _expected: 0 },
+ ] as const)
+ .fn(async t => {
+ const renderTexture = t.device.createTexture({
+ size: { width: 1, height: 1, depth: 1 },
+ format: 'r8unorm',
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.OUTPUT_ATTACHMENT,
+ });
- // create render pipeline
- const vertexModule = t.makeShaderModule('vertex', {
- glsl: `
- #version 450
- const vec2 pos[3] = vec2[3](
- vec2( 1.0f, -1.0f),
- vec2( 1.0f, 1.0f),
- vec2(-1.0f, 1.0f)
- );
+ // create render pipeline
+ const vertexModule = t.makeShaderModule('vertex', {
+ glsl: `
+ #version 450
+ const vec2 pos[3] = vec2[3](
+ vec2( 1.0f, -1.0f),
+ vec2( 1.0f, 1.0f),
+ vec2(-1.0f, 1.0f)
+ );
- void main() {
- gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
- }
- `,
- });
- const fragmentModule = t.makeShaderModule('fragment', {
- glsl: `
+ void main() {
+ gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
+ }
+ `,
+ });
+ const fragmentModule = t.makeShaderModule('fragment', {
+ glsl: `
#version 450
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`,
- });
- const renderPipeline = t.device.createRenderPipeline({
- vertexStage: { module: vertexModule, entryPoint: 'main' },
- fragmentStage: { module: fragmentModule, entryPoint: 'main' },
- layout: t.device.createPipelineLayout({ bindGroupLayouts: [] }),
- primitiveTopology: 'triangle-list',
- colorStates: [{ format: 'r8unorm' }],
- });
+ });
+ const renderPipeline = t.device.createRenderPipeline({
+ vertexStage: { module: vertexModule, entryPoint: 'main' },
+ fragmentStage: { module: fragmentModule, entryPoint: 'main' },
+ layout: t.device.createPipelineLayout({ bindGroupLayouts: [] }),
+ primitiveTopology: 'triangle-list',
+ colorStates: [{ format: 'r8unorm' }],
+ });
- // encode pass and submit
- const encoder = t.device.createCommandEncoder();
- const pass = encoder.beginRenderPass({
- colorAttachments: [
- {
- attachment: renderTexture.createView(),
- storeOp: t.params.storeOp,
- loadValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
- },
- ],
- });
- pass.setPipeline(renderPipeline);
- pass.draw(3, 1, 0, 0);
- pass.endPass();
- const dstBuffer = t.device.createBuffer({
- size: 4,
- usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
- });
- encoder.copyTextureToBuffer(
- { texture: renderTexture },
- { buffer: dstBuffer, bytesPerRow: 256 },
- { width: 1, height: 1, depth: 1 }
- );
- t.device.defaultQueue.submit([encoder.finish()]);
+ // encode pass and submit
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ attachment: renderTexture.createView(),
+ storeOp: t.params.storeOp,
+ loadValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
+ },
+ ],
+ });
+ pass.setPipeline(renderPipeline);
+ pass.draw(3, 1, 0, 0);
+ pass.endPass();
+ t.device.defaultQueue.submit([encoder.finish()]);
- // expect the buffer to be clear
- const expectedContent = new Uint32Array([t.params._expected]);
- t.expectContents(dstBuffer, expectedContent);
-}).params([
- { storeOp: 'store', _expected: 255 }, //
- { storeOp: 'clear', _expected: 0 },
-]);
+ // expect the buffer to be clear
+ t.expectSingleColor(renderTexture, 'r8unorm', {
+ size: [1, 1, 1],
+ exp: { R: t.params._expected },
+ });
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/fences.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/fences.spec.ts
index 698cbce33cb..7b9dbf9d05d 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/fences.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/fences.spec.ts
@@ -1,29 +1,29 @@
-export const description = ``;
+export const description = '';
-import { attemptGarbageCollection } from '../../../common/framework/collect_garbage.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { attemptGarbageCollection } from '../../../common/framework/util/collect_garbage.js';
import { raceWithRejectOnTimeout } from '../../../common/framework/util/util.js';
import { GPUTest } from '../../gpu_test.js';
-export const g = new TestGroup(GPUTest);
+export const g = makeTestGroup(GPUTest);
-g.test('initial/no descriptor', t => {
+g.test('initial,no_descriptor').fn(t => {
const fence = t.queue.createFence();
t.expect(fence.getCompletedValue() === 0);
});
-g.test('initial/empty descriptor', t => {
+g.test('initial,empty_descriptor').fn(t => {
const fence = t.queue.createFence({});
t.expect(fence.getCompletedValue() === 0);
});
-g.test('initial/descriptor with initialValue', t => {
+g.test('initial,descriptor_with_initialValue').fn(t => {
const fence = t.queue.createFence({ initialValue: 2 });
t.expect(fence.getCompletedValue() === 2);
});
// Promise resolves when onCompletion value is less than signal value.
-g.test('wait/less than signaled', async t => {
+g.test('wait,less_than_signaled').fn(async t => {
const fence = t.queue.createFence();
t.queue.signal(fence, 2);
await fence.onCompletion(1);
@@ -31,7 +31,7 @@ g.test('wait/less than signaled', async t => {
});
// Promise resolves when onCompletion value is equal to signal value.
-g.test('wait/equal to signaled', async t => {
+g.test('wait,equal_to_signaled').fn(async t => {
const fence = t.queue.createFence();
t.queue.signal(fence, 2);
await fence.onCompletion(2);
@@ -39,7 +39,7 @@ g.test('wait/equal to signaled', async t => {
});
// All promises resolve when signal is called once.
-g.test('wait/signaled once', async t => {
+g.test('wait,signaled_once').fn(async t => {
const fence = t.queue.createFence();
t.queue.signal(fence, 20);
const promises = [];
@@ -54,7 +54,7 @@ g.test('wait/signaled once', async t => {
});
// Promise resolves when signal is called multiple times.
-g.test('wait/signaled multiple times', async t => {
+g.test('wait,signaled_multiple_times').fn(async t => {
const fence = t.queue.createFence();
t.queue.signal(fence, 1);
t.queue.signal(fence, 2);
@@ -63,7 +63,7 @@ g.test('wait/signaled multiple times', async t => {
});
// Promise resolves if fence has already completed.
-g.test('wait/already completed', async t => {
+g.test('wait,already_completed').fn(async t => {
const fence = t.queue.createFence();
t.queue.signal(fence, 2);
@@ -81,7 +81,7 @@ g.test('wait/already completed', async t => {
});
// Test many calls to signal and wait on fence values one at a time.
-g.test('wait/many/serially', async t => {
+g.test('wait,many,serially').fn(async t => {
const fence = t.queue.createFence();
for (let i = 1; i <= 20; ++i) {
t.queue.signal(fence, i);
@@ -91,7 +91,7 @@ g.test('wait/many/serially', async t => {
});
// Test many calls to signal and wait on all fence values.
-g.test('wait/many/parallel', async t => {
+g.test('wait,many,parallel').fn(async t => {
const fence = t.queue.createFence();
const promises = [];
for (let i = 1; i <= 20; ++i) {
@@ -107,7 +107,7 @@ g.test('wait/many/parallel', async t => {
});
// Test onCompletion promise resolves within a time limit.
-g.test('wait/resolves within timeout', t => {
+g.test('wait,resolves_within_timeout').fn(t => {
const fence = t.queue.createFence();
t.queue.signal(fence, 2);
@@ -122,23 +122,23 @@ g.test('wait/resolves within timeout', t => {
});
// Test dropping references to the fence and onCompletion promise does not crash.
-g.test('drop/fence and promise', t => {
+g.test('drop,fence_and_promise').fn(async t => {
{
const fence = t.queue.createFence();
t.queue.signal(fence, 2);
fence.onCompletion(2);
}
- attemptGarbageCollection();
+ await attemptGarbageCollection();
});
// Test dropping references to the fence and holding the promise does not crash.
-g.test('drop/promise', async t => {
+g.test('drop,promise').fn(async t => {
let promise;
{
const fence = t.queue.createFence();
t.queue.signal(fence, 2);
promise = fence.onCompletion(2);
}
- attemptGarbageCollection();
+ await attemptGarbageCollection();
await promise;
});
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/copied_texture_clear.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/copied_texture_clear.spec.ts
new file mode 100644
index 00000000000..5e81506d710
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/copied_texture_clear.spec.ts
@@ -0,0 +1,86 @@
+export const description = 'Test uninitialized textures are initialized to zero when copied.';
+
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert, unreachable } from '../../../../common/framework/util/util.js';
+import { SubresourceRange } from '../../../util/texture/subresource.js';
+
+import { InitializedState, ReadMethod, TextureZeroInitTest } from './texture_zero_init_test.js';
+
+class CopiedTextureClearTest extends TextureZeroInitTest {
+ private checkContentsByBufferCopy(
+ texture: GPUTexture,
+ state: InitializedState,
+ subresourceRange: SubresourceRange
+ ): void {
+ for (const { level: mipLevel, slice } of subresourceRange.each()) {
+ assert(this.params.dimension === '2d');
+
+ this.expectSingleColor(texture, this.params.format, {
+ size: [this.textureWidth, this.textureHeight, 1],
+ dimension: this.params.dimension,
+ slice,
+ layout: { mipLevel },
+ exp: this.stateToTexelComponents[state],
+ });
+ }
+ }
+
+ private checkContentsByTextureCopy(
+ texture: GPUTexture,
+ state: InitializedState,
+ subresourceRange: SubresourceRange
+ ): void {
+ for (const { level, slice } of subresourceRange.each()) {
+ assert(this.params.dimension === '2d');
+
+ const width = this.textureWidth >> level;
+ const height = this.textureHeight >> level;
+
+ const dst = this.device.createTexture({
+ size: [width, height, 1],
+ format: this.params.format,
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
+ });
+
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.copyTextureToTexture(
+ { texture, mipLevel: level, arrayLayer: slice },
+ { texture: dst, mipLevel: 0, arrayLayer: 0 },
+ { width, height, depth: 1 }
+ );
+ this.queue.submit([commandEncoder.finish()]);
+
+ this.expectSingleColor(dst, this.params.format, {
+ size: [width, height, 1],
+ exp: this.stateToTexelComponents[state],
+ });
+ }
+ }
+
+ checkContents(
+ texture: GPUTexture,
+ state: InitializedState,
+ subresourceRange: SubresourceRange
+ ): void {
+ switch (this.params.readMethod) {
+ case ReadMethod.CopyToBuffer:
+ this.checkContentsByBufferCopy(texture, state, subresourceRange);
+ break;
+
+ case ReadMethod.CopyToTexture:
+ this.checkContentsByTextureCopy(texture, state, subresourceRange);
+ break;
+
+ default:
+ unreachable();
+ }
+ }
+}
+
+export const g = makeTestGroup(CopiedTextureClearTest);
+
+g.test('uninitialized_texture_is_zero')
+ .params(TextureZeroInitTest.generateParams([ReadMethod.CopyToBuffer, ReadMethod.CopyToTexture]))
+ .fn(t => {
+ t.run();
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/depth_stencil_attachment_clear.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/depth_stencil_attachment_clear.spec.ts
new file mode 100644
index 00000000000..ef316a9119e
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/depth_stencil_attachment_clear.spec.ts
@@ -0,0 +1,211 @@
+export const description =
+ 'Test uninitialized textures are initialized to zero when used as a depth/stencil attachment.';
+
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { unreachable } from '../../../../common/framework/util/util.js';
+import { SubresourceRange } from '../../../util/texture/subresource.js';
+
+import {
+ InitializedState,
+ ReadMethod,
+ TextureZeroInitTest,
+ initializedStateAsDepth,
+ initializedStateAsStencil,
+} from './texture_zero_init_test.js';
+
+class DepthStencilAttachmentClearTest extends TextureZeroInitTest {
+ // Construct a pipeline which will render a single triangle with depth
+ // equal to |initializeStateAsDepth(state)|. The depth compare function
+ // is set to "equal" so the fragment shader will only write 1.0 to the
+ // R8Unorm output if the depth buffer contains exactly the expected value.
+ private getDepthTestReadbackPipeline(
+ state: InitializedState,
+ format: GPUTextureFormat,
+ sampleCount: number
+ ): GPURenderPipeline {
+ return this.device.createRenderPipeline({
+ vertexStage: {
+ entryPoint: 'main',
+ module: this.makeShaderModule('vertex', {
+ glsl: `#version 310 es
+ void main() {
+ const vec2 pos[3] = vec2[3](
+ vec2(-1.f, -3.f), vec2(3.f, 1.f), vec2(-1.f, 1.f));
+ gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f);
+ }
+ `,
+ }),
+ },
+ fragmentStage: {
+ entryPoint: 'main',
+ module: this.makeShaderModule('fragment', {
+ glsl: `#version 310 es
+ precision highp float;
+ layout(location = 0) out float outSuccess;
+
+ void main() {
+ gl_FragDepth = float(${initializedStateAsDepth(state)});
+ outSuccess = 1.0;
+ }
+ `,
+ }),
+ },
+ colorStates: [
+ {
+ format: 'r8unorm',
+ },
+ ],
+ depthStencilState: {
+ format,
+ depthCompare: 'equal',
+ },
+ primitiveTopology: 'triangle-list',
+ sampleCount,
+ });
+ }
+
+ // Construct a pipeline which will render a single triangle.
+ // The stencil compare function is set to "equal" so the fragment shader
+ // will only write 1.0 to the R8Unorm output if the stencil buffer contains
+ // exactly the stencil reference value.
+ private getStencilTestReadbackPipeline(
+ format: GPUTextureFormat,
+ sampleCount: number
+ ): GPURenderPipeline {
+ return this.device.createRenderPipeline({
+ vertexStage: {
+ entryPoint: 'main',
+ module: this.makeShaderModule('vertex', {
+ glsl: `#version 310 es
+ void main() {
+ const vec2 pos[3] = vec2[3](
+ vec2(-1.f, -3.f), vec2(3.f, 1.f), vec2(-1.f, 1.f));
+ gl_Position = vec4(pos[gl_VertexIndex], 0.f, 1.f);
+ }
+ `,
+ }),
+ },
+ fragmentStage: {
+ entryPoint: 'main',
+ module: this.makeShaderModule('fragment', {
+ glsl: `#version 310 es
+ precision highp float;
+ layout(location = 0) out float outSuccess;
+
+ void main() {
+ outSuccess = 1.0;
+ }
+ `,
+ }),
+ },
+ colorStates: [
+ {
+ format: 'r8unorm',
+ },
+ ],
+ depthStencilState: {
+ format,
+ stencilFront: {
+ compare: 'equal',
+ },
+ stencilBack: {
+ compare: 'equal',
+ },
+ },
+ primitiveTopology: 'triangle-list',
+ sampleCount,
+ });
+ }
+
+ // Check the contents by running either a depth or stencil test. The test will
+ // render 1.0 to an R8Unorm texture if the depth/stencil buffer is equal to the expected
+ // value. This is done by using a depth compare function and explicitly setting the depth
+ // value with gl_FragDepth in the shader, or by using a stencil compare function and
+ // setting the stencil reference value in the render pass.
+ checkContents(
+ texture: GPUTexture,
+ state: InitializedState,
+ subresourceRange: SubresourceRange
+ ): void {
+ for (const viewDescriptor of this.generateTextureViewDescriptorsForRendering(
+ this.params.aspect,
+ subresourceRange
+ )) {
+ const width = this.textureWidth >> viewDescriptor.baseMipLevel!;
+ const height = this.textureHeight >> viewDescriptor.baseMipLevel!;
+
+ const renderTexture = this.device.createTexture({
+ size: [width, height, 1],
+ format: 'r8unorm',
+ usage: GPUTextureUsage.OUTPUT_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ sampleCount: this.params.sampleCount,
+ });
+
+ let resolveTexture = undefined;
+ let resolveTarget = undefined;
+ if (this.params.sampleCount > 1) {
+ resolveTexture = this.device.createTexture({
+ size: [width, height, 1],
+ format: 'r8unorm',
+ usage: GPUTextureUsage.OUTPUT_ATTACHMENT | GPUTextureUsage.COPY_SRC,
+ });
+ resolveTarget = resolveTexture.createView();
+ }
+
+ const commandEncoder = this.device.createCommandEncoder();
+ const pass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ attachment: renderTexture.createView(),
+ resolveTarget,
+ loadValue: [0, 0, 0, 0],
+ storeOp: 'store',
+ },
+ ],
+ depthStencilAttachment: {
+ attachment: texture.createView(viewDescriptor),
+ depthStoreOp: 'store',
+ depthLoadValue: 'load',
+ stencilStoreOp: 'store',
+ stencilLoadValue: 'load',
+ },
+ });
+
+ switch (this.params.readMethod) {
+ case ReadMethod.DepthTest:
+ pass.setPipeline(
+ this.getDepthTestReadbackPipeline(state, this.params.format, this.params.sampleCount)
+ );
+ break;
+
+ case ReadMethod.StencilTest:
+ pass.setPipeline(
+ this.getStencilTestReadbackPipeline(this.params.format, this.params.sampleCount)
+ );
+ // Set the stencil reference. The rendering pipeline uses stencil compare function "equal"
+ // so this pass will write 1.0 to the output only if the stencil buffer is equal to this
+ // reference value.
+ pass.setStencilReference(initializedStateAsStencil(state));
+ break;
+
+ default:
+ unreachable();
+ }
+ pass.draw(3, 1, 0, 0);
+ pass.endPass();
+
+ this.queue.submit([commandEncoder.finish()]);
+
+ this.expectSingleColor(resolveTexture || renderTexture, 'r8unorm', {
+ size: [width, height, 1],
+ exp: { R: 1 },
+ });
+ }
+ }
+}
+
+export const g = makeTestGroup(DepthStencilAttachmentClearTest);
+
+g.test('uninitialized_texture_is_zero')
+ .params(TextureZeroInitTest.generateParams([ReadMethod.DepthTest, ReadMethod.StencilTest]))
+ .fn(t => t.run());
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/sampled_texture_clear.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/sampled_texture_clear.spec.ts
index ca889f023cd..3463222a90a 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/sampled_texture_clear.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/sampled_texture_clear.spec.ts
@@ -1,73 +1,207 @@
-export const description = `
-computePass test that sampled texture is cleared`;
-
-import { TestGroup } from '../../../../common/framework/test_group.js';
-import { GPUTest } from '../../../gpu_test.js';
-
-export const g = new TestGroup(GPUTest);
-
-g.test('compute pass test that sampled texture is cleared', async t => {
- const texture = t.device.createTexture({
- size: { width: 256, height: 256, depth: 1 },
- format: 'r8unorm',
- usage: GPUTextureUsage.SAMPLED,
- });
-
- const bufferTex = t.device.createBuffer({
- size: 4 * 256 * 256,
- usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
- });
-
- const sampler = t.device.createSampler();
-
- const bindGroupLayout = t.device.createBindGroupLayout({
- entries: [
- { binding: 0, visibility: GPUShaderStage.COMPUTE, type: 'sampled-texture' },
- { binding: 1, visibility: GPUShaderStage.COMPUTE, type: 'storage-buffer' },
- { binding: 2, visibility: GPUShaderStage.COMPUTE, type: 'sampler' },
- ],
- });
-
- // create compute pipeline
- const computeModule = t.makeShaderModule('compute', {
- glsl: `
- #version 450
- layout(binding = 0) uniform texture2D sampleTex;
- layout(std430, binding = 1) buffer BufferTex {
- vec4 result;
- } bufferTex;
- layout(binding = 2) uniform sampler sampler0;
+export const description = 'Test uninitialized textures are initialized to zero when sampled.';
+
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { assert } from '../../../../common/framework/util/util.js';
+import { SubresourceRange } from '../../../util/texture/subresource.js';
+import { getTexelDataRepresentation } from '../../../util/texture/texelData.js';
+
+import {
+ InitializedState,
+ ReadMethod,
+ TextureZeroInitTest,
+ initializedStateAsFloat,
+ initializedStateAsSint,
+ initializedStateAsUint,
+} from './texture_zero_init_test.js';
+
+class SampledTextureClearTest extends TextureZeroInitTest {
+ private getSamplingReadbackPipeline(
+ prefix: string,
+ sampleCount: number,
+ dimension: GPUTextureDimension
+ ): GPUComputePipeline {
+ const componentOrder = getTexelDataRepresentation(this.params.format).componentOrder;
+ const MS = sampleCount > 1 ? 'MS' : '';
+ const XD = dimension.toUpperCase();
+ const componentCount = componentOrder.length;
+ const indexExpression =
+ componentCount === 1
+ ? componentOrder[0].toLowerCase()
+ : componentOrder.map(c => c.toLowerCase()).join('') + '[i]';
+
+ const glsl = `#version 310 es
+ precision highp float;
+ precision highp ${prefix}texture${XD}${MS};
+ precision highp sampler;
+
+ layout(set = 0, binding = 0, std140) uniform Constants {
+ int level;
+ };
+
+ layout(set = 0, binding = 1) uniform ${prefix}texture${XD}${MS} myTexture;
+ layout(set = 0, binding = 2) uniform sampler mySampler;
+ layout(set = 0, binding = 3, std430) writeonly buffer Result {
+ uint result[];
+ };
+
+ void writeResult(uint flatIndex, uvec4 texel) {
+ for (uint i = flatIndex; i < flatIndex + ${componentCount}u; ++i) {
+ result[i] = texel.${indexExpression};
+ }
+ }
+
+ void writeResult(uint flatIndex, ivec4 texel) {
+ for (uint i = flatIndex; i < flatIndex + ${componentCount}u; ++i) {
+ result[i] = uint(texel.${indexExpression});
+ }
+ }
+
+ void writeResult(uint flatIndex, vec4 texel) {
+ for (uint i = flatIndex; i < flatIndex + ${componentCount}u; ++i) {
+ result[i] = floatBitsToUint(texel.${indexExpression});
+ }
+ }
+
void main() {
- bufferTex.result =
- texelFetch(sampler2D(sampleTex, sampler0), ivec2(0,0), 0);
+ uint flatIndex = gl_NumWorkGroups.x * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;
+ flatIndex = flatIndex * ${componentCount}u;
+
+ writeResult(flatIndex, texelFetch(
+ ${prefix}sampler${XD}${MS}(myTexture, mySampler),
+ ivec2(gl_GlobalInvocationID.xy), level));
+ }
+ `;
+
+ return this.device.createComputePipeline({
+ layout: undefined,
+ computeStage: {
+ entryPoint: 'main',
+ module: this.makeShaderModule('compute', { glsl }),
+ },
+ });
+ }
+
+ checkContents(
+ texture: GPUTexture,
+ state: InitializedState,
+ subresourceRange: SubresourceRange
+ ): void {
+ assert(this.params.dimension === '2d');
+
+ const sampler = this.device.createSampler();
+
+ for (const { level, slices } of subresourceRange.mipLevels()) {
+ const width = this.textureWidth >> level;
+ const height = this.textureHeight >> level;
+
+ let readbackTypedArray:
+ | Float32ArrayConstructor
+ | Int32ArrayConstructor
+ | Uint32ArrayConstructor = Float32Array;
+ let prefix = '';
+ let expectedShaderValue = initializedStateAsFloat(state);
+ if (this.params.format.indexOf('sint') !== -1) {
+ prefix = 'i';
+ expectedShaderValue = initializedStateAsSint(state);
+ readbackTypedArray = Int32Array;
+ } else if (this.params.format.indexOf('uint') !== -1) {
+ prefix = 'u';
+ expectedShaderValue = initializedStateAsUint(state);
+ readbackTypedArray = Uint32Array;
+ }
+
+ const computePipeline = this.getSamplingReadbackPipeline(
+ prefix,
+ this.params.sampleCount,
+ this.params.dimension
+ );
+
+ for (const slice of slices) {
+ const [ubo, uboMapping] = this.device.createBufferMapped({
+ size: 4,
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
+ });
+ new Int32Array(uboMapping, 0, 1)[0] = level;
+ ubo.unmap();
+
+ const byteLength =
+ width *
+ height *
+ Uint32Array.BYTES_PER_ELEMENT *
+ getTexelDataRepresentation(this.params.format).componentOrder.length;
+ const resultBuffer = this.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
+ });
+
+ const bindGroup = this.device.createBindGroup({
+ layout: computePipeline.getBindGroupLayout(0),
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer: ubo },
+ },
+ {
+ binding: 1,
+ resource: texture.createView({
+ baseMipLevel: 0,
+ mipLevelCount: this.params.mipLevelCount,
+ baseArrayLayer: slice,
+ arrayLayerCount: 1,
+ }),
+ },
+ { binding: 2, resource: sampler },
+ {
+ binding: 3,
+ resource: {
+ buffer: resultBuffer,
+ },
+ },
+ ],
+ });
+
+ const commandEncoder = this.device.createCommandEncoder();
+ const pass = commandEncoder.beginComputePass();
+ pass.setPipeline(computePipeline);
+ pass.setBindGroup(0, bindGroup);
+ pass.dispatch(width, height);
+ pass.endPass();
+ this.queue.submit([commandEncoder.finish()]);
+ ubo.destroy();
+
+ const mappedResultBuffer = this.createCopyForMapRead(resultBuffer, 0, byteLength);
+ resultBuffer.destroy();
+
+ this.eventualAsyncExpectation(async niceStack => {
+ const actual = await mappedResultBuffer.mapReadAsync();
+ const expected = new readbackTypedArray(new ArrayBuffer(actual.byteLength));
+ expected.fill(expectedShaderValue);
+
+ // TODO: Have a better way to determine approximately equal, maybe in ULPs.
+ let tolerance;
+ if (this.params.format === 'rgb10a2unorm') {
+ tolerance = (i: number) => {
+ // The alpha component is only two bits. Use a generous tolerance.
+ return i % 4 === 3 ? 0.18 : 0.01;
+ };
+ } else {
+ tolerance = 0.01;
+ }
+
+ const check = this.checkBuffer(new readbackTypedArray(actual), expected, tolerance);
+ if (check !== undefined) {
+ niceStack.message = check;
+ this.rec.expectationFailed(niceStack);
+ }
+ mappedResultBuffer.destroy();
+ });
}
- `,
- });
- const pipelineLayout = t.device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] });
- const computePipeline = t.device.createComputePipeline({
- computeStage: { module: computeModule, entryPoint: 'main' },
- layout: pipelineLayout,
- });
-
- // create bindgroup
- const bindGroup = t.device.createBindGroup({
- layout: bindGroupLayout,
- entries: [
- { binding: 0, resource: texture.createView() },
- { binding: 1, resource: { buffer: bufferTex, offset: 0, size: 4 * 256 * 256 } },
- { binding: 2, resource: sampler },
- ],
- });
-
- // encode the pass and submit
- const encoder = t.device.createCommandEncoder();
- const pass = encoder.beginComputePass();
- pass.setPipeline(computePipeline);
- pass.setBindGroup(0, bindGroup);
- pass.dispatch(256, 256, 1);
- pass.endPass();
- const commands = encoder.finish();
- t.device.defaultQueue.submit([commands]);
-
- await t.expectContents(bufferTex, new Uint32Array([0]));
-});
+ }
+ }
+}
+
+export const g = makeTestGroup(SampledTextureClearTest);
+
+g.test('uninitialized_texture_is_zero')
+ .params(TextureZeroInitTest.generateParams([ReadMethod.Sample]))
+ .fn(t => t.run());
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/texture_zero_init_test.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/texture_zero_init_test.ts
new file mode 100644
index 00000000000..c5119e23ade
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/operation/resource_init/texture_zero_init_test.ts
@@ -0,0 +1,581 @@
+import { TextureUsage } from '../../../../common/constants.js';
+import { TestCaseRecorder } from '../../../../common/framework/logging/test_case_recorder.js';
+import { params, poptions, pbool } from '../../../../common/framework/params_builder.js';
+import { CaseParams } from '../../../../common/framework/params_utils.js';
+import { assert, unreachable } from '../../../../common/framework/util/util.js';
+import { kTextureAspects, kTextureFormatInfo, kTextureFormats } from '../../../capability_info.js';
+import { GPUTest } from '../../../gpu_test.js';
+import { createTextureUploadBuffer } from '../../../util/texture/layout.js';
+import { BeginEndRange, SubresourceRange } from '../../../util/texture/subresource.js';
+import { PerTexelComponent, getTexelDataRepresentation } from '../../../util/texture/texelData.js';
+
+enum UninitializeMethod {
+ Creation = 'Creation', // The texture was just created. It is uninitialized.
+ StoreOpClear = 'StoreOpClear', // The texture was rendered to with GPUStoreOp "clear"
+}
+const kUninitializeMethods = Object.keys(UninitializeMethod) as UninitializeMethod[];
+
+export enum ReadMethod {
+ Sample = 'Sample', // The texture is sampled from
+ CopyToBuffer = 'CopyToBuffer', // The texture is copied to a buffer
+ CopyToTexture = 'CopyToTexture', // The texture is copied to another texture
+ DepthTest = 'DepthTest', // The texture is read as a depth buffer
+ StencilTest = 'StencilTest', // The texture is read as a stencil buffer
+ ColorBlending = 'ColorBlending', // Read the texture by blending as a color attachment
+ Storage = 'Storage', // Read the texture as a storage texture
+}
+
+// Test with these mip level counts
+type MipLevels = 1 | 5;
+const kMipLevelCounts: MipLevels[] = [1, 5];
+
+// For each mip level count, define the mip ranges to leave uninitialized.
+const kUninitializedMipRangesToTest: { [k in MipLevels]: BeginEndRange[] } = {
+ 1: [{ begin: 0, end: 1 }], // Test the only mip
+ 5: [
+ { begin: 0, end: 2 },
+ { begin: 3, end: 4 },
+ ], // Test a range and a single mip
+};
+
+// Test with these sample counts.
+type SampleCounts = 1 | 4;
+const kSampleCounts: SampleCounts[] = [1, 4];
+
+// Test with these slice counts. This means the depth of a 3d texture or the number
+// or layers in a 2D or a 1D texture array.
+type SliceCounts = 1 | 7;
+
+// For each slice count, define the slices to leave uninitialized.
+const kUninitializedSliceRangesToTest: { [k in SliceCounts]: BeginEndRange[] } = {
+ 1: [{ begin: 0, end: 1 }], // Test the only slice
+ 7: [
+ { begin: 2, end: 4 },
+ { begin: 6, end: 7 },
+ ], // Test a range and a single slice
+};
+
+// Test with these combinations of texture dimension and sliceCount.
+const kCreationSizes: Array<{
+ dimension: GPUTextureDimension;
+ sliceCount: SliceCounts;
+}> = [
+ // { dimension: '1d', sliceCount: 7 }, // TODO: 1d textures
+ { dimension: '2d', sliceCount: 1 }, // 2d textures
+ { dimension: '2d', sliceCount: 7 }, // 2d array textures
+ // { dimension: '3d', sliceCount: 7 }, // TODO: 3d textures
+];
+
+// Enums to abstract over color / depth / stencil values in textures. Depending on the texture format,
+// the data for each value may have a different representation. These enums are converted to a
+// representation such that their values can be compared. ex.) An integer is needed to upload to an
+// unsigned normalized format, but its value is read as a float in the shader.
+export const enum InitializedState {
+ Canary, // Set on initialized subresources. It should stay the same. On discarded resources, we should observe zero.
+ Zero, // We check that uninitialized subresources are in this state when read back.
+}
+
+export function initializedStateAsFloat(state: InitializedState): number {
+ switch (state) {
+ case InitializedState.Zero:
+ return 0;
+ case InitializedState.Canary:
+ return 1;
+ default:
+ unreachable();
+ }
+}
+
+export function initializedStateAsUint(state: InitializedState): number {
+ switch (state) {
+ case InitializedState.Zero:
+ return 0;
+ case InitializedState.Canary:
+ return 255;
+ default:
+ unreachable();
+ }
+}
+
+export function initializedStateAsSint(state: InitializedState): number {
+ switch (state) {
+ case InitializedState.Zero:
+ return 0;
+ case InitializedState.Canary:
+ return -1;
+ default:
+ unreachable();
+ }
+}
+
+export function initializedStateAsColor(
+ state: InitializedState,
+ format: GPUTextureFormat
+): [number, number, number, number] {
+ let value;
+ if (format.indexOf('uint') !== -1) {
+ value = initializedStateAsUint(state);
+ } else if (format.indexOf('sint') !== -1) {
+ value = initializedStateAsSint(state);
+ } else {
+ value = initializedStateAsFloat(state);
+ }
+ return [value, value, value, value];
+}
+
+export function initializedStateAsDepth(state: InitializedState): number {
+ switch (state) {
+ case InitializedState.Zero:
+ return 0;
+ case InitializedState.Canary:
+ return 1;
+ default:
+ unreachable();
+ }
+}
+
+export function initializedStateAsStencil(state: InitializedState): number {
+ switch (state) {
+ case InitializedState.Zero:
+ return 0;
+ case InitializedState.Canary:
+ return 42;
+ default:
+ unreachable();
+ }
+}
+
+interface TestParams {
+ format: GPUTextureFormat;
+ aspect: GPUTextureAspect;
+ dimension: GPUTextureDimension;
+ sliceCount: SliceCounts;
+ mipLevelCount: MipLevels;
+ sampleCount: SampleCounts;
+ uninitializeMethod: UninitializeMethod;
+ readMethod: ReadMethod;
+ nonPowerOfTwo: boolean;
+}
+
+function getRequiredTextureUsage(
+ format: GPUTextureFormat,
+ sampleCount: SampleCounts,
+ uninitializeMethod: UninitializeMethod,
+ readMethod: ReadMethod
+): GPUTextureUsageFlags {
+ let usage: GPUTextureUsageFlags = TextureUsage.CopyDst;
+
+ switch (uninitializeMethod) {
+ case UninitializeMethod.Creation:
+ break;
+ case UninitializeMethod.StoreOpClear:
+ usage |= TextureUsage.OutputAttachment;
+ break;
+ default:
+ unreachable();
+ }
+
+ switch (readMethod) {
+ case ReadMethod.CopyToBuffer:
+ case ReadMethod.CopyToTexture:
+ usage |= TextureUsage.CopySrc;
+ break;
+ case ReadMethod.Sample:
+ usage |= TextureUsage.Sampled;
+ break;
+ case ReadMethod.Storage:
+ usage |= TextureUsage.Storage;
+ break;
+ case ReadMethod.DepthTest:
+ case ReadMethod.StencilTest:
+ case ReadMethod.ColorBlending:
+ usage |= TextureUsage.OutputAttachment;
+ break;
+ default:
+ unreachable();
+ }
+
+ if (sampleCount > 1) {
+ // Copies to multisampled textures are not allowed. We need OutputAttachment to initialize
+ // canary data in multisampled textures.
+ usage |= TextureUsage.OutputAttachment;
+ }
+
+ if (!kTextureFormatInfo[format].copyable) {
+ // Copies are not possible. We need OutputAttachment to initialize
+ // canary data.
+ assert(kTextureFormatInfo[format].renderable);
+ usage |= TextureUsage.OutputAttachment;
+ }
+
+ return usage;
+}
+
+export abstract class TextureZeroInitTest extends GPUTest {
+ protected stateToTexelComponents: { [k in InitializedState]: PerTexelComponent<number> };
+
+ constructor(rec: TestCaseRecorder, params: CaseParams) {
+ super(rec, params);
+
+ const stateToTexelComponents = (state: InitializedState) => {
+ const [R, G, B, A] = initializedStateAsColor(state, this.params.format);
+ return {
+ R,
+ G,
+ B,
+ A,
+ Depth: initializedStateAsDepth(state),
+ Stencil: initializedStateAsStencil(state),
+ };
+ };
+
+ this.stateToTexelComponents = {
+ [InitializedState.Zero]: stateToTexelComponents(InitializedState.Zero),
+ [InitializedState.Canary]: stateToTexelComponents(InitializedState.Canary),
+ };
+ }
+
+ get params(): TestParams {
+ return super.params as TestParams;
+ }
+
+ get textureWidth(): number {
+ let width = 1 << this.params.mipLevelCount;
+ if (this.params.nonPowerOfTwo) {
+ width = 2 * width - 1;
+ }
+ return width;
+ }
+
+ get textureHeight(): number {
+ let height = 1 << this.params.mipLevelCount;
+ if (this.params.nonPowerOfTwo) {
+ height = 2 * height - 1;
+ }
+ return height;
+ }
+
+ // Used to iterate subresources and check that their uninitialized contents are zero when accessed
+ *iterateUninitializedSubresources(): Generator<SubresourceRange> {
+ for (const mipRange of kUninitializedMipRangesToTest[this.params.mipLevelCount]) {
+ for (const sliceRange of kUninitializedSliceRangesToTest[this.params.sliceCount]) {
+ yield new SubresourceRange({ mipRange, sliceRange });
+ }
+ }
+ }
+
+ // Used to iterate and initialize other subresources not checked for zero-initialization.
+ // Zero-initialization of uninitialized subresources should not have side effects on already
+ // initialized subresources.
+ *iterateInitializedSubresources(): Generator<SubresourceRange> {
+ const uninitialized: boolean[][] = new Array(this.params.mipLevelCount);
+ for (let level = 0; level < uninitialized.length; ++level) {
+ uninitialized[level] = new Array(this.params.sliceCount);
+ }
+ for (const subresources of this.iterateUninitializedSubresources()) {
+ for (const { level, slice } of subresources.each()) {
+ uninitialized[level][slice] = true;
+ }
+ }
+ for (let level = 0; level < uninitialized.length; ++level) {
+ for (let slice = 0; slice < uninitialized[level].length; ++slice) {
+ if (!uninitialized[level][slice]) {
+ yield new SubresourceRange({
+ mipRange: { begin: level, count: 1 },
+ sliceRange: { begin: slice, count: 1 },
+ });
+ }
+ }
+ }
+ }
+
+ *generateTextureViewDescriptorsForRendering(
+ aspect: GPUTextureAspect,
+ subresourceRange?: SubresourceRange
+ ): Generator<GPUTextureViewDescriptor> {
+ const viewDescriptor: GPUTextureViewDescriptor = {
+ dimension: '2d',
+ aspect,
+ };
+
+ if (subresourceRange === undefined) {
+ return viewDescriptor;
+ }
+
+ for (const { level, slice } of subresourceRange.each()) {
+ yield {
+ ...viewDescriptor,
+ baseMipLevel: level,
+ mipLevelCount: 1,
+ baseArrayLayer: slice,
+ arrayLayerCount: 1,
+ };
+ }
+ }
+
+ abstract checkContents(
+ texture: GPUTexture,
+ state: InitializedState,
+ subresourceRange: SubresourceRange
+ ): void;
+
+ private initializeWithStoreOp(
+ state: InitializedState,
+ texture: GPUTexture,
+ subresourceRange?: SubresourceRange
+ ): void {
+ const commandEncoder = this.device.createCommandEncoder();
+ for (const viewDescriptor of this.generateTextureViewDescriptorsForRendering(
+ this.params.aspect,
+ subresourceRange
+ )) {
+ if (kTextureFormatInfo[this.params.format].color) {
+ commandEncoder
+ .beginRenderPass({
+ colorAttachments: [
+ {
+ attachment: texture.createView(viewDescriptor),
+ storeOp: 'store',
+ loadValue: initializedStateAsColor(state, this.params.format),
+ },
+ ],
+ })
+ .endPass();
+ } else {
+ commandEncoder
+ .beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment: {
+ attachment: texture.createView(viewDescriptor),
+ depthStoreOp: 'store',
+ depthLoadValue: initializedStateAsDepth(state),
+ stencilStoreOp: 'store',
+ stencilLoadValue: initializedStateAsStencil(state),
+ },
+ })
+ .endPass();
+ }
+ }
+ this.queue.submit([commandEncoder.finish()]);
+ }
+
+ private initializeWithCopy(
+ texture: GPUTexture,
+ state: InitializedState,
+ subresourceRange: SubresourceRange
+ ): void {
+ if (this.params.dimension === '1d' || this.params.dimension === '3d') {
+ // TODO: https://github.com/gpuweb/gpuweb/issues/69
+ // Copies with 1D and 3D textures are not yet specified
+ unreachable();
+ }
+
+ const firstSubresource = subresourceRange.each().next().value;
+ assert(typeof firstSubresource !== 'undefined');
+
+ const largestWidth = this.textureWidth >> firstSubresource.level;
+ const largestHeight = this.textureHeight >> firstSubresource.level;
+
+ const texelData = new Uint8Array(
+ getTexelDataRepresentation(this.params.format).getBytes(this.stateToTexelComponents[state])
+ );
+ const { buffer, bytesPerRow, rowsPerImage } = createTextureUploadBuffer(
+ texelData,
+ this.device,
+ this.params.format,
+ this.params.dimension,
+ [largestWidth, largestHeight, 1]
+ );
+
+ const commandEncoder = this.device.createCommandEncoder();
+
+ for (const { level, slice } of subresourceRange.each()) {
+ const width = this.textureWidth >> level;
+ const height = this.textureHeight >> level;
+
+ commandEncoder.copyBufferToTexture(
+ {
+ buffer,
+ bytesPerRow,
+ rowsPerImage,
+ },
+ { texture, mipLevel: level, arrayLayer: slice },
+ { width, height, depth: 1 }
+ );
+ }
+ this.queue.submit([commandEncoder.finish()]);
+ buffer.destroy();
+ }
+
+ initializeTexture(
+ texture: GPUTexture,
+ state: InitializedState,
+ subresourceRange: SubresourceRange
+ ): void {
+ if (this.params.sampleCount > 1 || !kTextureFormatInfo[this.params.format].copyable) {
+ // Copies to multisampled textures not yet specified.
+ // Use a storeOp for now.
+ assert(kTextureFormatInfo[this.params.format].renderable);
+ this.initializeWithStoreOp(state, texture, subresourceRange);
+ } else {
+ this.initializeWithCopy(texture, state, subresourceRange);
+ }
+ }
+
+ discardTexture(texture: GPUTexture, subresourceRange: SubresourceRange): void {
+ const commandEncoder = this.device.createCommandEncoder();
+
+ for (const desc of this.generateTextureViewDescriptorsForRendering(
+ this.params.aspect,
+ subresourceRange
+ )) {
+ if (kTextureFormatInfo[this.params.format].color) {
+ commandEncoder
+ .beginRenderPass({
+ colorAttachments: [
+ {
+ attachment: texture.createView(desc),
+ storeOp: 'clear',
+ loadValue: 'load',
+ },
+ ],
+ })
+ .endPass();
+ } else {
+ commandEncoder
+ .beginRenderPass({
+ colorAttachments: [],
+ depthStencilAttachment: {
+ attachment: texture.createView(desc),
+ depthStoreOp: 'clear',
+ depthLoadValue: 'load',
+ stencilStoreOp: 'clear',
+ stencilLoadValue: 'load',
+ },
+ })
+ .endPass();
+ }
+ }
+ this.queue.submit([commandEncoder.finish()]);
+ }
+
+ static generateParams(readMethods: ReadMethod[]) {
+ return (
+ // TODO: Consider making a list of "valid" texture descriptors in capability_info.
+ params()
+ .combine(poptions('format', kTextureFormats))
+ .combine(poptions('aspect', kTextureAspects))
+ .unless(
+ ({ format, aspect }) =>
+ (aspect === 'depth-only' && !kTextureFormatInfo[format].depth) ||
+ (aspect === 'stencil-only' && !kTextureFormatInfo[format].stencil)
+ )
+ .combine(poptions('mipLevelCount', kMipLevelCounts))
+ .combine(poptions('sampleCount', kSampleCounts))
+ // Multisampled textures may only have one mip
+ .unless(({ sampleCount, mipLevelCount }) => sampleCount > 1 && mipLevelCount > 1)
+ .combine(poptions('uninitializeMethod', kUninitializeMethods))
+ .combine(poptions('readMethod', readMethods))
+ .unless(
+ ({ readMethod, format }) =>
+ // It doesn't make sense to copy from a packed depth format.
+ // This is not specified yet, but it will probably be disallowed as the bits may
+ // be vendor-specific.
+ // TODO: Test copying out of the stencil aspect.
+ (readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture) &&
+ (format === 'depth24plus' || format === 'depth24plus-stencil8')
+ )
+ .unless(
+ ({ readMethod, format }) =>
+ (readMethod === ReadMethod.DepthTest && !kTextureFormatInfo[format].depth) ||
+ (readMethod === ReadMethod.StencilTest && !kTextureFormatInfo[format].stencil) ||
+ (readMethod === ReadMethod.ColorBlending && !kTextureFormatInfo[format].color) ||
+ // TODO: Test with depth sampling
+ (readMethod === ReadMethod.Sample && kTextureFormatInfo[format].depth)
+ )
+ .unless(
+ ({ readMethod, sampleCount }) =>
+ // We can only read from multisampled textures by sampling.
+ sampleCount > 1 &&
+ (readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture)
+ )
+ .combine(kCreationSizes)
+ // Multisampled 3D / 2D array textures not supported.
+ .unless(({ sampleCount, sliceCount }) => sampleCount > 1 && sliceCount > 1)
+ .filter(({ format, sampleCount, uninitializeMethod, readMethod }) => {
+ const usage = getRequiredTextureUsage(
+ format,
+ sampleCount,
+ uninitializeMethod,
+ readMethod
+ );
+
+ if (usage & TextureUsage.OutputAttachment && !kTextureFormatInfo[format].renderable) {
+ return false;
+ }
+
+ if (usage & TextureUsage.Storage && !kTextureFormatInfo[format].storage) {
+ return false;
+ }
+
+ return true;
+ })
+ .combine(pbool('nonPowerOfTwo'))
+ );
+ }
+
+ run(): void {
+ const {
+ format,
+ dimension,
+ mipLevelCount,
+ sliceCount,
+ sampleCount,
+ uninitializeMethod,
+ readMethod,
+ } = this.params;
+
+ const usage = getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod);
+
+ const texture = this.device.createTexture({
+ size: [this.textureWidth, this.textureHeight, sliceCount],
+ format,
+ dimension,
+ usage,
+ mipLevelCount,
+ sampleCount,
+ });
+
+ // Initialize some subresources with canary values
+ for (const subresourceRange of this.iterateInitializedSubresources()) {
+ this.initializeTexture(texture, InitializedState.Canary, subresourceRange);
+ }
+
+ switch (uninitializeMethod) {
+ case UninitializeMethod.Creation:
+ break;
+ case UninitializeMethod.StoreOpClear:
+ // Initialize the rest of the resources.
+ for (const subresourceRange of this.iterateUninitializedSubresources()) {
+ this.initializeTexture(texture, InitializedState.Canary, subresourceRange);
+ }
+ // Then use a store op to discard their contents.
+ for (const subresourceRange of this.iterateUninitializedSubresources()) {
+ this.discardTexture(texture, subresourceRange);
+ }
+ break;
+ default:
+ unreachable();
+ }
+
+ // Check that all uninitialized resources are zero.
+ for (const subresourceRange of this.iterateUninitializedSubresources()) {
+ this.checkContents(texture, InitializedState.Zero, subresourceRange);
+ }
+
+ // Check the all other resources are unchanged.
+ for (const subresourceRange of this.iterateInitializedSubresources()) {
+ this.checkContents(texture, InitializedState.Canary, subresourceRange);
+ }
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroup.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroup.spec.ts
index 0825405b939..61ff346027c 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroup.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroup.spec.ts
@@ -2,21 +2,27 @@ export const description = `
createBindGroup validation tests.
`;
-import * as C from '../../../common/constants.js';
-import { pcombine, poptions } from '../../../common/framework/params.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { poptions, params } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { unreachable } from '../../../common/framework/util/util.js';
-import { kBindingTypes } from '../../capability_info.js';
+import {
+ kBindingTypes,
+ kBindingTypeInfo,
+ kBindableResources,
+ kTextureUsages,
+ kTextureBindingTypes,
+ kTextureBindingTypeInfo,
+} from '../../capability_info.js';
-import { BindingResourceType, ValidationTest, resourceBindingMatches } from './validation_test.js';
+import { ValidationTest } from './validation_test.js';
function clone<T extends GPUTextureDescriptor>(descriptor: T): T {
return JSON.parse(JSON.stringify(descriptor));
}
-export const g = new TestGroup(ValidationTest);
+export const g = makeTestGroup(ValidationTest);
-g.test('binding count mismatch', async t => {
+g.test('binding_count_mismatch').fn(async t => {
const bindGroupLayout = t.device.createBindGroupLayout({
entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, type: 'storage-buffer' }],
});
@@ -44,7 +50,7 @@ g.test('binding count mismatch', async t => {
});
});
-g.test('binding must be present in layout', async t => {
+g.test('binding_must_be_present_in_layout').fn(async t => {
const bindGroupLayout = t.device.createBindGroupLayout({
entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, type: 'storage-buffer' }],
});
@@ -68,147 +74,134 @@ g.test('binding must be present in layout', async t => {
});
});
-g.test('buffer binding must contain exactly one buffer of its type', t => {
- const bindingType: GPUBindingType = t.params.bindingType;
- const resourceType: BindingResourceType = t.params.resourceType;
-
- const layout = t.device.createBindGroupLayout({
- entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, type: bindingType }],
- });
-
- const resource = t.getBindingResource(resourceType);
-
- const shouldError = !resourceBindingMatches(bindingType, resourceType);
- t.expectValidationError(() => {
- t.device.createBindGroup({ layout, entries: [{ binding: 0, resource }] });
- }, shouldError);
-}).params(
- pcombine(
- poptions('bindingType', kBindingTypes),
- poptions('resourceType', Object.keys(BindingResourceType))
+g.test('buffer_binding_must_contain_exactly_one_buffer_of_its_type')
+ .params(
+ params()
+ .combine(poptions('bindingType', kBindingTypes))
+ .combine(poptions('resourceType', kBindableResources))
)
-);
+ .fn(t => {
+ const { bindingType, resourceType } = t.params;
+ const info = kBindingTypeInfo[bindingType];
+
+ const storageTextureFormat = info.resource === 'storageTex' ? 'rgba8unorm' : undefined;
+ const layout = t.device.createBindGroupLayout({
+ entries: [
+ { binding: 0, visibility: GPUShaderStage.COMPUTE, type: bindingType, storageTextureFormat },
+ ],
+ });
-g.test('texture binding must have correct usage', async t => {
- const type: GPUBindingType = t.params.type;
- const usage: GPUTextureUsageFlags = t.params._usage;
+ const resource = t.getBindingResource(resourceType);
- const bindGroupLayout = t.device.createBindGroupLayout({
- entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, type }],
+ const resourceBindingMatches = info.resource === resourceType;
+ t.expectValidationError(() => {
+ t.device.createBindGroup({ layout, entries: [{ binding: 0, resource }] });
+ }, !resourceBindingMatches);
});
- const goodDescriptor = {
- size: { width: 16, height: 16, depth: 1 },
- format: C.TextureFormat.R8Unorm,
- usage,
- };
-
- // Control case
- t.device.createBindGroup({
- entries: [{ binding: 0, resource: t.device.createTexture(goodDescriptor).createView() }],
- layout: bindGroupLayout,
- });
+g.test('texture_binding_must_have_correct_usage')
+ .params(
+ params()
+ .combine(poptions('type', kTextureBindingTypes))
+ .combine(poptions('usage', kTextureUsages))
+ )
+ .fn(async t => {
+ const { type, usage } = t.params;
+ const info = kTextureBindingTypeInfo[type];
- function* mismatchedTextureUsages(): Iterable<GPUTextureUsageFlags> {
- yield GPUTextureUsage.COPY_SRC;
- yield GPUTextureUsage.COPY_DST;
- if (type !== 'sampled-texture') {
- yield GPUTextureUsage.SAMPLED;
- }
- if (type !== 'readonly-storage-texture' && type !== 'writeonly-storage-texture') {
- yield GPUTextureUsage.STORAGE;
- }
- yield GPUTextureUsage.OUTPUT_ATTACHMENT;
- }
+ const storageTextureFormat = info.resource === 'storageTex' ? 'rgba8unorm' : undefined;
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, type, storageTextureFormat }],
+ });
- // Mismatched texture binding usages are not valid.
- for (const mismatchedTextureUsage of mismatchedTextureUsages()) {
- const badDescriptor = clone(goodDescriptor);
- badDescriptor.usage = mismatchedTextureUsage;
+ const descriptor = {
+ size: { width: 16, height: 16, depth: 1 },
+ format: 'rgba8unorm' as const,
+ usage,
+ };
+ const shouldError = usage !== info.usage;
t.expectValidationError(() => {
t.device.createBindGroup({
- entries: [{ binding: 0, resource: t.device.createTexture(badDescriptor).createView() }],
+ entries: [{ binding: 0, resource: t.device.createTexture(descriptor).createView() }],
layout: bindGroupLayout,
});
- });
- }
-}).params([
- { type: 'sampled-texture', _usage: C.TextureUsage.Sampled },
- { type: 'storage-texture', _usage: C.TextureUsage.Storage },
-]);
-
-g.test('texture must have correct component type', async t => {
- const { textureComponentType } = t.params;
-
- const bindGroupLayout = t.device.createBindGroupLayout({
- entries: [
- {
- binding: 0,
- visibility: GPUShaderStage.FRAGMENT,
- type: 'sampled-texture',
- textureComponentType,
- },
- ],
+ }, shouldError);
});
- // TODO: Test more texture component types.
- let format: GPUTextureFormat;
- if (textureComponentType === 'float') {
- format = 'r8unorm';
- } else if (textureComponentType === 'sint') {
- format = 'r8sint';
- } else if (textureComponentType === 'uint') {
- format = 'r8uint';
- } else {
- unreachable('Unexpected texture component type');
- }
+g.test('texture_must_have_correct_component_type')
+ .params(poptions('textureComponentType', ['float', 'sint', 'uint'] as const))
+ .fn(async t => {
+ const { textureComponentType } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ type: 'sampled-texture',
+ textureComponentType,
+ },
+ ],
+ });
- const goodDescriptor = {
- size: { width: 16, height: 16, depth: 1 },
- format,
- usage: GPUTextureUsage.SAMPLED,
- };
+ // TODO: Test more texture component types.
+ let format: GPUTextureFormat;
+ if (textureComponentType === 'float') {
+ format = 'r8unorm';
+ } else if (textureComponentType === 'sint') {
+ format = 'r8sint';
+ } else if (textureComponentType === 'uint') {
+ format = 'r8uint';
+ } else {
+ unreachable('Unexpected texture component type');
+ }
- // Control case
- t.device.createBindGroup({
- entries: [
- {
- binding: 0,
- resource: t.device.createTexture(goodDescriptor).createView(),
- },
- ],
- layout: bindGroupLayout,
- });
+ const goodDescriptor = {
+ size: { width: 16, height: 16, depth: 1 },
+ format,
+ usage: GPUTextureUsage.SAMPLED,
+ };
- function* mismatchedTextureFormats(): Iterable<GPUTextureFormat> {
- if (textureComponentType !== 'float') {
- yield 'r8unorm';
- }
- if (textureComponentType !== 'sint') {
- yield 'r8sint';
- }
- if (textureComponentType !== 'uint') {
- yield 'r8uint';
+ // Control case
+ t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: t.device.createTexture(goodDescriptor).createView(),
+ },
+ ],
+ layout: bindGroupLayout,
+ });
+
+ function* mismatchedTextureFormats(): Iterable<GPUTextureFormat> {
+ if (textureComponentType !== 'float') {
+ yield 'r8unorm';
+ }
+ if (textureComponentType !== 'sint') {
+ yield 'r8sint';
+ }
+ if (textureComponentType !== 'uint') {
+ yield 'r8uint';
+ }
}
- }
- // Mismatched texture binding formats are not valid.
- for (const mismatchedTextureFormat of mismatchedTextureFormats()) {
- const badDescriptor: GPUTextureDescriptor = clone(goodDescriptor);
- badDescriptor.format = mismatchedTextureFormat;
+ // Mismatched texture binding formats are not valid.
+ for (const mismatchedTextureFormat of mismatchedTextureFormats()) {
+ const badDescriptor: GPUTextureDescriptor = clone(goodDescriptor);
+ badDescriptor.format = mismatchedTextureFormat;
- t.expectValidationError(() => {
- t.device.createBindGroup({
- entries: [{ binding: 0, resource: t.device.createTexture(badDescriptor).createView() }],
- layout: bindGroupLayout,
+ t.expectValidationError(() => {
+ t.device.createBindGroup({
+ entries: [{ binding: 0, resource: t.device.createTexture(badDescriptor).createView() }],
+ layout: bindGroupLayout,
+ });
});
- });
- }
-}).params(poptions('textureComponentType', ['float', 'sint', 'uint']));
+ }
+ });
// TODO: Write test for all dimensions.
-g.test('texture must have correct dimension', async t => {
+g.test('texture_must_have_correct_dimension').fn(async t => {
const bindGroupLayout = t.device.createBindGroupLayout({
entries: [
{
@@ -222,7 +215,7 @@ g.test('texture must have correct dimension', async t => {
const goodDescriptor = {
size: { width: 16, height: 16, depth: 1 },
- format: C.TextureFormat.RGBA8Unorm,
+ format: 'rgba8unorm' as const,
usage: GPUTextureUsage.SAMPLED,
};
@@ -244,61 +237,63 @@ g.test('texture must have correct dimension', async t => {
});
});
-g.test('buffer offset and size for bind groups match', async t => {
- const { offset, size, _success } = t.params;
-
- const bindGroupLayout = t.device.createBindGroupLayout({
- entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, type: 'storage-buffer' }],
- });
+g.test('buffer_offset_and_size_for_bind_groups_match')
+ .params([
+ { offset: 0, size: 512, _success: true }, // offset 0 is valid
+ { offset: 256, size: 256, _success: true }, // offset 256 (aligned) is valid
+
+ // Touching the end of the buffer
+ { offset: 0, size: 1024, _success: true },
+ { offset: 0, size: undefined, _success: true },
+ { offset: 256 * 3, size: 256, _success: true },
+ { offset: 256 * 3, size: undefined, _success: true },
+
+ // Zero-sized bindings
+ { offset: 0, size: 0, _success: true },
+ { offset: 256, size: 0, _success: true },
+ { offset: 1024, size: 0, _success: true },
+ { offset: 1024, size: undefined, _success: true },
+
+ // Unaligned buffer offset is invalid
+ { offset: 1, size: 256, _success: false },
+ { offset: 1, size: undefined, _success: false },
+ { offset: 128, size: 256, _success: false },
+ { offset: 255, size: 256, _success: false },
+
+ // Out-of-bounds
+ { offset: 256 * 5, size: 0, _success: false }, // offset is OOB
+ { offset: 0, size: 256 * 5, _success: false }, // size is OOB
+ { offset: 1024, size: 1, _success: false }, // offset+size is OOB
+ ])
+ .fn(async t => {
+ const { offset, size, _success } = t.params;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, type: 'storage-buffer' }],
+ });
- const buffer = t.device.createBuffer({
- size: 1024,
- usage: GPUBufferUsage.STORAGE,
- });
+ const buffer = t.device.createBuffer({
+ size: 1024,
+ usage: GPUBufferUsage.STORAGE,
+ });
- const descriptor = {
- entries: [
- {
- binding: 0,
- resource: { buffer, offset, size },
- },
- ],
- layout: bindGroupLayout,
- };
+ const descriptor = {
+ entries: [
+ {
+ binding: 0,
+ resource: { buffer, offset, size },
+ },
+ ],
+ layout: bindGroupLayout,
+ };
- if (_success) {
- // Control case
- t.device.createBindGroup(descriptor);
- } else {
- // Buffer offset and/or size don't match in bind groups.
- t.expectValidationError(() => {
+ if (_success) {
+ // Control case
t.device.createBindGroup(descriptor);
- });
- }
-}).params([
- { offset: 0, size: 512, _success: true }, // offset 0 is valid
- { offset: 256, size: 256, _success: true }, // offset 256 (aligned) is valid
-
- // Touching the end of the buffer
- { offset: 0, size: 1024, _success: true },
- { offset: 0, size: undefined, _success: true },
- { offset: 256 * 3, size: 256, _success: true },
- { offset: 256 * 3, size: undefined, _success: true },
-
- // Zero-sized bindings
- { offset: 0, size: 0, _success: true },
- { offset: 256, size: 0, _success: true },
- { offset: 1024, size: 0, _success: true },
- { offset: 1024, size: undefined, _success: true },
-
- // Unaligned buffer offset is invalid
- { offset: 1, size: 256, _success: false },
- { offset: 1, size: undefined, _success: false },
- { offset: 128, size: 256, _success: false },
- { offset: 255, size: 256, _success: false },
-
- // Out-of-bounds
- { offset: 256 * 5, size: 0, _success: false }, // offset is OOB
- { offset: 0, size: 256 * 5, _success: false }, // size is OOB
- { offset: 1024, size: 1, _success: false }, // offset+size is OOB
-]);
+ } else {
+ // Buffer offset and/or size don't match in bind groups.
+ t.expectValidationError(() => {
+ t.device.createBindGroup(descriptor);
+ });
+ }
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroupLayout.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroupLayout.spec.ts
index 2ab8b5e6465..5aa5dae448d 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroupLayout.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createBindGroupLayout.spec.ts
@@ -2,15 +2,12 @@ export const description = `
createBindGroupLayout validation tests.
`;
-import * as C from '../../../common/constants.js';
-import { poptions } from '../../../common/framework/params.js';
-import { ParamSpec } from '../../../common/framework/params_utils.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { poptions, params } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import {
kBindingTypeInfo,
kBindingTypes,
kMaxBindingsPerBindGroup,
- kPerStageBindingLimits,
kShaderStages,
} from '../../capability_info.js';
@@ -20,13 +17,13 @@ function clone<T extends GPUBindGroupLayoutDescriptor>(descriptor: T): T {
return JSON.parse(JSON.stringify(descriptor));
}
-export const g = new TestGroup(ValidationTest);
+export const g = makeTestGroup(ValidationTest);
-g.test('some binding index was specified more than once', async t => {
+g.test('some_binding_index_was_specified_more_than_once').fn(async t => {
const goodDescriptor = {
entries: [
- { binding: 0, visibility: GPUShaderStage.COMPUTE, type: C.BindingType.StorageBuffer },
- { binding: 1, visibility: GPUShaderStage.COMPUTE, type: C.BindingType.StorageBuffer },
+ { binding: 0, visibility: GPUShaderStage.COMPUTE, type: 'storage-buffer' as const },
+ { binding: 1, visibility: GPUShaderStage.COMPUTE, type: 'storage-buffer' as const },
],
};
@@ -42,185 +39,192 @@ g.test('some binding index was specified more than once', async t => {
});
});
-g.test('Visibility of bindings can be 0', async t => {
+g.test('visibility_of_bindings_can_be_0').fn(async t => {
t.device.createBindGroupLayout({
entries: [{ binding: 0, visibility: 0, type: 'storage-buffer' }],
});
});
-g.test('number of dynamic buffers exceeds the maximum value', async t => {
- const { type, maxDynamicBufferCount } = t.params;
-
- const maxDynamicBufferBindings: GPUBindGroupLayoutEntry[] = [];
- for (let i = 0; i < maxDynamicBufferCount; i++) {
- maxDynamicBufferBindings.push({
- binding: i,
- visibility: GPUShaderStage.COMPUTE,
- type,
- hasDynamicOffset: true,
- });
- }
-
- const goodDescriptor = {
- entries: [
- ...maxDynamicBufferBindings,
- {
- binding: maxDynamicBufferBindings.length,
+g.test('number_of_dynamic_buffers_exceeds_the_maximum_value')
+ .params([
+ { type: 'storage-buffer' as const, maxDynamicBufferCount: 4 },
+ { type: 'uniform-buffer' as const, maxDynamicBufferCount: 8 },
+ ])
+ .fn(async t => {
+ const { type, maxDynamicBufferCount } = t.params;
+
+ const maxDynamicBufferBindings: GPUBindGroupLayoutEntry[] = [];
+ for (let i = 0; i < maxDynamicBufferCount; i++) {
+ maxDynamicBufferBindings.push({
+ binding: i,
visibility: GPUShaderStage.COMPUTE,
type,
- hasDynamicOffset: false,
- },
- ],
- };
-
- // Control case
- t.device.createBindGroupLayout(goodDescriptor);
-
- // Dynamic buffers exceed maximum in a bind group layout.
- const badDescriptor = clone(goodDescriptor);
- badDescriptor.entries[maxDynamicBufferCount].hasDynamicOffset = true;
+ hasDynamicOffset: true,
+ });
+ }
- t.expectValidationError(() => {
- t.device.createBindGroupLayout(badDescriptor);
+ const goodDescriptor = {
+ entries: [
+ ...maxDynamicBufferBindings,
+ {
+ binding: maxDynamicBufferBindings.length,
+ visibility: GPUShaderStage.COMPUTE,
+ type,
+ hasDynamicOffset: false,
+ },
+ ],
+ };
+
+ // Control case
+ t.device.createBindGroupLayout(goodDescriptor);
+
+ // Dynamic buffers exceed maximum in a bind group layout.
+ const badDescriptor = clone(goodDescriptor);
+ badDescriptor.entries[maxDynamicBufferCount].hasDynamicOffset = true;
+
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout(badDescriptor);
+ });
});
-}).params([
- { type: C.BindingType.StorageBuffer, maxDynamicBufferCount: 4 },
- { type: C.BindingType.UniformBuffer, maxDynamicBufferCount: 8 },
-]);
-g.test('dynamic set to true is allowed only for buffers', async t => {
- const type: GPUBindingType = t.params.type;
- const success = kBindingTypeInfo[type].type === 'buffer';
+g.test('dynamic_set_to_true_is_allowed_only_for_buffers')
+ .params(poptions('type', kBindingTypes))
+ .fn(async t => {
+ const { type } = t.params;
+ const success = kBindingTypeInfo[type].perPipelineLimitClass.maxDynamic > 0;
- const descriptor = {
- entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, type, hasDynamicOffset: true }],
- };
+ const descriptor = {
+ entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, type, hasDynamicOffset: true }],
+ };
- t.expectValidationError(() => {
- t.device.createBindGroupLayout(descriptor);
- }, !success);
-}).params(poptions('type', kBindingTypes));
-
-let kCasesForMaxResourcesPerStageTests: ParamSpec[];
-{
- // One bind group layout will be filled with kPerStageBindingLimit[...] of the type |type|.
- // For each item in the array returned here, a case will be generated which tests a pipeline
- // layout with one extra bind group layout with one extra binding. That extra binding will have:
- //
- // - If extraTypeSame, any of the binding types which counts toward the same limit as |type|.
- // (i.e. 'storage-buffer' <-> 'readonly-storage-buffer').
- // - Otherwise, an arbitrary other type.
- function* pickExtraBindingTypes(
- bindingType: GPUBindingType,
- extraTypeSame: boolean
- ): IterableIterator<GPUBindingType> {
- const info = kBindingTypeInfo[bindingType];
- if (extraTypeSame) {
- for (const extraBindingType of kBindingTypes) {
- if (info.perStageLimitType === kBindingTypeInfo[extraBindingType].perStageLimitType) {
- yield extraBindingType;
- }
- }
- } else {
- yield info.perStageLimitType === 'sampler' ? 'sampled-texture' : 'sampler';
- }
- }
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout(descriptor);
+ }, !success);
+ });
- kCasesForMaxResourcesPerStageTests = [];
- for (const maxedType of kBindingTypes) {
- for (const maxedVisibility of kShaderStages) {
- // Don't generate a case where maxedType isn't valid in maxedVisibility.
- if (!(kBindingTypeInfo[maxedType].validStages & maxedVisibility)) continue;
-
- for (const extraTypeSame of [true, false]) {
- for (const extraType of pickExtraBindingTypes(maxedType, extraTypeSame)) {
- for (const extraVisibility of kShaderStages) {
- // Don't generate a case where extraType isn't valid in extraVisibility.
- if (!(kBindingTypeInfo[extraType].validStages & extraVisibility)) continue;
-
- kCasesForMaxResourcesPerStageTests.push({
- maxedType,
- maxedVisibility,
- extraType,
- extraVisibility,
- });
- }
- }
+// One bind group layout will be filled with kPerStageBindingLimit[...] of the type |type|.
+// For each item in the array returned here, a case will be generated which tests a pipeline
+// layout with one extra bind group layout with one extra binding. That extra binding will have:
+//
+// - If extraTypeSame, any of the binding types which counts toward the same limit as |type|.
+// (i.e. 'storage-buffer' <-> 'readonly-storage-buffer').
+// - Otherwise, an arbitrary other type.
+function* pickExtraBindingTypes(
+ bindingType: GPUBindingType,
+ extraTypeSame: boolean
+): IterableIterator<GPUBindingType> {
+ const info = kBindingTypeInfo[bindingType];
+ if (extraTypeSame) {
+ for (const extraBindingType of kBindingTypes) {
+ if (
+ info.perStageLimitClass.class ===
+ kBindingTypeInfo[extraBindingType].perStageLimitClass.class
+ ) {
+ yield extraBindingType;
}
}
+ } else {
+ yield info.perStageLimitClass.class === 'sampler' ? 'sampled-texture' : 'sampler';
}
}
+const kCasesForMaxResourcesPerStageTests = params()
+ .combine(poptions('maxedType', kBindingTypes))
+ .combine(poptions('maxedVisibility', kShaderStages))
+ .filter(p => (kBindingTypeInfo[p.maxedType].validStages & p.maxedVisibility) !== 0)
+ .expand(function* (p) {
+ for (const extraTypeSame of [true, false]) {
+ yield* poptions('extraType', pickExtraBindingTypes(p.maxedType, extraTypeSame));
+ }
+ })
+ .combine(poptions('extraVisibility', kShaderStages))
+ .filter(p => (kBindingTypeInfo[p.extraType].validStages & p.extraVisibility) !== 0);
+
// Should never fail unless kMaxBindingsPerBindGroup is exceeded, because the validation for
// resources-of-type-per-stage is in pipeline layout creation.
-g.test('max resources per stage/in bind group layout', async t => {
- const maxedType: GPUBindingType = t.params.maxedType;
- const extraType: GPUBindingType = t.params.extraType;
- const { maxedVisibility, extraVisibility } = t.params;
- const maxedCount = kPerStageBindingLimits[kBindingTypeInfo[maxedType].perStageLimitType];
-
- const maxResourceBindings: GPUBindGroupLayoutEntry[] = [];
- for (let i = 0; i < maxedCount; i++) {
- maxResourceBindings.push({
- binding: i,
- visibility: maxedVisibility,
- type: maxedType,
- });
- }
+g.test('max_resources_per_stage,in_bind_group_layout')
+ .params(kCasesForMaxResourcesPerStageTests)
+ .fn(async t => {
+ const { maxedType, extraType, maxedVisibility, extraVisibility } = t.params;
+ const maxedTypeInfo = kBindingTypeInfo[maxedType];
+ const maxedCount = maxedTypeInfo.perStageLimitClass.max;
+ const extraTypeInfo = kBindingTypeInfo[extraType];
+
+ const maxResourceBindings: GPUBindGroupLayoutEntry[] = [];
+ for (let i = 0; i < maxedCount; i++) {
+ maxResourceBindings.push({
+ binding: i,
+ visibility: maxedVisibility,
+ type: maxedType,
+ storageTextureFormat: maxedTypeInfo.resource === 'storageTex' ? 'rgba8unorm' : undefined,
+ });
+ }
- const goodDescriptor = { entries: maxResourceBindings };
+ const goodDescriptor = { entries: maxResourceBindings };
- // Control
- t.device.createBindGroupLayout(goodDescriptor);
+ // Control
+ t.device.createBindGroupLayout(goodDescriptor);
- const newDescriptor = clone(goodDescriptor);
- newDescriptor.entries.push({
- binding: maxedCount,
- visibility: extraVisibility,
- type: extraType,
- });
+ const newDescriptor = clone(goodDescriptor);
+ newDescriptor.entries.push({
+ binding: maxedCount,
+ visibility: extraVisibility,
+ type: extraType,
+ storageTextureFormat: extraTypeInfo.resource === 'storageTex' ? 'rgba8unorm' : undefined,
+ });
- const shouldError = maxedCount >= kMaxBindingsPerBindGroup;
+ const shouldError = maxedCount >= kMaxBindingsPerBindGroup;
- t.expectValidationError(() => {
- t.device.createBindGroupLayout(newDescriptor);
- }, shouldError);
-}).params(kCasesForMaxResourcesPerStageTests);
+ t.expectValidationError(() => {
+ t.device.createBindGroupLayout(newDescriptor);
+ }, shouldError);
+ });
// One pipeline layout can have a maximum number of each type of binding *per stage* (which is
// different for each type). Test that the max works, then add one more binding of same-or-different
// type and same-or-different visibility.
-g.test('max resources per stage/in pipeline layout', async t => {
- const maxedType: GPUBindingType = t.params.maxedType;
- const extraType: GPUBindingType = t.params.extraType;
- const { maxedVisibility, extraVisibility } = t.params;
- const maxedCount = kPerStageBindingLimits[kBindingTypeInfo[maxedType].perStageLimitType];
-
- const maxResourceBindings: GPUBindGroupLayoutEntry[] = [];
- for (let i = 0; i < maxedCount; i++) {
- maxResourceBindings.push({
- binding: i,
- visibility: maxedVisibility,
- type: maxedType,
- });
- }
+g.test('max_resources_per_stage,in_pipeline_layout')
+ .params(kCasesForMaxResourcesPerStageTests)
+ .fn(async t => {
+ const { maxedType, extraType, maxedVisibility, extraVisibility } = t.params;
+ const maxedTypeInfo = kBindingTypeInfo[maxedType];
+ const maxedCount = maxedTypeInfo.perStageLimitClass.max;
+ const extraTypeInfo = kBindingTypeInfo[extraType];
+
+ const maxResourceBindings: GPUBindGroupLayoutEntry[] = [];
+ for (let i = 0; i < maxedCount; i++) {
+ maxResourceBindings.push({
+ binding: i,
+ visibility: maxedVisibility,
+ type: maxedType,
+ storageTextureFormat: maxedTypeInfo.resource === 'storageTex' ? 'rgba8unorm' : undefined,
+ });
+ }
- const goodLayout = t.device.createBindGroupLayout({ entries: maxResourceBindings });
+ const goodLayout = t.device.createBindGroupLayout({ entries: maxResourceBindings });
- // Control
- t.device.createPipelineLayout({ bindGroupLayouts: [goodLayout] });
+ // Control
+ t.device.createPipelineLayout({ bindGroupLayouts: [goodLayout] });
- const extraLayout = t.device.createBindGroupLayout({
- entries: [{ binding: 0, visibility: extraVisibility, type: extraType }],
- });
+ const extraLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: extraVisibility,
+ type: extraType,
+ storageTextureFormat: extraTypeInfo.resource === 'storageTex' ? 'rgba8unorm' : undefined,
+ },
+ ],
+ });
- // Some binding types use the same limit, e.g. 'storage-buffer' and 'readonly-storage-buffer'.
- const newBindingCountsTowardSamePerStageLimit =
- (maxedVisibility & extraVisibility) !== 0 &&
- kBindingTypeInfo[maxedType].perStageLimitType === kBindingTypeInfo[extraType].perStageLimitType;
- const layoutExceedsPerStageLimit = newBindingCountsTowardSamePerStageLimit;
+ // Some binding types use the same limit, e.g. 'storage-buffer' and 'readonly-storage-buffer'.
+ const newBindingCountsTowardSamePerStageLimit =
+ (maxedVisibility & extraVisibility) !== 0 &&
+ kBindingTypeInfo[maxedType].perStageLimitClass.class ===
+ kBindingTypeInfo[extraType].perStageLimitClass.class;
+ const layoutExceedsPerStageLimit = newBindingCountsTowardSamePerStageLimit;
- t.expectValidationError(() => {
- t.device.createPipelineLayout({ bindGroupLayouts: [goodLayout, extraLayout] });
- }, layoutExceedsPerStageLimit);
-}).params(kCasesForMaxResourcesPerStageTests);
+ t.expectValidationError(() => {
+ t.device.createPipelineLayout({ bindGroupLayouts: [goodLayout, extraLayout] });
+ }, layoutExceedsPerStageLimit);
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createPipelineLayout.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createPipelineLayout.spec.ts
index 9d8116cc517..cc466482991 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createPipelineLayout.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createPipelineLayout.spec.ts
@@ -2,8 +2,8 @@ export const description = `
createPipelineLayout validation tests.
`;
-import { pbool, pcombine, poptions } from '../../../common/framework/params.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { pbool, poptions, params } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import {
kBindingTypeInfo,
kBindingTypes,
@@ -16,84 +16,88 @@ function clone<T extends GPUBindGroupLayoutDescriptor>(descriptor: T): T {
return JSON.parse(JSON.stringify(descriptor));
}
-export const g = new TestGroup(ValidationTest);
+export const g = makeTestGroup(ValidationTest);
-g.test('number of dynamic buffers exceeds the maximum value', async t => {
- const { type, visibility } = t.params;
- const maxDynamicCount = kBindingTypeInfo[type as GPUBindingType].maxDynamicCount;
-
- const maxDynamicBufferBindings: GPUBindGroupLayoutEntry[] = [];
- for (let binding = 0; binding < maxDynamicCount; binding++) {
- maxDynamicBufferBindings.push({ binding, visibility, type, hasDynamicOffset: true });
- }
-
- const maxDynamicBufferBindGroupLayout = t.device.createBindGroupLayout({
- entries: maxDynamicBufferBindings,
- });
-
- const goodDescriptor = {
- entries: [{ binding: 0, visibility, type, hasDynamicOffset: false }],
- };
-
- const goodPipelineLayoutDescriptor = {
- bindGroupLayouts: [
- maxDynamicBufferBindGroupLayout,
- t.device.createBindGroupLayout(goodDescriptor),
- ],
- };
-
- // Control case
- t.device.createPipelineLayout(goodPipelineLayoutDescriptor);
-
- // Check dynamic buffers exceed maximum in pipeline layout.
- const badDescriptor = clone(goodDescriptor);
- badDescriptor.entries[0].hasDynamicOffset = true;
-
- const badPipelineLayoutDescriptor = {
- bindGroupLayouts: [
- maxDynamicBufferBindGroupLayout,
- t.device.createBindGroupLayout(badDescriptor),
- ],
- };
-
- t.expectValidationError(() => {
- t.device.createPipelineLayout(badPipelineLayoutDescriptor);
- });
-}).params(
- pcombine(
- poptions('visibility', [0, 2, 4, 6]), //
- poptions('type', ['uniform-buffer', 'storage-buffer', 'readonly-storage-buffer'])
+g.test('number_of_dynamic_buffers_exceeds_the_maximum_value')
+ .params(
+ params()
+ .combine(poptions('visibility', [0, 2, 4, 6]))
+ .combine(
+ poptions('type', ['uniform-buffer', 'storage-buffer', 'readonly-storage-buffer'] as const)
+ )
)
-);
+ .fn(async t => {
+ const { type, visibility } = t.params;
+ const { maxDynamic } = kBindingTypeInfo[type].perPipelineLimitClass;
-g.test('visibility and dynamic offsets', t => {
- const hasDynamicOffset: boolean = t.params.hasDynamicOffset;
- const type: GPUBindingType = t.params.type;
- const visibility: GPUShaderStageFlags = t.params.visibility;
- const info = kBindingTypeInfo[type as GPUBindingType];
+ const maxDynamicBufferBindings: GPUBindGroupLayoutEntry[] = [];
+ for (let binding = 0; binding < maxDynamic; binding++) {
+ maxDynamicBufferBindings.push({ binding, visibility, type, hasDynamicOffset: true });
+ }
- const descriptor = {
- entries: [{ binding: 0, visibility, type, hasDynamicOffset }],
- };
-
- let success = true;
- if (info.type !== 'buffer' && hasDynamicOffset) success = false;
- if ((visibility & ~info.validStages) !== 0) success = false;
+ const maxDynamicBufferBindGroupLayout = t.device.createBindGroupLayout({
+ entries: maxDynamicBufferBindings,
+ });
- t.expectValidationError(() => {
- t.device.createPipelineLayout({
- bindGroupLayouts: [t.device.createBindGroupLayout(descriptor)],
+ const goodDescriptor = {
+ entries: [{ binding: 0, visibility, type, hasDynamicOffset: false }],
+ };
+
+ const goodPipelineLayoutDescriptor = {
+ bindGroupLayouts: [
+ maxDynamicBufferBindGroupLayout,
+ t.device.createBindGroupLayout(goodDescriptor),
+ ],
+ };
+
+ // Control case
+ t.device.createPipelineLayout(goodPipelineLayoutDescriptor);
+
+ // Check dynamic buffers exceed maximum in pipeline layout.
+ const badDescriptor = clone(goodDescriptor);
+ badDescriptor.entries[0].hasDynamicOffset = true;
+
+ const badPipelineLayoutDescriptor = {
+ bindGroupLayouts: [
+ maxDynamicBufferBindGroupLayout,
+ t.device.createBindGroupLayout(badDescriptor),
+ ],
+ };
+
+ t.expectValidationError(() => {
+ t.device.createPipelineLayout(badPipelineLayoutDescriptor);
});
- }, !success);
-}).params(
- pcombine(
- poptions('type', kBindingTypes), //
- pbool('hasDynamicOffset'),
- poptions('visibility', kShaderStageCombinations)
+ });
+
+g.test('visibility_and_dynamic_offsets')
+ .params(
+ params()
+ .combine(poptions('type', kBindingTypes))
+ .combine(pbool('hasDynamicOffset'))
+ .combine(poptions('visibility', kShaderStageCombinations))
)
-);
+ .fn(t => {
+ const { type, hasDynamicOffset, visibility } = t.params;
+ const info = kBindingTypeInfo[type as GPUBindingType];
+
+ const storageTextureFormat = info.resource === 'storageTex' ? ('r32uint' as const) : undefined;
+ const descriptor = {
+ entries: [{ binding: 0, visibility, type, hasDynamicOffset, storageTextureFormat }],
+ };
+
+ const supportsDynamicOffset = kBindingTypeInfo[type].perPipelineLimitClass.maxDynamic > 0;
+ let success = true;
+ if (!supportsDynamicOffset && hasDynamicOffset) success = false;
+ if ((visibility & ~info.validStages) !== 0) success = false;
+
+ t.expectValidationError(() => {
+ t.device.createPipelineLayout({
+ bindGroupLayouts: [t.device.createBindGroupLayout(descriptor)],
+ });
+ }, !success);
+ });
-g.test('number of bind group layouts exceeds the maximum value', async t => {
+g.test('number_of_bind_group_layouts_exceeds_the_maximum_value').fn(async t => {
const bindGroupLayoutDescriptor: GPUBindGroupLayoutDescriptor = {
entries: [],
};
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createRenderPipeline.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createRenderPipeline.spec.ts
index 9560bb940c8..b5ac9e8070c 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createRenderPipeline.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createRenderPipeline.spec.ts
@@ -2,8 +2,8 @@ export const description = `
createRenderPipeline validation tests.
`;
-import { poptions } from '../../../common/framework/params.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { poptions } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { kTextureFormatInfo, kTextureFormats } from '../../capability_info.js';
import { ValidationTest } from './validation_test.js';
@@ -92,15 +92,15 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('basic use of createRenderPipeline', t => {
+g.test('basic_use_of_createRenderPipeline').fn(t => {
const descriptor = t.getDescriptor();
t.device.createRenderPipeline(descriptor);
});
-g.test('at least one color state is required', async t => {
+g.test('at_least_one_color_state_is_required').fn(async t => {
const goodDescriptor = t.getDescriptor({
colorStates: [{ format: 'rgba8unorm' }],
});
@@ -118,111 +118,117 @@ g.test('at least one color state is required', async t => {
});
});
-g.test('color formats must be renderable', async t => {
- const format: GPUTextureFormat = t.params.format;
- const info = kTextureFormatInfo[format];
+g.test('color_formats_must_be_renderable')
+ .params(poptions('format', kTextureFormats))
+ .fn(async t => {
+ const format: GPUTextureFormat = t.params.format;
+ const info = kTextureFormatInfo[format];
- const descriptor = t.getDescriptor({ colorStates: [{ format }] });
+ const descriptor = t.getDescriptor({ colorStates: [{ format }] });
- if (info.renderable && info.color) {
- // Succeeds when color format is renderable
- t.device.createRenderPipeline(descriptor);
- } else {
- // Fails because when format is non-renderable
- t.expectValidationError(() => {
+ if (info.renderable && info.color) {
+ // Succeeds when color format is renderable
t.device.createRenderPipeline(descriptor);
- });
- }
-}).params(poptions('format', kTextureFormats));
-
-g.test('sample count must be valid', async t => {
- const { sampleCount, _success } = t.params;
-
- const descriptor = t.getDescriptor({ sampleCount });
+ } else {
+ // Fails because when format is non-renderable
+ t.expectValidationError(() => {
+ t.device.createRenderPipeline(descriptor);
+ });
+ }
+ });
- if (_success) {
- // Succeeds when sample count is valid
- t.device.createRenderPipeline(descriptor);
- } else {
- // Fails when sample count is not 4 or 1
- t.expectValidationError(() => {
+g.test('sample_count_must_be_valid')
+ .params([
+ { sampleCount: 0, _success: false },
+ { sampleCount: 1, _success: true },
+ { sampleCount: 2, _success: false },
+ { sampleCount: 3, _success: false },
+ { sampleCount: 4, _success: true },
+ { sampleCount: 8, _success: false },
+ { sampleCount: 16, _success: false },
+ ])
+ .fn(async t => {
+ const { sampleCount, _success } = t.params;
+
+ const descriptor = t.getDescriptor({ sampleCount });
+
+ if (_success) {
+ // Succeeds when sample count is valid
t.device.createRenderPipeline(descriptor);
- });
- }
-}).params([
- { sampleCount: 0, _success: false },
- { sampleCount: 1, _success: true },
- { sampleCount: 2, _success: false },
- { sampleCount: 3, _success: false },
- { sampleCount: 4, _success: true },
- { sampleCount: 8, _success: false },
- { sampleCount: 16, _success: false },
-]);
-
-g.test('sample count must be equal to the one of every attachment in the render pass', async t => {
- const { attachmentSamples, pipelineSamples, _success } = t.params;
-
- const colorTexture = t.createTexture({
- format: 'rgba8unorm',
- sampleCount: attachmentSamples,
- });
- const depthStencilTexture = t.createTexture({
- format: 'depth24plus-stencil8',
- sampleCount: attachmentSamples,
+ } else {
+ // Fails when sample count is not 4 or 1
+ t.expectValidationError(() => {
+ t.device.createRenderPipeline(descriptor);
+ });
+ }
});
- const renderPassDescriptorWithoutDepthStencil = {
- colorAttachments: [
+
+g.test('sample_count_must_be_equal_to_the_one_of_every_attachment_in_the_render_pass')
+ .params([
+ { attachmentSamples: 4, pipelineSamples: 4, _success: true }, // It is allowed to use multisampled render pass and multisampled render pipeline.
+ { attachmentSamples: 4, pipelineSamples: 1, _success: false }, // It is not allowed to use multisampled render pass and non-multisampled render pipeline.
+ { attachmentSamples: 1, pipelineSamples: 4, _success: false }, // It is not allowed to use non-multisampled render pass and multisampled render pipeline.
+ ])
+ .fn(async t => {
+ const { attachmentSamples, pipelineSamples, _success } = t.params;
+
+ const colorTexture = t.createTexture({
+ format: 'rgba8unorm',
+ sampleCount: attachmentSamples,
+ });
+ const depthStencilTexture = t.createTexture({
+ format: 'depth24plus-stencil8',
+ sampleCount: attachmentSamples,
+ });
+ const renderPassDescriptorWithoutDepthStencil = {
+ colorAttachments: [
+ {
+ attachment: colorTexture.createView(),
+ loadValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ },
+ ],
+ };
+ const renderPassDescriptorWithDepthStencilOnly = {
+ colorAttachments: [],
+ depthStencilAttachment: {
+ attachment: depthStencilTexture.createView(),
+ depthLoadValue: 1.0,
+ depthStoreOp: 'store',
+ stencilLoadValue: 0,
+ stencilStoreOp: 'store',
+ },
+ };
+
+ const pipelineWithoutDepthStencil = t.device.createRenderPipeline(
+ t.getDescriptor({
+ sampleCount: pipelineSamples,
+ })
+ );
+ const pipelineWithDepthStencilOnly = t.device.createRenderPipeline(
+ t.getDescriptor({
+ colorStates: [],
+ depthStencilState: { format: 'depth24plus-stencil8' },
+ sampleCount: pipelineSamples,
+ })
+ );
+
+ for (const { renderPassDescriptor, pipeline } of [
{
- attachment: colorTexture.createView(),
- loadValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ renderPassDescriptor: renderPassDescriptorWithoutDepthStencil,
+ pipeline: pipelineWithoutDepthStencil,
},
- ],
- };
- const renderPassDescriptorWithDepthStencilOnly = {
- colorAttachments: [],
- depthStencilAttachment: {
- attachment: depthStencilTexture.createView(),
- depthLoadValue: 1.0,
- depthStoreOp: 'store',
- stencilLoadValue: 0,
- stencilStoreOp: 'store',
- },
- };
-
- const pipelineWithoutDepthStencil = t.device.createRenderPipeline(
- t.getDescriptor({
- sampleCount: pipelineSamples,
- })
- );
- const pipelineWithDepthStencilOnly = t.device.createRenderPipeline(
- t.getDescriptor({
- colorStates: [],
- depthStencilState: { format: 'depth24plus-stencil8' },
- sampleCount: pipelineSamples,
- })
- );
-
- for (const { renderPassDescriptor, pipeline } of [
- {
- renderPassDescriptor: renderPassDescriptorWithoutDepthStencil,
- pipeline: pipelineWithoutDepthStencil,
- },
- {
- renderPassDescriptor: renderPassDescriptorWithDepthStencilOnly,
- pipeline: pipelineWithDepthStencilOnly,
- },
- ]) {
- const commandEncoder = t.device.createCommandEncoder();
- const renderPass = commandEncoder.beginRenderPass(renderPassDescriptor);
- renderPass.setPipeline(pipeline);
- renderPass.endPass();
-
- t.expectValidationError(() => {
- commandEncoder.finish();
- }, !_success);
- }
-}).params([
- { attachmentSamples: 4, pipelineSamples: 4, _success: true }, // It is allowed to use multisampled render pass and multisampled render pipeline.
- { attachmentSamples: 4, pipelineSamples: 1, _success: false }, // It is not allowed to use multisampled render pass and non-multisampled render pipeline.
- { attachmentSamples: 1, pipelineSamples: 4, _success: false }, // It is not allowed to use non-multisampled render pass and multisampled render pipeline.
-]);
+ {
+ renderPassDescriptor: renderPassDescriptorWithDepthStencilOnly,
+ pipeline: pipelineWithDepthStencilOnly,
+ },
+ ]) {
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass(renderPassDescriptor);
+ renderPass.setPipeline(pipeline);
+ renderPass.endPass();
+
+ t.expectValidationError(() => {
+ commandEncoder.finish();
+ }, !_success);
+ }
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createTexture.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createTexture.spec.ts
index b34cf77e0bf..46ff763e6f4 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createTexture.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createTexture.spec.ts
@@ -2,8 +2,8 @@ export const description = `
createTexture validation tests.
`;
-import { poptions } from '../../../common/framework/params.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { poptions } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { kTextureFormatInfo, kTextureFormats } from '../../capability_info.js';
import { ValidationTest } from './validation_test.js';
@@ -38,106 +38,115 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
-
-g.test('validation of sampleCount', async t => {
- const { sampleCount, mipLevelCount, arrayLayerCount, _success } = t.params;
-
- const descriptor = t.getDescriptor({ sampleCount, mipLevelCount, arrayLayerCount });
-
- t.expectValidationError(() => {
- t.device.createTexture(descriptor);
- }, !_success);
-}).params([
- { sampleCount: 0, _success: false }, // sampleCount of 0 is not allowed
- { sampleCount: 1, _success: true }, // sampleCount of 1 is allowed
- { sampleCount: 2, _success: false }, // sampleCount of 2 is not allowed
- { sampleCount: 3, _success: false }, // sampleCount of 3 is not allowed
- { sampleCount: 4, _success: true }, // sampleCount of 4 is allowed
- { sampleCount: 8, _success: false }, // sampleCount of 8 is not allowed
- { sampleCount: 16, _success: false }, // sampleCount of 16 is not allowed
- { sampleCount: 4, mipLevelCount: 2, _success: false }, // it is an error to create a multisampled texture with mipLevelCount > 1
- { sampleCount: 4, arrayLayerCount: 2, _success: true }, // multisampled 2D array texture is supported
-]);
-
-g.test('validation of mipLevelCount', async t => {
- const { width, height, mipLevelCount, _success } = t.params;
-
- const descriptor = t.getDescriptor({ width, height, mipLevelCount });
-
- t.expectValidationError(() => {
- t.device.createTexture(descriptor);
- }, !_success);
-}).params([
- { width: 32, height: 32, mipLevelCount: 1, _success: true }, // mipLevelCount of 1 is allowed
- { width: 32, height: 32, mipLevelCount: 0, _success: false }, // mipLevelCount of 0 is not allowed
- { width: 32, height: 32, mipLevelCount: 6, _success: true }, // full mip chains are allowed (Mip level sizes: 32, 16, 8, 4, 2, 1)
- { width: 31, height: 32, mipLevelCount: 6, _success: true }, // full mip chains are allowed (Mip level sizes: 31x32, 15x16, 7x8, 3x4, 1x2, 1x1)
- { width: 32, height: 31, mipLevelCount: 6, _success: true }, // full mip chains are allowed (Mip level sizes: 32x31, 16x15, 8x7, 4x3, 2x1, 1x1)
- { width: 31, height: 32, mipLevelCount: 7, _success: false }, // too big mip chains on width are disallowed (Mip level sizes: 31x32, 15x16, 7x8, 3x4, 1x2, 1x1, ?x?)
- { width: 32, height: 31, mipLevelCount: 7, _success: false }, // too big mip chains on height are disallowed (Mip level sizes: 32x31, 16x15, 8x7, 4x3, 2x1, 1x1, ?x?)
- { width: 32, height: 32, mipLevelCount: 100, _success: false }, // undefined shift check if miplevel is bigger than the integer bit width
- { width: 32, height: 8, mipLevelCount: 6, _success: true }, // non square mip map halves the resolution until a 1x1 dimension. (Mip maps: 32 * 8, 16 * 4, 8 * 2, 4 * 1, 2 * 1, 1 * 1)
-]);
-
-g.test('it is valid to destroy a texture', t => {
+export const g = makeTestGroup(F);
+
+g.test('validation_of_sampleCount')
+ .params([
+ // TODO: Consider making a list of "valid"+"invalid" texture descriptors in capability_info.
+ { sampleCount: 0, _success: false }, // sampleCount of 0 is not allowed
+ { sampleCount: 1, _success: true }, // sampleCount of 1 is allowed
+ { sampleCount: 2, _success: false }, // sampleCount of 2 is not allowed
+ { sampleCount: 3, _success: false }, // sampleCount of 3 is not allowed
+ { sampleCount: 4, _success: true }, // sampleCount of 4 is allowed
+ { sampleCount: 8, _success: false }, // sampleCount of 8 is not allowed
+ { sampleCount: 16, _success: false }, // sampleCount of 16 is not allowed
+ { sampleCount: 4, mipLevelCount: 2, _success: false }, // multisampled multi-level not allowed
+ { sampleCount: 4, arrayLayerCount: 2, _success: false }, // multisampled multi-layer is not allowed
+ ])
+ .fn(async t => {
+ const { sampleCount, mipLevelCount, arrayLayerCount, _success } = t.params;
+
+ const descriptor = t.getDescriptor({ sampleCount, mipLevelCount, arrayLayerCount });
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !_success);
+ });
+
+g.test('validation_of_mipLevelCount')
+ .params([
+ { width: 32, height: 32, mipLevelCount: 1, _success: true }, // mipLevelCount of 1 is allowed
+ { width: 32, height: 32, mipLevelCount: 0, _success: false }, // mipLevelCount of 0 is not allowed
+ { width: 32, height: 32, mipLevelCount: 6, _success: true }, // full mip chains are allowed (Mip level sizes: 32, 16, 8, 4, 2, 1)
+ { width: 31, height: 32, mipLevelCount: 6, _success: true }, // full mip chains are allowed (Mip level sizes: 31x32, 15x16, 7x8, 3x4, 1x2, 1x1)
+ { width: 32, height: 31, mipLevelCount: 6, _success: true }, // full mip chains are allowed (Mip level sizes: 32x31, 16x15, 8x7, 4x3, 2x1, 1x1)
+ { width: 31, height: 32, mipLevelCount: 7, _success: false }, // too big mip chains on width are disallowed (Mip level sizes: 31x32, 15x16, 7x8, 3x4, 1x2, 1x1, ?x?)
+ { width: 32, height: 31, mipLevelCount: 7, _success: false }, // too big mip chains on height are disallowed (Mip level sizes: 32x31, 16x15, 8x7, 4x3, 2x1, 1x1, ?x?)
+ { width: 32, height: 32, mipLevelCount: 100, _success: false }, // undefined shift check if miplevel is bigger than the integer bit width
+ { width: 32, height: 8, mipLevelCount: 6, _success: true }, // non square mip map halves the resolution until a 1x1 dimension. (Mip maps: 32 * 8, 16 * 4, 8 * 2, 4 * 1, 2 * 1, 1 * 1)
+ ])
+ .fn(async t => {
+ const { width, height, mipLevelCount, _success } = t.params;
+
+ const descriptor = t.getDescriptor({ width, height, mipLevelCount });
+
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !_success);
+ });
+
+g.test('it_is_valid_to_destroy_a_texture').fn(t => {
const descriptor = t.getDescriptor();
const texture = t.device.createTexture(descriptor);
texture.destroy();
});
-g.test('it is valid to destroy a destroyed texture', t => {
+g.test('it_is_valid_to_destroy_a_destroyed_texture').fn(t => {
const descriptor = t.getDescriptor();
const texture = t.device.createTexture(descriptor);
texture.destroy();
texture.destroy();
});
-g.test('it is invalid to submit a destroyed texture before and after encode', async t => {
- const { destroyBeforeEncode, destroyAfterEncode, _success } = t.params;
+g.test('it_is_invalid_to_submit_a_destroyed_texture_before_and_after_encode')
+ .params([
+ { destroyBeforeEncode: false, destroyAfterEncode: false, _success: true },
+ { destroyBeforeEncode: true, destroyAfterEncode: false, _success: false },
+ { destroyBeforeEncode: false, destroyAfterEncode: true, _success: false },
+ ])
+ .fn(async t => {
+ const { destroyBeforeEncode, destroyAfterEncode, _success } = t.params;
+
+ const descriptor = t.getDescriptor();
+ const texture = t.device.createTexture(descriptor);
+ const textureView = texture.createView();
+
+ if (destroyBeforeEncode) {
+ texture.destroy();
+ }
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = commandEncoder.beginRenderPass({
+ colorAttachments: [
+ {
+ attachment: textureView,
+ loadValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ },
+ ],
+ });
+ renderPass.endPass();
+ const commandBuffer = commandEncoder.finish();
+
+ if (destroyAfterEncode) {
+ texture.destroy();
+ }
+
+ t.expectValidationError(() => {
+ t.queue.submit([commandBuffer]);
+ }, !_success);
+ });
- const descriptor = t.getDescriptor();
- const texture = t.device.createTexture(descriptor);
- const textureView = texture.createView();
+g.test('it_is_invalid_to_have_an_output_attachment_texture_with_non_renderable_format')
+ .params(poptions('format', kTextureFormats))
+ .fn(async t => {
+ const format: GPUTextureFormat = t.params.format;
+ const info = kTextureFormatInfo[format];
- if (destroyBeforeEncode) {
- texture.destroy();
- }
+ const descriptor = t.getDescriptor({ width: 1, height: 1, format });
- const commandEncoder = t.device.createCommandEncoder();
- const renderPass = commandEncoder.beginRenderPass({
- colorAttachments: [
- {
- attachment: textureView,
- loadValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
- },
- ],
+ t.expectValidationError(() => {
+ t.device.createTexture(descriptor);
+ }, !info.renderable);
});
- renderPass.endPass();
- const commandBuffer = commandEncoder.finish();
-
- if (destroyAfterEncode) {
- texture.destroy();
- }
-
- t.expectValidationError(() => {
- t.queue.submit([commandBuffer]);
- }, !_success);
-}).params([
- { destroyBeforeEncode: false, destroyAfterEncode: false, _success: true },
- { destroyBeforeEncode: true, destroyAfterEncode: false, _success: false },
- { destroyBeforeEncode: false, destroyAfterEncode: true, _success: false },
-]);
-
-g.test('it is invalid to have an output attachment texture with non renderable format', async t => {
- const format: GPUTextureFormat = t.params.format;
- const info = kTextureFormatInfo[format];
-
- const descriptor = t.getDescriptor({ width: 1, height: 1, format });
-
- t.expectValidationError(() => {
- t.device.createTexture(descriptor);
- }, !info.renderable);
-}).params(poptions('format', kTextureFormats));
// TODO: Add tests for compressed texture formats
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createView.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createView.spec.ts
index 695a9737de4..18033f17384 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createView.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/createView.spec.ts
@@ -2,7 +2,7 @@ export const description = `
createView validation tests.
`;
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
@@ -67,76 +67,94 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
+
+g.test('creating_texture_view_on_a_2D_non_array_texture')
+ .params([
+ { _success: true }, // default view works
+ { arrayLayerCount: 1, _success: true }, // it is OK to create a 2D texture view on a 2D texture
+ { arrayLayerCount: 2, _success: false }, // it is an error to view a layer past the end of the texture
+ { dimension: '2d-array' as const, arrayLayerCount: 1, _success: true }, // it is OK to create a 1-layer 2D array texture view on a 2D texture
+ // mip level is in range
+ { mipLevelCount: 1, baseMipLevel: MIP_LEVEL_COUNT - 1, _success: true },
+ { mipLevelCount: 2, baseMipLevel: MIP_LEVEL_COUNT - 2, _success: true },
+ // baseMipLevel == k && mipLevelCount == 0 means to use levels k..end
+ { mipLevelCount: 0, baseMipLevel: 0, _success: true },
+ { mipLevelCount: 0, baseMipLevel: 1, _success: true },
+ { mipLevelCount: 0, baseMipLevel: MIP_LEVEL_COUNT - 1, _success: true },
+ { mipLevelCount: 0, baseMipLevel: MIP_LEVEL_COUNT, _success: false },
+ // it is an error to make the mip level out of range
+ { mipLevelCount: MIP_LEVEL_COUNT + 1, baseMipLevel: 0, _success: false },
+ { mipLevelCount: MIP_LEVEL_COUNT, baseMipLevel: 1, _success: false },
+ { mipLevelCount: 2, baseMipLevel: MIP_LEVEL_COUNT - 1, _success: false },
+ { mipLevelCount: 1, baseMipLevel: MIP_LEVEL_COUNT, _success: false },
+ ])
+ .fn(async t => {
+ const { dimension = '2d', arrayLayerCount, mipLevelCount, baseMipLevel, _success } = t.params;
+
+ const texture = t.createTexture({ arrayLayerCount: 1 });
+
+ const descriptor = t.getDescriptor({
+ dimension,
+ arrayLayerCount,
+ mipLevelCount,
+ baseMipLevel,
+ });
-g.test('creating texture view on a 2D non array texture', async t => {
- const { dimension = '2d', arrayLayerCount, mipLevelCount, baseMipLevel, _success } = t.params;
+ t.expectValidationError(() => {
+ texture.createView(descriptor);
+ }, !_success);
+ });
- const texture = t.createTexture({ arrayLayerCount: 1 });
+g.test('creating_texture_view_on_a_2D_array_texture')
+ .params([
+ { _success: true }, // default view works
+ { dimension: '2d' as const, arrayLayerCount: 1, _success: true }, // it is OK to create a 2D texture view on a 2D array texture
+ { arrayLayerCount: ARRAY_LAYER_COUNT_2D, _success: true }, // it is OK to create a 2D array texture view on a 2D array texture
+ // baseArrayLayer == k && arrayLayerCount == 0 means to use layers k..end.
+ { arrayLayerCount: 0, baseArrayLayer: 0, _success: true },
+ { arrayLayerCount: 0, baseArrayLayer: 1, _success: true },
+ { arrayLayerCount: 0, baseArrayLayer: ARRAY_LAYER_COUNT_2D - 1, _success: true },
+ { arrayLayerCount: 0, baseArrayLayer: ARRAY_LAYER_COUNT_2D, _success: false },
+ // It is an error for the array layer range of the view to exceed that of the texture
+ { arrayLayerCount: ARRAY_LAYER_COUNT_2D + 1, baseArrayLayer: 0, _success: false },
+ { arrayLayerCount: ARRAY_LAYER_COUNT_2D, baseArrayLayer: 1, _success: false },
+ { arrayLayerCount: 2, baseArrayLayer: ARRAY_LAYER_COUNT_2D - 1, _success: false },
+ { arrayLayerCount: 1, baseArrayLayer: ARRAY_LAYER_COUNT_2D, _success: false },
+ ])
+ .fn(async t => {
+ const { dimension = '2d-array', arrayLayerCount, baseArrayLayer, _success } = t.params;
- const descriptor = t.getDescriptor({
- dimension,
- arrayLayerCount,
- mipLevelCount,
- baseMipLevel,
- });
+ const texture = t.createTexture({ arrayLayerCount: ARRAY_LAYER_COUNT_2D });
- t.expectValidationError(() => {
- texture.createView(descriptor);
- }, !_success);
-}).params([
- { _success: true }, // default view works
- { arrayLayerCount: 1, _success: true }, // it is OK to create a 2D texture view on a 2D texture
- { arrayLayerCount: 2, _success: false }, // it is an error to view a layer past the end of the texture
- { dimension: '2d-array', arrayLayerCount: 1, _success: true }, // it is OK to create a 1-layer 2D array texture view on a 2D texture
- // mip level is in range
- { mipLevelCount: 1, baseMipLevel: MIP_LEVEL_COUNT - 1, _success: true },
- { mipLevelCount: 2, baseMipLevel: MIP_LEVEL_COUNT - 2, _success: true },
- // baseMipLevel == k && mipLevelCount == 0 means to use levels k..end
- { mipLevelCount: 0, baseMipLevel: 0, _success: true },
- { mipLevelCount: 0, baseMipLevel: 1, _success: true },
- { mipLevelCount: 0, baseMipLevel: MIP_LEVEL_COUNT - 1, _success: true },
- { mipLevelCount: 0, baseMipLevel: MIP_LEVEL_COUNT, _success: false },
- // it is an error to make the mip level out of range
- { mipLevelCount: MIP_LEVEL_COUNT + 1, baseMipLevel: 0, _success: false },
- { mipLevelCount: MIP_LEVEL_COUNT, baseMipLevel: 1, _success: false },
- { mipLevelCount: 2, baseMipLevel: MIP_LEVEL_COUNT - 1, _success: false },
- { mipLevelCount: 1, baseMipLevel: MIP_LEVEL_COUNT, _success: false },
-]);
-
-g.test('creating texture view on a 2D array texture', async t => {
- const { dimension = '2d-array', arrayLayerCount, baseArrayLayer, _success } = t.params;
-
- const texture = t.createTexture({ arrayLayerCount: ARRAY_LAYER_COUNT_2D });
+ const descriptor = t.getDescriptor({
+ dimension,
+ arrayLayerCount,
+ baseArrayLayer,
+ });
- const descriptor = t.getDescriptor({
- dimension,
- arrayLayerCount,
- baseArrayLayer,
+ t.expectValidationError(() => {
+ texture.createView(descriptor);
+ }, !_success);
});
- t.expectValidationError(() => {
- texture.createView(descriptor);
- }, !_success);
-}).params([
- { _success: true }, // default view works
- { dimension: '2d', arrayLayerCount: 1, _success: true }, // it is OK to create a 2D texture view on a 2D array texture
- { arrayLayerCount: ARRAY_LAYER_COUNT_2D, _success: true }, // it is OK to create a 2D array texture view on a 2D array texture
- // baseArrayLayer == k && arrayLayerCount == 0 means to use layers k..end.
- { arrayLayerCount: 0, baseArrayLayer: 0, _success: true },
- { arrayLayerCount: 0, baseArrayLayer: 1, _success: true },
- { arrayLayerCount: 0, baseArrayLayer: ARRAY_LAYER_COUNT_2D - 1, _success: true },
- { arrayLayerCount: 0, baseArrayLayer: ARRAY_LAYER_COUNT_2D, _success: false },
- // It is an error for the array layer range of the view to exceed that of the texture
- { arrayLayerCount: ARRAY_LAYER_COUNT_2D + 1, baseArrayLayer: 0, _success: false },
- { arrayLayerCount: ARRAY_LAYER_COUNT_2D, baseArrayLayer: 1, _success: false },
- { arrayLayerCount: 2, baseArrayLayer: ARRAY_LAYER_COUNT_2D - 1, _success: false },
- { arrayLayerCount: 1, baseArrayLayer: ARRAY_LAYER_COUNT_2D, _success: false },
-]);
-
-g.test(
- 'Using defaults validates the same as setting values for more than 1 array layer',
- async t => {
+g.test('Using_defaults_validates_the_same_as_setting_values_for_more_than_1_array_layer')
+ .params([
+ { _success: true },
+ { format: 'rgba8unorm', _success: true },
+ { format: 'r8unorm', _success: false },
+ { dimension: '2d-array', _success: true },
+ { dimension: '2d', _success: false },
+ { arrayLayerCount: ARRAY_LAYER_COUNT_2D, _success: false }, // setting array layers to non-0 means the dimensionality will default to 2D so by itself it causes an error.
+ { arrayLayerCount: ARRAY_LAYER_COUNT_2D, dimension: '2d-array', _success: true },
+ {
+ arrayLayerCount: ARRAY_LAYER_COUNT_2D,
+ dimension: '2d-array',
+ mipLevelCount: MIP_LEVEL_COUNT,
+ _success: true,
+ },
+ ] as const)
+ .fn(async t => {
const { format, dimension, arrayLayerCount, mipLevelCount, _success } = t.params;
const texture = t.createTexture({ arrayLayerCount: ARRAY_LAYER_COUNT_2D });
@@ -146,97 +164,88 @@ g.test(
t.expectValidationError(() => {
texture.createView(descriptor);
}, !_success);
- }
-).params([
- { _success: true },
- { format: 'rgba8unorm', _success: true },
- { format: 'r8unorm', _success: false },
- { dimension: '2d-array', _success: true },
- { dimension: '2d', _success: false },
- { arrayLayerCount: ARRAY_LAYER_COUNT_2D, _success: false }, // setting array layers to non-0 means the dimensionality will default to 2D so by itself it causes an error.
- { arrayLayerCount: ARRAY_LAYER_COUNT_2D, dimension: '2d-array', _success: true },
- {
- arrayLayerCount: ARRAY_LAYER_COUNT_2D,
- dimension: '2d-array',
- mipLevelCount: MIP_LEVEL_COUNT,
- _success: true,
- },
-]);
-
-g.test('Using defaults validates the same as setting values for only 1 array layer', async t => {
- const { format, dimension, arrayLayerCount, mipLevelCount, _success } = t.params;
+ });
- const texture = t.createTexture({ arrayLayerCount: 1 });
+g.test('Using_defaults_validates_the_same_as_setting_values_for_only_1_array_layer')
+ .params([
+ { _success: true },
+ { format: 'rgba8unorm', _success: true },
+ { format: 'r8unorm', _success: false },
+ { dimension: '2d-array', _success: true },
+ { dimension: '2d', _success: true },
+ { arrayLayerCount: 0, _success: true },
+ { arrayLayerCount: 1, _success: true },
+ { arrayLayerCount: 2, _success: false },
+ { mipLevelCount: MIP_LEVEL_COUNT, _success: true },
+ { mipLevelCount: 1, _success: true },
+ ] as const)
+ .fn(async t => {
+ const { format, dimension, arrayLayerCount, mipLevelCount, _success } = t.params;
- const descriptor = { format, dimension, arrayLayerCount, mipLevelCount };
+ const texture = t.createTexture({ arrayLayerCount: 1 });
- t.expectValidationError(() => {
- texture.createView(descriptor);
- }, !_success);
-}).params([
- { _success: true },
- { format: 'rgba8unorm', _success: true },
- { format: 'r8unorm', _success: false },
- { dimension: '2d-array', _success: true },
- { dimension: '2d', _success: true },
- { arrayLayerCount: 0, _success: true },
- { arrayLayerCount: 1, _success: true },
- { arrayLayerCount: 2, _success: false },
- { mipLevelCount: MIP_LEVEL_COUNT, _success: true },
- { mipLevelCount: 1, _success: true },
-]);
-
-g.test('creating cube map texture view', async t => {
- const { dimension = '2d-array', arrayLayerCount, _success } = t.params;
-
- const texture = t.createTexture({ arrayLayerCount: 16 });
+ const descriptor = { format, dimension, arrayLayerCount, mipLevelCount };
- const descriptor = t.getDescriptor({
- dimension,
- arrayLayerCount,
+ t.expectValidationError(() => {
+ texture.createView(descriptor);
+ }, !_success);
});
- t.expectValidationError(() => {
- texture.createView(descriptor);
- }, !_success);
-}).params([
- { dimension: 'cube', arrayLayerCount: 6, _success: true }, // it is OK to create a cube map texture view with arrayLayerCount == 6
- // it is an error to create a cube map texture view with arrayLayerCount != 6
- { dimension: 'cube', arrayLayerCount: 3, _success: false },
- { dimension: 'cube', arrayLayerCount: 7, _success: false },
- { dimension: 'cube', arrayLayerCount: 12, _success: false },
- { dimension: 'cube', _success: false },
- { dimension: 'cube-array', arrayLayerCount: 12, _success: true }, // it is OK to create a cube map array texture view with arrayLayerCount % 6 == 0
- // it is an error to create a cube map array texture view with arrayLayerCount % 6 != 0
- { dimension: 'cube-array', arrayLayerCount: 11, _success: false },
- { dimension: 'cube-array', arrayLayerCount: 13, _success: false },
-]);
-
-g.test('creating cube map texture view with a non square texture', async t => {
- const { dimension, arrayLayerCount } = t.params;
-
- const nonSquareTexture = t.createTexture({
- arrayLayerCount: 18,
- width: 32,
- height: 16,
- mipLevelCount: 5,
- });
+g.test('creating_cube_map_texture_view')
+ .params([
+ { dimension: 'cube', arrayLayerCount: 6, _success: true }, // it is OK to create a cube map texture view with arrayLayerCount == 6
+ // it is an error to create a cube map texture view with arrayLayerCount != 6
+ { dimension: 'cube', arrayLayerCount: 3, _success: false },
+ { dimension: 'cube', arrayLayerCount: 7, _success: false },
+ { dimension: 'cube', arrayLayerCount: 12, _success: false },
+ { dimension: 'cube', _success: false },
+ { dimension: 'cube-array', arrayLayerCount: 12, _success: true }, // it is OK to create a cube map array texture view with arrayLayerCount % 6 == 0
+ // it is an error to create a cube map array texture view with arrayLayerCount % 6 != 0
+ { dimension: 'cube-array', arrayLayerCount: 11, _success: false },
+ { dimension: 'cube-array', arrayLayerCount: 13, _success: false },
+ ] as const)
+ .fn(async t => {
+ const { dimension = '2d-array', arrayLayerCount, _success } = t.params;
+
+ const texture = t.createTexture({ arrayLayerCount: 16 });
+
+ const descriptor = t.getDescriptor({
+ dimension,
+ arrayLayerCount,
+ });
- const descriptor = t.getDescriptor({
- dimension,
- arrayLayerCount,
+ t.expectValidationError(() => {
+ texture.createView(descriptor);
+ }, !_success);
});
- t.expectValidationError(() => {
- nonSquareTexture.createView(descriptor);
+g.test('creating_cube_map_texture_view_with_a_non_square_texture')
+ .params([
+ { dimension: 'cube', arrayLayerCount: 6 }, // it is an error to create a cube map texture view with width != height.
+ { dimension: 'cube-array', arrayLayerCount: 12 }, // it is an error to create a cube map array texture view with width != height.
+ ] as const)
+ .fn(async t => {
+ const { dimension, arrayLayerCount } = t.params;
+
+ const nonSquareTexture = t.createTexture({
+ arrayLayerCount: 18,
+ width: 32,
+ height: 16,
+ mipLevelCount: 5,
+ });
+
+ const descriptor = t.getDescriptor({
+ dimension,
+ arrayLayerCount,
+ });
+
+ t.expectValidationError(() => {
+ nonSquareTexture.createView(descriptor);
+ });
});
-}).params([
- { dimension: 'cube', arrayLayerCount: 6 }, // it is an error to create a cube map texture view with width != height.
- { dimension: 'cube-array', arrayLayerCount: 12 }, // it is an error to create a cube map array texture view with width != height.
-]);
// TODO: add more tests when rules are fully implemented.
-g.test('test the format compatibility rules when creating a texture view', async t => {
+g.test('test_the_format_compatibility_rules_when_creating_a_texture_view').fn(async t => {
const texture = t.createTexture({ arrayLayerCount: 1 });
const descriptor = t.getDescriptor({
@@ -249,7 +258,7 @@ g.test('test the format compatibility rules when creating a texture view', async
});
});
-g.test('it is invalid to use a texture view created from a destroyed texture', async t => {
+g.test('it_is_invalid_to_use_a_texture_view_created_from_a_destroyed_texture').fn(async t => {
const texture = t.createTexture({ arrayLayerCount: 1 });
const commandEncoder = t.device.createCommandEncoder();
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/error_scope.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/error_scope.spec.ts
index 1a5b8984080..eb2a2166ac0 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/error_scope.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/error_scope.spec.ts
@@ -4,7 +4,7 @@ error scope validation tests.
import { Fixture } from '../../../common/framework/fixture.js';
import { getGPU } from '../../../common/framework/gpu/implementation.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { assert, raceWithRejectOnTimeout } from '../../../common/framework/util/util.js';
class F extends Fixture {
@@ -58,9 +58,9 @@ class F extends Fixture {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('simple case where the error scope catches an error', async t => {
+g.test('simple_case_where_the_error_scope_catches_an_error').fn(async t => {
t.device.pushErrorScope('validation');
t.createErrorBuffer();
@@ -69,7 +69,7 @@ g.test('simple case where the error scope catches an error', async t => {
t.expect(error instanceof GPUValidationError);
});
-g.test('errors bubble to the parent scope if not handled by the current scope', async t => {
+g.test('errors_bubble_to_the_parent_scope_if_not_handled_by_the_current_scope').fn(async t => {
t.device.pushErrorScope('validation');
t.device.pushErrorScope('out-of-memory');
@@ -85,7 +85,7 @@ g.test('errors bubble to the parent scope if not handled by the current scope',
}
});
-g.test('if an error scope matches an error it does not bubble to the parent scope', async t => {
+g.test('if_an_error_scope_matches_an_error_it_does_not_bubble_to_the_parent_scope').fn(async t => {
t.device.pushErrorScope('validation');
t.device.pushErrorScope('validation');
@@ -101,7 +101,7 @@ g.test('if an error scope matches an error it does not bubble to the parent scop
}
});
-g.test('if no error scope handles an error it fires an uncapturederror event', async t => {
+g.test('if_no_error_scope_handles_an_error_it_fires_an_uncapturederror_event').fn(async t => {
t.device.pushErrorScope('out-of-memory');
const uncapturedErrorEvent = await t.expectUncapturedError(() => {
@@ -113,7 +113,7 @@ g.test('if no error scope handles an error it fires an uncapturederror event', a
t.expect(error === null);
});
-g.test('push/popping sibling error scopes must be balanced', async t => {
+g.test('push,popping_sibling_error_scopes_must_be_balanced').fn(async t => {
{
const promise = t.device.popErrorScope();
t.shouldReject('OperationError', promise);
@@ -133,7 +133,7 @@ g.test('push/popping sibling error scopes must be balanced', async t => {
}
});
-g.test('push/popping nested error scopes must be balanced', async t => {
+g.test('push,popping_nested_error_scopes_must_be_balanced').fn(async t => {
{
const promise = t.device.popErrorScope();
t.shouldReject('OperationError', promise);
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/fences.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/fences.spec.ts
index a89fcff13ee..32d133304ef 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/fences.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/fences.spec.ts
@@ -2,14 +2,14 @@ export const description = `
fences validation tests.
`;
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
-export const g = new TestGroup(ValidationTest);
+export const g = makeTestGroup(ValidationTest);
// TODO: Remove if https://github.com/gpuweb/gpuweb/issues/377 is decided
-g.test('wait on a fence without signaling the value is invalid', async t => {
+g.test('wait_on_a_fence_without_signaling_the_value_is_invalid').fn(async t => {
const fence = t.queue.createFence();
t.expectValidationError(() => {
@@ -19,7 +19,7 @@ g.test('wait on a fence without signaling the value is invalid', async t => {
});
// TODO: Remove if https://github.com/gpuweb/gpuweb/issues/377 is decided
-g.test('wait on a fence with a value greater than signaled value is invalid', async t => {
+g.test('wait_on_a_fence_with_a_value_greater_than_signaled_value_is_invalid').fn(async t => {
const fence = t.queue.createFence();
t.queue.signal(fence, 2);
@@ -29,7 +29,7 @@ g.test('wait on a fence with a value greater than signaled value is invalid', as
});
});
-g.test('signal a value lower than signaled value is invalid', async t => {
+g.test('signal_a_value_lower_than_signaled_value_is_invalid').fn(async t => {
const fence = t.queue.createFence({ initialValue: 1 });
t.expectValidationError(() => {
@@ -37,7 +37,7 @@ g.test('signal a value lower than signaled value is invalid', async t => {
});
});
-g.test('signal a value equal to signaled value is invalid', async t => {
+g.test('signal_a_value_equal_to_signaled_value_is_invalid').fn(async t => {
const fence = t.queue.createFence({ initialValue: 1 });
t.expectValidationError(() => {
@@ -45,7 +45,7 @@ g.test('signal a value equal to signaled value is invalid', async t => {
});
});
-g.test('increasing fence value by more than 1 succeeds', async t => {
+g.test('increasing_fence_value_by_more_than_1_succeeds').fn(async t => {
const fence = t.queue.createFence();
t.queue.signal(fence, 2);
@@ -55,29 +55,33 @@ g.test('increasing fence value by more than 1 succeeds', async t => {
await fence.onCompletion(6);
});
-g.test('signal a fence on a different device than it was created on is invalid', async t => {
- const fence = t.queue.createFence();
-
+g.test('signal_a_fence_on_a_different_device_than_it_was_created_on_is_invalid').fn(async t => {
const anotherDevice = await t.device.adapter.requestDevice();
- const anotherQueue = anotherDevice.defaultQueue;
+ const fence = anotherDevice.defaultQueue.createFence();
t.expectValidationError(() => {
- anotherQueue.signal(fence, 2);
+ t.queue.signal(fence, 2);
});
});
-g.test('signal a fence on a different device does not update fence signaled value', async t => {
- const fence = t.queue.createFence({ initialValue: 1 });
-
+g.test('signal_a_fence_on_a_different_device_does_not_update_fence_signaled_value').fn(async t => {
const anotherDevice = await t.device.adapter.requestDevice();
- const anotherQueue = anotherDevice.defaultQueue;
+ const fence = anotherDevice.defaultQueue.createFence({ initialValue: 1 });
t.expectValidationError(() => {
- anotherQueue.signal(fence, 2);
+ t.queue.signal(fence, 2);
});
t.expect(fence.getCompletedValue() === 1);
- t.queue.signal(fence, 2);
+ anotherDevice.pushErrorScope('validation');
+
+ anotherDevice.defaultQueue.signal(fence, 2);
await fence.onCompletion(2);
+ t.expect(fence.getCompletedValue() === 2);
+
+ const gpuValidationError = await anotherDevice.popErrorScope();
+ if (gpuValidationError instanceof GPUValidationError) {
+ t.fail(`Captured validation error - ${gpuValidationError.message}`);
+ }
});
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/queue_submit.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/queue_submit.spec.ts
index b8d93a920a0..fd11ec0c8b0 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/queue_submit.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/queue_submit.spec.ts
@@ -2,13 +2,13 @@ export const description = `
queue submit validation tests.
`;
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
-export const g = new TestGroup(ValidationTest);
+export const g = makeTestGroup(ValidationTest);
-g.test('submitting with a mapped buffer is disallowed', async t => {
+g.test('submitting_with_a_mapped_buffer_is_disallowed').fn(async t => {
const buffer = t.device.createBuffer({
size: 4,
usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC,
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass.spec.ts
index 88801f49b9e..f0e36b3b350 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass.spec.ts
@@ -2,14 +2,14 @@ export const description = `
render pass validation tests.
`;
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
class F extends ValidationTest {
getUniformBuffer(): GPUBuffer {
return this.device.createBuffer({
- size: 4 * Float32Array.BYTES_PER_ELEMENT,
+ size: 8 * Float32Array.BYTES_PER_ELEMENT,
usage: GPUBufferUsage.UNIFORM,
});
}
@@ -67,80 +67,82 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('it is invalid to draw in a render pass with missing bind groups', async t => {
- const { setBindGroup1, setBindGroup2, _success } = t.params;
+g.test('it_is_invalid_to_draw_in_a_render_pass_with_missing_bind_groups')
+ .params([
+ { setBindGroup1: true, setBindGroup2: true, _success: true },
+ { setBindGroup1: true, setBindGroup2: false, _success: false },
+ { setBindGroup1: false, setBindGroup2: true, _success: false },
+ { setBindGroup1: false, setBindGroup2: false, _success: false },
+ ])
+ .fn(async t => {
+ const { setBindGroup1, setBindGroup2, _success } = t.params;
- const uniformBuffer = t.getUniformBuffer();
+ const uniformBuffer = t.getUniformBuffer();
- const bindGroupLayout1 = t.device.createBindGroupLayout({
- entries: [
- {
- binding: 0,
- visibility: GPUShaderStage.VERTEX,
- type: 'uniform-buffer',
- },
- ],
- });
-
- const bindGroup1 = t.device.createBindGroup({
- entries: [
- {
- binding: 0,
- resource: {
- buffer: uniformBuffer,
+ const bindGroupLayout1 = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.VERTEX,
+ type: 'uniform-buffer',
},
- },
- ],
- layout: bindGroupLayout1,
- });
+ ],
+ });
- const bindGroupLayout2 = t.device.createBindGroupLayout({
- entries: [
- {
- binding: 0,
- visibility: GPUShaderStage.FRAGMENT,
- type: 'uniform-buffer',
- },
- ],
- });
+ const bindGroup1 = t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ },
+ },
+ ],
+ layout: bindGroupLayout1,
+ });
- const bindGroup2 = t.device.createBindGroup({
- entries: [
- {
- binding: 0,
- resource: {
- buffer: uniformBuffer,
+ const bindGroupLayout2 = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.FRAGMENT,
+ type: 'uniform-buffer',
},
- },
- ],
- layout: bindGroupLayout2,
- });
+ ],
+ });
- const pipelineLayout = t.device.createPipelineLayout({
- bindGroupLayouts: [bindGroupLayout1, bindGroupLayout2],
- });
+ const bindGroup2 = t.device.createBindGroup({
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ },
+ },
+ ],
+ layout: bindGroupLayout2,
+ });
- const pipeline = t.createRenderPipeline(pipelineLayout);
+ const pipelineLayout = t.device.createPipelineLayout({
+ bindGroupLayouts: [bindGroupLayout1, bindGroupLayout2],
+ });
- const commandEncoder = t.device.createCommandEncoder();
- const renderPass = t.beginRenderPass(commandEncoder);
- renderPass.setPipeline(pipeline);
- if (setBindGroup1) {
- renderPass.setBindGroup(0, bindGroup1);
- }
- if (setBindGroup2) {
- renderPass.setBindGroup(1, bindGroup2);
- }
- renderPass.draw(3, 1, 0, 0);
- renderPass.endPass();
- t.expectValidationError(() => {
- commandEncoder.finish();
- }, !_success);
-}).params([
- { setBindGroup1: true, setBindGroup2: true, _success: true },
- { setBindGroup1: true, setBindGroup2: false, _success: false },
- { setBindGroup1: false, setBindGroup2: true, _success: false },
- { setBindGroup1: false, setBindGroup2: false, _success: false },
-]);
+ const pipeline = t.createRenderPipeline(pipelineLayout);
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setPipeline(pipeline);
+ if (setBindGroup1) {
+ renderPass.setBindGroup(0, bindGroup1);
+ }
+ if (setBindGroup2) {
+ renderPass.setBindGroup(1, bindGroup2);
+ }
+ renderPass.draw(3, 1, 0, 0);
+ renderPass.endPass();
+ t.expectValidationError(() => {
+ commandEncoder.finish();
+ }, !_success);
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass_descriptor.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass_descriptor.spec.ts
index 192de3adfdd..a40a0f13e92 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass_descriptor.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/render_pass_descriptor.spec.ts
@@ -2,7 +2,7 @@ export const description = `
render pass descriptor validation tests.
`;
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
@@ -75,9 +75,9 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('a render pass with only one color is ok', t => {
+g.test('a_render_pass_with_only_one_color_is_ok').fn(t => {
const colorTexture = t.createTexture({ format: 'rgba8unorm' });
const descriptor = {
colorAttachments: [t.getColorAttachment(colorTexture)],
@@ -86,7 +86,7 @@ g.test('a render pass with only one color is ok', t => {
t.tryRenderPass(true, descriptor);
});
-g.test('a render pass with only one depth attachment is ok', t => {
+g.test('a_render_pass_with_only_one_depth_attachment_is_ok').fn(t => {
const depthStencilTexture = t.createTexture({ format: 'depth24plus-stencil8' });
const descriptor = {
colorAttachments: [],
@@ -96,22 +96,24 @@ g.test('a render pass with only one depth attachment is ok', t => {
t.tryRenderPass(true, descriptor);
});
-g.test('OOB color attachment indices are handled', async t => {
- const { colorAttachmentsCount, _success } = t.params;
-
- const colorAttachments = [];
- for (let i = 0; i < colorAttachmentsCount; i++) {
- const colorTexture = t.createTexture();
- colorAttachments.push(t.getColorAttachment(colorTexture));
- }
-
- await t.tryRenderPass(_success, { colorAttachments });
-}).params([
- { colorAttachmentsCount: 4, _success: true }, // Control case
- { colorAttachmentsCount: 5, _success: false }, // Out of bounds
-]);
+g.test('OOB_color_attachment_indices_are_handled')
+ .params([
+ { colorAttachmentsCount: 4, _success: true }, // Control case
+ { colorAttachmentsCount: 5, _success: false }, // Out of bounds
+ ])
+ .fn(async t => {
+ const { colorAttachmentsCount, _success } = t.params;
+
+ const colorAttachments = [];
+ for (let i = 0; i < colorAttachmentsCount; i++) {
+ const colorTexture = t.createTexture();
+ colorAttachments.push(t.getColorAttachment(colorTexture));
+ }
+
+ await t.tryRenderPass(_success, { colorAttachments });
+ });
-g.test('attachments must have the same size', async t => {
+g.test('attachments_must_have_the_same_size').fn(async t => {
const colorTexture1x1A = t.createTexture({ width: 1, height: 1, format: 'rgba8unorm' });
const colorTexture1x1B = t.createTexture({ width: 1, height: 1, format: 'rgba8unorm' });
const colorTexture2x2 = t.createTexture({ width: 2, height: 2, format: 'rgba8unorm' });
@@ -163,7 +165,7 @@ g.test('attachments must have the same size', async t => {
}
});
-g.test('attachments must match whether they are used for color or depth stencil', async t => {
+g.test('attachments_must_match_whether_they_are_used_for_color_or_depth_stencil').fn(async t => {
const colorTexture = t.createTexture({ format: 'rgba8unorm' });
const depthStencilTexture = t.createTexture({ format: 'depth24plus-stencil8' });
@@ -186,158 +188,164 @@ g.test('attachments must match whether they are used for color or depth stencil'
}
});
-g.test('check layer count for color or depth stencil', async t => {
- const { arrayLayerCount, baseArrayLayer, _success } = t.params;
-
- const ARRAY_LAYER_COUNT = 10;
- const MIP_LEVEL_COUNT = 1;
- const COLOR_FORMAT = 'rgba8unorm';
- const DEPTH_STENCIL_FORMAT = 'depth24plus-stencil8';
-
- const colorTexture = t.createTexture({
- format: COLOR_FORMAT,
- width: 32,
- height: 32,
- mipLevelCount: MIP_LEVEL_COUNT,
- arrayLayerCount: ARRAY_LAYER_COUNT,
- });
- const depthStencilTexture = t.createTexture({
- format: DEPTH_STENCIL_FORMAT,
- width: 32,
- height: 32,
- mipLevelCount: MIP_LEVEL_COUNT,
- arrayLayerCount: ARRAY_LAYER_COUNT,
- });
-
- const baseTextureViewDescriptor: GPUTextureViewDescriptor = {
- dimension: '2d-array',
- baseArrayLayer,
- arrayLayerCount,
- baseMipLevel: 0,
- mipLevelCount: MIP_LEVEL_COUNT,
- };
-
- {
- // Check 2D array texture view for color
- const textureViewDescriptor: GPUTextureViewDescriptor = {
- ...baseTextureViewDescriptor,
+g.test('check_layer_count_for_color_or_depth_stencil')
+ .params([
+ { arrayLayerCount: 5, baseArrayLayer: 0, _success: false }, // using 2D array texture view with arrayLayerCount > 1 is not allowed
+ { arrayLayerCount: 1, baseArrayLayer: 0, _success: true }, // using 2D array texture view that covers the first layer of the texture is OK
+ { arrayLayerCount: 1, baseArrayLayer: 9, _success: true }, // using 2D array texture view that covers the last layer is OK for depth stencil
+ ])
+ .fn(async t => {
+ const { arrayLayerCount, baseArrayLayer, _success } = t.params;
+
+ const ARRAY_LAYER_COUNT = 10;
+ const MIP_LEVEL_COUNT = 1;
+ const COLOR_FORMAT = 'rgba8unorm';
+ const DEPTH_STENCIL_FORMAT = 'depth24plus-stencil8';
+
+ const colorTexture = t.createTexture({
format: COLOR_FORMAT,
- };
-
- const descriptor: GPURenderPassDescriptor = {
- colorAttachments: [t.getColorAttachment(colorTexture, textureViewDescriptor)],
- };
-
- await t.tryRenderPass(_success, descriptor);
- }
- {
- // Check 2D array texture view for depth stencil
- const textureViewDescriptor: GPUTextureViewDescriptor = {
- ...baseTextureViewDescriptor,
+ width: 32,
+ height: 32,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ });
+ const depthStencilTexture = t.createTexture({
format: DEPTH_STENCIL_FORMAT,
- };
+ width: 32,
+ height: 32,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ });
- const descriptor: GPURenderPassDescriptor = {
- colorAttachments: [],
- depthStencilAttachment: t.getDepthStencilAttachment(
- depthStencilTexture,
- textureViewDescriptor
- ),
+ const baseTextureViewDescriptor: GPUTextureViewDescriptor = {
+ dimension: '2d-array',
+ baseArrayLayer,
+ arrayLayerCount,
+ baseMipLevel: 0,
+ mipLevelCount: MIP_LEVEL_COUNT,
};
- await t.tryRenderPass(_success, descriptor);
- }
-}).params([
- { arrayLayerCount: 5, baseArrayLayer: 0, _success: false }, // using 2D array texture view with arrayLayerCount > 1 is not allowed
- { arrayLayerCount: 1, baseArrayLayer: 0, _success: true }, // using 2D array texture view that covers the first layer of the texture is OK
- { arrayLayerCount: 1, baseArrayLayer: 9, _success: true }, // using 2D array texture view that covers the last layer is OK for depth stencil
-]);
-
-g.test('check mip level count for color or depth stencil', async t => {
- const { mipLevelCount, baseMipLevel, _success } = t.params;
-
- const ARRAY_LAYER_COUNT = 1;
- const MIP_LEVEL_COUNT = 4;
- const COLOR_FORMAT = 'rgba8unorm';
- const DEPTH_STENCIL_FORMAT = 'depth24plus-stencil8';
-
- const colorTexture = t.createTexture({
- format: COLOR_FORMAT,
- width: 32,
- height: 32,
- mipLevelCount: MIP_LEVEL_COUNT,
- arrayLayerCount: ARRAY_LAYER_COUNT,
- });
- const depthStencilTexture = t.createTexture({
- format: DEPTH_STENCIL_FORMAT,
- width: 32,
- height: 32,
- mipLevelCount: MIP_LEVEL_COUNT,
- arrayLayerCount: ARRAY_LAYER_COUNT,
+ {
+ // Check 2D array texture view for color
+ const textureViewDescriptor: GPUTextureViewDescriptor = {
+ ...baseTextureViewDescriptor,
+ format: COLOR_FORMAT,
+ };
+
+ const descriptor: GPURenderPassDescriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture, textureViewDescriptor)],
+ };
+
+ await t.tryRenderPass(_success, descriptor);
+ }
+ {
+ // Check 2D array texture view for depth stencil
+ const textureViewDescriptor: GPUTextureViewDescriptor = {
+ ...baseTextureViewDescriptor,
+ format: DEPTH_STENCIL_FORMAT,
+ };
+
+ const descriptor: GPURenderPassDescriptor = {
+ colorAttachments: [],
+ depthStencilAttachment: t.getDepthStencilAttachment(
+ depthStencilTexture,
+ textureViewDescriptor
+ ),
+ };
+
+ await t.tryRenderPass(_success, descriptor);
+ }
});
- const baseTextureViewDescriptor: GPUTextureViewDescriptor = {
- dimension: '2d',
- baseArrayLayer: 0,
- arrayLayerCount: ARRAY_LAYER_COUNT,
- baseMipLevel,
- mipLevelCount,
- };
-
- {
- // Check 2D texture view for color
- const textureViewDescriptor: GPUTextureViewDescriptor = {
- ...baseTextureViewDescriptor,
+g.test('check_mip_level_count_for_color_or_depth_stencil')
+ .params([
+ { mipLevelCount: 2, baseMipLevel: 0, _success: false }, // using 2D texture view with mipLevelCount > 1 is not allowed
+ { mipLevelCount: 1, baseMipLevel: 0, _success: true }, // using 2D texture view that covers the first level of the texture is OK
+ { mipLevelCount: 1, baseMipLevel: 3, _success: true }, // using 2D texture view that covers the last level of the texture is OK
+ ])
+ .fn(async t => {
+ const { mipLevelCount, baseMipLevel, _success } = t.params;
+
+ const ARRAY_LAYER_COUNT = 1;
+ const MIP_LEVEL_COUNT = 4;
+ const COLOR_FORMAT = 'rgba8unorm';
+ const DEPTH_STENCIL_FORMAT = 'depth24plus-stencil8';
+
+ const colorTexture = t.createTexture({
format: COLOR_FORMAT,
- };
+ width: 32,
+ height: 32,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ });
+ const depthStencilTexture = t.createTexture({
+ format: DEPTH_STENCIL_FORMAT,
+ width: 32,
+ height: 32,
+ mipLevelCount: MIP_LEVEL_COUNT,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ });
- const descriptor: GPURenderPassDescriptor = {
- colorAttachments: [t.getColorAttachment(colorTexture, textureViewDescriptor)],
+ const baseTextureViewDescriptor: GPUTextureViewDescriptor = {
+ dimension: '2d',
+ baseArrayLayer: 0,
+ arrayLayerCount: ARRAY_LAYER_COUNT,
+ baseMipLevel,
+ mipLevelCount,
};
- await t.tryRenderPass(_success, descriptor);
- }
- {
- // Check 2D texture view for depth stencil
- const textureViewDescriptor: GPUTextureViewDescriptor = {
- ...baseTextureViewDescriptor,
- format: DEPTH_STENCIL_FORMAT,
- };
+ {
+ // Check 2D texture view for color
+ const textureViewDescriptor: GPUTextureViewDescriptor = {
+ ...baseTextureViewDescriptor,
+ format: COLOR_FORMAT,
+ };
+
+ const descriptor: GPURenderPassDescriptor = {
+ colorAttachments: [t.getColorAttachment(colorTexture, textureViewDescriptor)],
+ };
+
+ await t.tryRenderPass(_success, descriptor);
+ }
+ {
+ // Check 2D texture view for depth stencil
+ const textureViewDescriptor: GPUTextureViewDescriptor = {
+ ...baseTextureViewDescriptor,
+ format: DEPTH_STENCIL_FORMAT,
+ };
+
+ const descriptor: GPURenderPassDescriptor = {
+ colorAttachments: [],
+ depthStencilAttachment: t.getDepthStencilAttachment(
+ depthStencilTexture,
+ textureViewDescriptor
+ ),
+ };
+
+ await t.tryRenderPass(_success, descriptor);
+ }
+ });
+
+g.test('it_is_invalid_to_set_resolve_target_if_color_attachment_is_non_multisampled').fn(
+ async t => {
+ const colorTexture = t.createTexture({ sampleCount: 1 });
+ const resolveTargetTexture = t.createTexture({ sampleCount: 1 });
const descriptor: GPURenderPassDescriptor = {
- colorAttachments: [],
- depthStencilAttachment: t.getDepthStencilAttachment(
- depthStencilTexture,
- textureViewDescriptor
- ),
+ colorAttachments: [
+ {
+ attachment: colorTexture.createView(),
+ resolveTarget: resolveTargetTexture.createView(),
+ loadValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ },
+ ],
};
- await t.tryRenderPass(_success, descriptor);
+ await t.tryRenderPass(false, descriptor);
}
-}).params([
- { mipLevelCount: 2, baseMipLevel: 0, _success: false }, // using 2D texture view with mipLevelCount > 1 is not allowed
- { mipLevelCount: 1, baseMipLevel: 0, _success: true }, // using 2D texture view that covers the first level of the texture is OK
- { mipLevelCount: 1, baseMipLevel: 3, _success: true }, // using 2D texture view that covers the last level of the texture is OK
-]);
-
-g.test('it is invalid to set resolve target if color attachment is non multisampled', async t => {
- const colorTexture = t.createTexture({ sampleCount: 1 });
- const resolveTargetTexture = t.createTexture({ sampleCount: 1 });
-
- const descriptor: GPURenderPassDescriptor = {
- colorAttachments: [
- {
- attachment: colorTexture.createView(),
- resolveTarget: resolveTargetTexture.createView(),
- loadValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
- },
- ],
- };
-
- await t.tryRenderPass(false, descriptor);
-});
+);
-g.test('check the use of multisampled textures as color attachments', async t => {
+g.test('check_the_use_of_multisampled_textures_as_color_attachments').fn(async t => {
const colorTexture = t.createTexture({ sampleCount: 1 });
const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
@@ -361,7 +369,7 @@ g.test('check the use of multisampled textures as color attachments', async t =>
}
});
-g.test('it is invalid to use a multisampled resolve target', async t => {
+g.test('it_is_invalid_to_use_a_multisampled_resolve_target').fn(async t => {
const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
const multisampledResolveTargetTexture = t.createTexture({ sampleCount: 4 });
@@ -375,35 +383,39 @@ g.test('it is invalid to use a multisampled resolve target', async t => {
await t.tryRenderPass(false, descriptor);
});
-g.test('it is invalid to use a resolve target with array layer count greater than 1', async t => {
- const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
- const resolveTargetTexture = t.createTexture({ arrayLayerCount: 2 });
+g.test('it_is_invalid_to_use_a_resolve_target_with_array_layer_count_greater_than_1').fn(
+ async t => {
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ arrayLayerCount: 2 });
- const colorAttachment = t.getColorAttachment(multisampledColorTexture);
- colorAttachment.resolveTarget = resolveTargetTexture.createView();
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTexture.createView();
- const descriptor: GPURenderPassDescriptor = {
- colorAttachments: [colorAttachment],
- };
+ const descriptor: GPURenderPassDescriptor = {
+ colorAttachments: [colorAttachment],
+ };
- await t.tryRenderPass(false, descriptor);
-});
+ await t.tryRenderPass(false, descriptor);
+ }
+);
-g.test('it is invalid to use a resolve target with mipmap level count greater than 1', async t => {
- const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
- const resolveTargetTexture = t.createTexture({ mipLevelCount: 2 });
+g.test('it_is_invalid_to_use_a_resolve_target_with_mipmap_level_count_greater_than_1').fn(
+ async t => {
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ mipLevelCount: 2 });
- const colorAttachment = t.getColorAttachment(multisampledColorTexture);
- colorAttachment.resolveTarget = resolveTargetTexture.createView();
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTexture.createView();
- const descriptor: GPURenderPassDescriptor = {
- colorAttachments: [colorAttachment],
- };
+ const descriptor: GPURenderPassDescriptor = {
+ colorAttachments: [colorAttachment],
+ };
- await t.tryRenderPass(false, descriptor);
-});
+ await t.tryRenderPass(false, descriptor);
+ }
+);
-g.test('it is invalid to use a resolve target whose usage is not output attachment', async t => {
+g.test('it_is_invalid_to_use_a_resolve_target_whose_usage_is_not_output_attachment').fn(async t => {
const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
const resolveTargetTexture = t.createTexture({
usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
@@ -419,7 +431,7 @@ g.test('it is invalid to use a resolve target whose usage is not output attachme
await t.tryRenderPass(false, descriptor);
});
-g.test('it is invalid to use a resolve target in error state', async t => {
+g.test('it_is_invalid_to_use_a_resolve_target_in_error_state').fn(async t => {
const ARRAY_LAYER_COUNT = 1;
const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
@@ -441,35 +453,39 @@ g.test('it is invalid to use a resolve target in error state', async t => {
await t.tryRenderPass(false, descriptor);
});
-g.test('use of multisampled attachment and non multisampled resolve target is allowed', async t => {
- const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
- const resolveTargetTexture = t.createTexture({ sampleCount: 1 });
+g.test('use_of_multisampled_attachment_and_non_multisampled_resolve_target_is_allowed').fn(
+ async t => {
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ sampleCount: 1 });
- const colorAttachment = t.getColorAttachment(multisampledColorTexture);
- colorAttachment.resolveTarget = resolveTargetTexture.createView();
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTexture.createView();
- const descriptor: GPURenderPassDescriptor = {
- colorAttachments: [colorAttachment],
- };
+ const descriptor: GPURenderPassDescriptor = {
+ colorAttachments: [colorAttachment],
+ };
- t.tryRenderPass(true, descriptor);
-});
+ t.tryRenderPass(true, descriptor);
+ }
+);
-g.test('use a resolve target in a format different than the attachment is not allowed', async t => {
- const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
- const resolveTargetTexture = t.createTexture({ format: 'bgra8unorm' });
+g.test('use_a_resolve_target_in_a_format_different_than_the_attachment_is_not_allowed').fn(
+ async t => {
+ const multisampledColorTexture = t.createTexture({ sampleCount: 4 });
+ const resolveTargetTexture = t.createTexture({ format: 'bgra8unorm' });
- const colorAttachment = t.getColorAttachment(multisampledColorTexture);
- colorAttachment.resolveTarget = resolveTargetTexture.createView();
+ const colorAttachment = t.getColorAttachment(multisampledColorTexture);
+ colorAttachment.resolveTarget = resolveTargetTexture.createView();
- const descriptor: GPURenderPassDescriptor = {
- colorAttachments: [colorAttachment],
- };
+ const descriptor: GPURenderPassDescriptor = {
+ colorAttachments: [colorAttachment],
+ };
- await t.tryRenderPass(false, descriptor);
-});
+ await t.tryRenderPass(false, descriptor);
+ }
+);
-g.test('size of the resolve target must be the same as the color attachment', async t => {
+g.test('size_of_the_resolve_target_must_be_the_same_as_the_color_attachment').fn(async t => {
const size = 16;
const multisampledColorTexture = t.createTexture({ width: size, height: size, sampleCount: 4 });
const resolveTargetTexture = t.createTexture({
@@ -507,7 +523,7 @@ g.test('size of the resolve target must be the same as the color attachment', as
}
});
-g.test('check depth stencil attachment sample counts mismatch', async t => {
+g.test('check_depth_stencil_attachment_sample_counts_mismatch').fn(async t => {
const multisampledDepthStencilTexture = t.createTexture({
sampleCount: 4,
format: 'depth24plus-stencil8',
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBindGroup.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBindGroup.spec.ts
index 2965fc39281..c7bbd9e873d 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBindGroup.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBindGroup.spec.ts
@@ -2,8 +2,8 @@ export const description = `
setBindGroup validation tests.
`;
-import { pcombine, poptions } from '../../../common/framework/params.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { poptions, params } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
@@ -48,133 +48,139 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
-
-g.test('dynamic offsets passed but not expected/compute pass', async t => {
- const bindGroupLayout = t.device.createBindGroupLayout({ entries: [] });
- const bindGroup = t.device.createBindGroup({ layout: bindGroupLayout, entries: [] });
-
- const { type } = t.params;
- const dynamicOffsets = [0];
-
- t.expectValidationError(() => {
- if (type === 'compute') {
- const encoder = t.device.createCommandEncoder();
- const computePass = encoder.beginComputePass();
- computePass.setBindGroup(0, bindGroup, dynamicOffsets);
- computePass.endPass();
- encoder.finish();
- } else if (type === 'renderpass') {
- const encoder = t.device.createCommandEncoder();
- const renderPass = encoder.beginRenderPass({
- colorAttachments: [
- {
- attachment: t.makeAttachmentTexture().createView(),
- loadValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
- },
- ],
- });
- renderPass.setBindGroup(0, bindGroup, dynamicOffsets);
- renderPass.endPass();
- encoder.finish();
- } else if (type === 'renderbundle') {
- const encoder = t.device.createRenderBundleEncoder({
- colorFormats: ['rgba8unorm'],
- });
- encoder.setBindGroup(0, bindGroup, dynamicOffsets);
- encoder.finish();
- } else {
- t.fail();
- }
- });
-}).params(poptions('type', ['compute', 'renderpass', 'renderbundle']));
-
-g.test('dynamic offsets match expectations in pass encoder', async t => {
- // Dynamic buffer offsets require offset to be divisible by 256
- const MIN_DYNAMIC_BUFFER_OFFSET_ALIGNMENT = 256;
- const BINDING_SIZE = 9;
-
- const bindGroupLayout = t.device.createBindGroupLayout({
- entries: [
- {
- binding: 0,
- visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,
- type: 'uniform-buffer',
- hasDynamicOffset: true,
- },
- {
- binding: 1,
- visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,
- type: 'storage-buffer',
- hasDynamicOffset: true,
- },
- ],
+export const g = makeTestGroup(F);
+
+g.test('dynamic_offsets_passed_but_not_expected,compute_pass')
+ .params(poptions('type', ['compute', 'renderpass', 'renderbundle']))
+ .fn(async t => {
+ const bindGroupLayout = t.device.createBindGroupLayout({ entries: [] });
+ const bindGroup = t.device.createBindGroup({ layout: bindGroupLayout, entries: [] });
+
+ const { type } = t.params;
+ const dynamicOffsets = [0];
+
+ t.expectValidationError(() => {
+ if (type === 'compute') {
+ const encoder = t.device.createCommandEncoder();
+ const computePass = encoder.beginComputePass();
+ computePass.setBindGroup(0, bindGroup, dynamicOffsets);
+ computePass.endPass();
+ encoder.finish();
+ } else if (type === 'renderpass') {
+ const encoder = t.device.createCommandEncoder();
+ const renderPass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ attachment: t.makeAttachmentTexture().createView(),
+ loadValue: { r: 1.0, g: 0.0, b: 0.0, a: 1.0 },
+ },
+ ],
+ });
+ renderPass.setBindGroup(0, bindGroup, dynamicOffsets);
+ renderPass.endPass();
+ encoder.finish();
+ } else if (type === 'renderbundle') {
+ const encoder = t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ });
+ encoder.setBindGroup(0, bindGroup, dynamicOffsets);
+ encoder.finish();
+ } else {
+ t.fail();
+ }
+ });
});
- const uniformBuffer = t.device.createBuffer({
- size: 2 * MIN_DYNAMIC_BUFFER_OFFSET_ALIGNMENT + 8,
- usage: GPUBufferUsage.UNIFORM,
- });
+g.test('dynamic_offsets_match_expectations_in_pass_encoder')
+ .params(
+ params()
+ .combine(poptions('type', ['compute', 'renderpass', 'renderbundle']))
+ .combine([
+ { dynamicOffsets: [256, 0], _success: true }, // Dynamic offsets aligned
+ { dynamicOffsets: [1, 2], _success: false }, // Dynamic offsets not aligned
+
+ // Wrong number of dynamic offsets
+ { dynamicOffsets: [256, 0, 0], _success: false },
+ { dynamicOffsets: [256], _success: false },
+ { dynamicOffsets: [], _success: false },
+
+ // Dynamic uniform buffer out of bounds because of binding size
+ { dynamicOffsets: [512, 0], _success: false },
+ { dynamicOffsets: [1024, 0], _success: false },
+ { dynamicOffsets: [0xffffffff, 0], _success: false },
+
+ // Dynamic storage buffer out of bounds because of binding size
+ { dynamicOffsets: [0, 512], _success: false },
+ { dynamicOffsets: [0, 1024], _success: false },
+ { dynamicOffsets: [0, 0xffffffff], _success: false },
+ ])
+ )
+ .fn(async t => {
+ // Dynamic buffer offsets require offset to be divisible by 256
+ const MIN_DYNAMIC_BUFFER_OFFSET_ALIGNMENT = 256;
+ const BINDING_SIZE = 9;
+
+ const bindGroupLayout = t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,
+ type: 'uniform-buffer',
+ hasDynamicOffset: true,
+ },
+ {
+ binding: 1,
+ visibility: GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,
+ type: 'storage-buffer',
+ hasDynamicOffset: true,
+ },
+ ],
+ });
- const storageBuffer = t.device.createBuffer({
- size: 2 * MIN_DYNAMIC_BUFFER_OFFSET_ALIGNMENT + 8,
- usage: GPUBufferUsage.STORAGE,
- });
+ const uniformBuffer = t.device.createBuffer({
+ size: 2 * MIN_DYNAMIC_BUFFER_OFFSET_ALIGNMENT + 8,
+ usage: GPUBufferUsage.UNIFORM,
+ });
- const bindGroup = t.device.createBindGroup({
- layout: bindGroupLayout,
- entries: [
- {
- binding: 0,
- resource: {
- buffer: uniformBuffer,
- size: BINDING_SIZE,
+ const storageBuffer = t.device.createBuffer({
+ size: 2 * MIN_DYNAMIC_BUFFER_OFFSET_ALIGNMENT + 8,
+ usage: GPUBufferUsage.STORAGE,
+ });
+
+ const bindGroup = t.device.createBindGroup({
+ layout: bindGroupLayout,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: uniformBuffer,
+ size: BINDING_SIZE,
+ },
},
- },
- {
- binding: 1,
- resource: {
- buffer: storageBuffer,
- size: BINDING_SIZE,
+ {
+ binding: 1,
+ resource: {
+ buffer: storageBuffer,
+ size: BINDING_SIZE,
+ },
},
- },
- ],
- });
-
- const { type, dynamicOffsets, _success } = t.params;
+ ],
+ });
- t.expectValidationError(() => {
- if (type === 'compute') {
+ const { type, dynamicOffsets, _success } = t.params;
+
+ t.expectValidationError(() => {
+ if (type === 'compute') {
+ t.testComputePass(bindGroup, dynamicOffsets);
+ } else if (type === 'renderpass') {
+ t.testRenderPass(bindGroup, dynamicOffsets);
+ } else if (type === 'renderbundle') {
+ t.testRenderBundle(bindGroup, dynamicOffsets);
+ } else {
+ t.fail();
+ }
t.testComputePass(bindGroup, dynamicOffsets);
- } else if (type === 'renderpass') {
- t.testRenderPass(bindGroup, dynamicOffsets);
- } else if (type === 'renderbundle') {
- t.testRenderBundle(bindGroup, dynamicOffsets);
- } else {
- t.fail();
- }
- t.testComputePass(bindGroup, dynamicOffsets);
- }, !_success);
-}).params(
- pcombine(poptions('type', ['compute', 'renderpass', 'renderbundle']), [
- { dynamicOffsets: [256, 0], _success: true }, // Dynamic offsets aligned
- { dynamicOffsets: [1, 2], _success: false }, // Dynamic offsets not aligned
-
- // Wrong number of dynamic offsets
- { dynamicOffsets: [256, 0, 0], _success: false },
- { dynamicOffsets: [256], _success: false },
- { dynamicOffsets: [], _success: false },
-
- // Dynamic uniform buffer out of bounds because of binding size
- { dynamicOffsets: [512, 0], _success: false },
- { dynamicOffsets: [1024, 0], _success: false },
- { dynamicOffsets: [Number.MAX_SAFE_INTEGER, 0], _success: false },
-
- // Dynamic storage buffer out of bounds because of binding size
- { dynamicOffsets: [0, 512], _success: false },
- { dynamicOffsets: [0, 1024], _success: false },
- { dynamicOffsets: [0, Number.MAX_SAFE_INTEGER], _success: false },
- ])
-);
+ }, !_success);
+ });
// TODO: test error bind group
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBlendColor.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBlendColor.spec.ts
index 3dca9c7d8aa..ec0172d8668 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBlendColor.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setBlendColor.spec.ts
@@ -2,7 +2,7 @@ export const description = `
setBlendColor validation tests.
`;
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
@@ -26,9 +26,9 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('basic use of setBlendColor', t => {
+g.test('basic_use_of_setBlendColor').fn(t => {
const commandEncoder = t.device.createCommandEncoder();
const renderPass = t.beginRenderPass(commandEncoder);
renderPass.setBlendColor({ r: 0, g: 0, b: 0, a: 0 });
@@ -36,7 +36,7 @@ g.test('basic use of setBlendColor', t => {
commandEncoder.finish();
});
-g.test('setBlendColor allows any number value', t => {
+g.test('setBlendColor_allows_any_number_value').fn(t => {
const values = [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER];
for (const value of values) {
const commandEncoder = t.device.createCommandEncoder();
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setScissorRect.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setScissorRect.spec.ts
index 358f11dc839..73895f6fef8 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setScissorRect.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setScissorRect.spec.ts
@@ -2,7 +2,7 @@ export const description = `
setScissorRect validation tests.
`;
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
@@ -29,23 +29,25 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
-
-g.test('use of setScissorRect', async t => {
- const { x, y, width, height, _success } = t.params;
-
- const commandEncoder = t.device.createCommandEncoder();
- const renderPass = t.beginRenderPass(commandEncoder);
- renderPass.setScissorRect(x, y, width, height);
- renderPass.endPass();
-
- t.expectValidationError(() => {
- commandEncoder.finish();
- }, !_success);
-}).params([
- { x: 0, y: 0, width: 1, height: 1, _success: true }, // Basic use
- { x: 0, y: 0, width: 0, height: 1, _success: false }, // Width of zero is not allowed
- { x: 0, y: 0, width: 1, height: 0, _success: false }, // Height of zero is not allowed
- { x: 0, y: 0, width: 0, height: 0, _success: false }, // Both width and height of zero are not allowed
- { x: 0, y: 0, width: TEXTURE_WIDTH + 1, height: TEXTURE_HEIGHT + 1, _success: true }, // Scissor larger than the framebuffer is allowed
-]);
+export const g = makeTestGroup(F);
+
+g.test('use_of_setScissorRect')
+ .params([
+ { x: 0, y: 0, width: 1, height: 1, _success: true }, // Basic use
+ { x: 0, y: 0, width: 0, height: 1, _success: false }, // Width of zero is not allowed
+ { x: 0, y: 0, width: 1, height: 0, _success: false }, // Height of zero is not allowed
+ { x: 0, y: 0, width: 0, height: 0, _success: false }, // Both width and height of zero are not allowed
+ { x: 0, y: 0, width: TEXTURE_WIDTH + 1, height: TEXTURE_HEIGHT + 1, _success: true }, // Scissor larger than the framebuffer is allowed
+ ])
+ .fn(async t => {
+ const { x, y, width, height, _success } = t.params;
+
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setScissorRect(x, y, width, height);
+ renderPass.endPass();
+
+ t.expectValidationError(() => {
+ commandEncoder.finish();
+ }, !_success);
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setStencilReference.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setStencilReference.spec.ts
index 53ad5215666..bccc5113854 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setStencilReference.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setStencilReference.spec.ts
@@ -2,8 +2,8 @@ export const description = `
setStencilReference validation tests.
`;
-import { poptions } from '../../../common/framework/params.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { poptions } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
@@ -27,14 +27,16 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('use of setStencilReference', t => {
- const { reference } = t.params;
+g.test('use_of_setStencilReference')
+ .params(poptions('reference', [0, 0xffffffff]))
+ .fn(t => {
+ const { reference } = t.params;
- const commandEncoder = t.device.createCommandEncoder();
- const renderPass = t.beginRenderPass(commandEncoder);
- renderPass.setStencilReference(reference);
- renderPass.endPass();
- commandEncoder.finish();
-}).params(poptions('reference', [0, 0xffffffff]));
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setStencilReference(reference);
+ renderPass.endPass();
+ commandEncoder.finish();
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setVertexBuffer.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setVertexBuffer.spec.ts
index 14582bd1007..efd38fe6d34 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setVertexBuffer.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setVertexBuffer.spec.ts
@@ -2,7 +2,7 @@ export const description = `
setVertexBuffer validation tests.
`;
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { range } from '../../../common/framework/util/util.js';
import { ValidationTest } from './validation_test.js';
@@ -88,9 +88,9 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('vertex buffers inherit from previous pipeline', async t => {
+g.test('vertex_buffers_inherit_from_previous_pipeline').fn(async t => {
const pipeline1 = t.createRenderPipeline(1);
const pipeline2 = t.createRenderPipeline(2);
@@ -125,7 +125,7 @@ g.test('vertex buffers inherit from previous pipeline', async t => {
}
});
-g.test('vertex buffers do not inherit between render passes', async t => {
+g.test('vertex_buffers_do_not_inherit_between_render_passes').fn(async t => {
const pipeline1 = t.createRenderPipeline(1);
const pipeline2 = t.createRenderPipeline(2);
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setViewport.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setViewport.spec.ts
index 0f0bfa75259..29b22b14ab9 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setViewport.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/setViewport.spec.ts
@@ -2,7 +2,7 @@ export const description = `
setViewport validation tests.
`;
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
@@ -29,41 +29,43 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('use of setViewport', async t => {
- const { x, y, width, height, minDepth, maxDepth, _success } = t.params;
+g.test('use_of_setViewport')
+ .params([
+ { x: 0, y: 0, width: 1, height: 1, minDepth: 0, maxDepth: 1, _success: true }, // Basic use
+ { x: 0, y: 0, width: 0, height: 1, minDepth: 0, maxDepth: 1, _success: false }, // Width of zero is not allowed
+ { x: 0, y: 0, width: 1, height: 0, minDepth: 0, maxDepth: 1, _success: false }, // Height of zero is not allowed
+ { x: 0, y: 0, width: 0, height: 0, minDepth: 0, maxDepth: 1, _success: false }, // Both width and height of zero are not allowed
+ { x: -1, y: 0, width: 1, height: 1, minDepth: 0, maxDepth: 1, _success: true }, // Negative x is allowed
+ { x: 0, y: -1, width: 1, height: 1, minDepth: 0, maxDepth: 1, _success: true }, // Negative y is allowed
+ { x: 0, y: 0, width: -1, height: 1, minDepth: 0, maxDepth: 1, _success: false }, // Negative width is not allowed
+ { x: 0, y: 0, width: 1, height: -1, minDepth: 0, maxDepth: 1, _success: false }, // Negative height is not allowed
+ { x: 0, y: 0, width: 1, height: 1, minDepth: -1, maxDepth: 1, _success: false }, // Negative minDepth is not allowed
+ { x: 0, y: 0, width: 1, height: 1, minDepth: 0, maxDepth: -1, _success: false }, // Negative maxDepth is not allowed
+ { x: 0, y: 0, width: 1, height: 1, minDepth: 10, maxDepth: 1, _success: false }, // minDepth greater than 1 is not allowed
+ { x: 0, y: 0, width: 1, height: 1, minDepth: 0, maxDepth: 10, _success: false }, // maxDepth greater than 1 is not allowed
+ { x: 0, y: 0, width: 1, height: 1, minDepth: 0.5, maxDepth: 0.5, _success: true }, // minDepth equal to maxDepth is allowed
+ { x: 0, y: 0, width: 1, height: 1, minDepth: 0.8, maxDepth: 0.5, _success: true }, // minDepth greater than maxDepth is allowed
+ {
+ x: 0,
+ y: 0,
+ width: TEXTURE_WIDTH + 1,
+ height: TEXTURE_HEIGHT + 1,
+ minDepth: 0,
+ maxDepth: 1,
+ _success: true,
+ }, // Viewport larger than the framebuffer is allowed
+ ])
+ .fn(async t => {
+ const { x, y, width, height, minDepth, maxDepth, _success } = t.params;
- const commandEncoder = t.device.createCommandEncoder();
- const renderPass = t.beginRenderPass(commandEncoder);
- renderPass.setViewport(x, y, width, height, minDepth, maxDepth);
- renderPass.endPass();
+ const commandEncoder = t.device.createCommandEncoder();
+ const renderPass = t.beginRenderPass(commandEncoder);
+ renderPass.setViewport(x, y, width, height, minDepth, maxDepth);
+ renderPass.endPass();
- t.expectValidationError(() => {
- commandEncoder.finish();
- }, !_success);
-}).params([
- { x: 0, y: 0, width: 1, height: 1, minDepth: 0, maxDepth: 1, _success: true }, // Basic use
- { x: 0, y: 0, width: 0, height: 1, minDepth: 0, maxDepth: 1, _success: false }, // Width of zero is not allowed
- { x: 0, y: 0, width: 1, height: 0, minDepth: 0, maxDepth: 1, _success: false }, // Height of zero is not allowed
- { x: 0, y: 0, width: 0, height: 0, minDepth: 0, maxDepth: 1, _success: false }, // Both width and height of zero are not allowed
- { x: -1, y: 0, width: 1, height: 1, minDepth: 0, maxDepth: 1, _success: true }, // Negative x is allowed
- { x: 0, y: -1, width: 1, height: 1, minDepth: 0, maxDepth: 1, _success: true }, // Negative y is allowed
- { x: 0, y: 0, width: -1, height: 1, minDepth: 0, maxDepth: 1, _success: false }, // Negative width is not allowed
- { x: 0, y: 0, width: 1, height: -1, minDepth: 0, maxDepth: 1, _success: false }, // Negative height is not allowed
- { x: 0, y: 0, width: 1, height: 1, minDepth: -1, maxDepth: 1, _success: false }, // Negative minDepth is not allowed
- { x: 0, y: 0, width: 1, height: 1, minDepth: 0, maxDepth: -1, _success: false }, // Negative maxDepth is not allowed
- { x: 0, y: 0, width: 1, height: 1, minDepth: 10, maxDepth: 1, _success: false }, // minDepth greater than 1 is not allowed
- { x: 0, y: 0, width: 1, height: 1, minDepth: 0, maxDepth: 10, _success: false }, // maxDepth greater than 1 is not allowed
- { x: 0, y: 0, width: 1, height: 1, minDepth: 0.5, maxDepth: 0.5, _success: true }, // minDepth equal to maxDepth is allowed
- { x: 0, y: 0, width: 1, height: 1, minDepth: 0.8, maxDepth: 0.5, _success: true }, // minDepth greater than maxDepth is allowed
- {
- x: 0,
- y: 0,
- width: TEXTURE_WIDTH + 1,
- height: TEXTURE_HEIGHT + 1,
- minDepth: 0,
- maxDepth: 1,
- _success: true,
- }, // Viewport larger than the framebuffer is allowed
-]);
+ t.expectValidationError(() => {
+ commandEncoder.finish();
+ }, !_success);
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/validation_test.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/validation_test.ts
index 9e1ccd50b31..0a09c58eaa2 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/validation_test.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/validation_test.ts
@@ -1,36 +1,7 @@
import { unreachable } from '../../../common/framework/util/util.js';
+import { BindableResource } from '../../capability_info.js';
import { GPUTest } from '../../gpu_test.js';
-export enum BindingResourceType {
- 'error-buffer' = 'error-buffer',
- 'error-sampler' = 'error-sampler',
- 'error-textureview' = 'error-textureview',
- 'uniform-buffer' = 'uniform-buffer',
- 'storage-buffer' = 'storage-buffer',
- 'sampler' = 'sampler',
- 'sampled-textureview' = 'sampled-textureview',
- 'storage-textureview' = 'storage-textureview',
-}
-
-export function resourceBindingMatches(b: GPUBindingType, r: BindingResourceType): boolean {
- switch (b) {
- case 'storage-buffer':
- case 'readonly-storage-buffer':
- return r === 'storage-buffer';
- case 'sampled-texture':
- return r === 'sampled-textureview';
- case 'sampler':
- return r === 'sampler';
- case 'readonly-storage-texture':
- case 'writeonly-storage-texture':
- return r === 'storage-textureview';
- case 'uniform-buffer':
- return r === 'uniform-buffer';
- default:
- unreachable('unknown GPUBindingType');
- }
-}
-
export class ValidationTest extends GPUTest {
getStorageBuffer(): GPUBuffer {
return this.device.createBuffer({ size: 1024, usage: GPUBufferUsage.STORAGE });
@@ -54,6 +25,10 @@ export class ValidationTest extends GPUTest {
return this.device.createSampler();
}
+ getComparisonSampler(): GPUSampler {
+ return this.device.createSampler({ compare: 'never' });
+ }
+
getErrorSampler(): GPUSampler {
this.device.pushErrorScope('validation');
const sampler = this.device.createSampler({ lodMinClamp: -1 });
@@ -90,23 +65,25 @@ export class ValidationTest extends GPUTest {
return view;
}
- getBindingResource(bindingType: BindingResourceType): GPUBindingResource {
+ getBindingResource(bindingType: BindableResource): GPUBindingResource {
switch (bindingType) {
- case 'error-buffer':
+ case 'errorBuf':
return { buffer: this.getErrorBuffer() };
- case 'error-sampler':
+ case 'errorSamp':
return this.getErrorSampler();
- case 'error-textureview':
+ case 'errorTex':
return this.getErrorTextureView();
- case 'uniform-buffer':
+ case 'uniformBuf':
return { buffer: this.getUniformBuffer() };
- case 'storage-buffer':
+ case 'storageBuf':
return { buffer: this.getStorageBuffer() };
- case 'sampler':
+ case 'plainSamp':
return this.getSampler();
- case 'sampled-textureview':
+ case 'compareSamp':
+ return this.getComparisonSampler();
+ case 'sampledTex':
return this.getSampledTexture().createView();
- case 'storage-textureview':
+ case 'storageTex':
return this.getStorageTexture().createView();
default:
unreachable('unknown binding resource type');
@@ -128,7 +105,7 @@ export class ValidationTest extends GPUTest {
const gpuValidationError = await promise;
if (!gpuValidationError) {
niceStack.message = 'Validation error was expected.';
- this.rec.fail(niceStack);
+ this.rec.validationFailed(niceStack);
} else if (gpuValidationError instanceof GPUValidationError) {
niceStack.message = `Captured validation error - ${gpuValidationError.message}`;
this.rec.debug(niceStack);
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/vertex_state.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/vertex_state.spec.ts
index 24382306521..455dbccb8e4 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/vertex_state.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/api/validation/vertex_state.spec.ts
@@ -2,8 +2,7 @@ export const description = `
vertexState validation tests.
`;
-import * as C from '../../../common/constants.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
import { ValidationTest } from './validation_test.js';
@@ -56,15 +55,15 @@ class F extends ValidationTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('an empty vertex input is valid', t => {
+g.test('an_empty_vertex_input_is_valid').fn(t => {
const vertexState: GPUVertexStateDescriptor = {};
const descriptor = t.getDescriptor(vertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
t.device.createRenderPipeline(descriptor);
});
-g.test('a null buffer is valid', t => {
+g.test('a_null_buffer_is_valid').fn(t => {
{
// One null buffer is OK
const vertexState: GPUVertexStateDescriptor = {
@@ -136,7 +135,7 @@ g.test('a null buffer is valid', t => {
}
});
-g.test('pipeline vertex buffers are backed by attributes in vertex input', async t => {
+g.test('pipeline_vertex_buffers_are_backed_by_attributes_in_vertex_input').fn(async t => {
const vertexState: GPUVertexStateDescriptor = {
vertexBuffers: [
{
@@ -198,14 +197,14 @@ g.test('pipeline vertex buffers are backed by attributes in vertex input', async
}
});
-g.test('an arrayStride of 0 is valid', t => {
+g.test('an_arrayStride_of_0_is_valid').fn(t => {
const vertexState = {
vertexBuffers: [
{
arrayStride: 0,
attributes: [
{
- format: C.VertexFormat.Float,
+ format: 'float' as const,
offset: 0,
shaderLocation: 0,
},
@@ -226,73 +225,76 @@ g.test('an arrayStride of 0 is valid', t => {
}
});
-g.test('offset should be within vertex buffer arrayStride if arrayStride is not zero', async t => {
- const vertexState = {
- vertexBuffers: [
- {
- arrayStride: 2 * SIZEOF_FLOAT,
- attributes: [
- {
- format: C.VertexFormat.Float,
- offset: 0,
- shaderLocation: 0,
- },
- {
- format: C.VertexFormat.Float,
- offset: SIZEOF_FLOAT,
- shaderLocation: 1,
- },
- ],
- },
- ],
- };
- {
- // Control case, setting correct arrayStride and offset
- const descriptor = t.getDescriptor(vertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
- t.device.createRenderPipeline(descriptor);
- }
- {
- // Test vertex attribute offset exceed vertex buffer arrayStride range
- const badVertexState = clone(vertexState);
- badVertexState.vertexBuffers[0].attributes[1].format = C.VertexFormat.Float2;
- const descriptor = t.getDescriptor(badVertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
-
- t.expectValidationError(() => {
+g.test('offset_should_be_within_vertex_buffer_arrayStride_if_arrayStride_is_not_zero').fn(
+ async t => {
+ const vertexState = {
+ vertexBuffers: [
+ {
+ arrayStride: 2 * SIZEOF_FLOAT,
+ attributes: [
+ {
+ format: 'float' as GPUVertexFormat,
+ offset: 0,
+ shaderLocation: 0,
+ },
+ {
+ format: 'float' as GPUVertexFormat,
+ offset: SIZEOF_FLOAT,
+ shaderLocation: 1,
+ },
+ ],
+ },
+ ],
+ };
+ {
+ // Control case, setting correct arrayStride and offset
+ const descriptor = t.getDescriptor(vertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
t.device.createRenderPipeline(descriptor);
- });
- }
- {
- // Test vertex attribute offset exceed vertex buffer arrayStride range
- const badVertexState = clone(vertexState);
- badVertexState.vertexBuffers[0].arrayStride = SIZEOF_FLOAT;
- const descriptor = t.getDescriptor(badVertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
+ }
+ {
+ // Test vertex attribute offset exceed vertex buffer arrayStride range
+ const badVertexState = clone(vertexState);
+ badVertexState.vertexBuffers[0].attributes[1].format = 'float2';
+ const descriptor = t.getDescriptor(badVertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
- t.expectValidationError(() => {
+ t.expectValidationError(() => {
+ t.device.createRenderPipeline(descriptor);
+ });
+ }
+ {
+ // Test vertex attribute offset exceed vertex buffer arrayStride range
+ const badVertexState = clone(vertexState);
+ badVertexState.vertexBuffers[0].arrayStride = SIZEOF_FLOAT;
+ const descriptor = t.getDescriptor(badVertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
+
+ t.expectValidationError(() => {
+ t.device.createRenderPipeline(descriptor);
+ });
+ }
+ {
+ // It's OK if arrayStride is zero
+ const goodVertexState = clone(vertexState);
+ goodVertexState.vertexBuffers[0].arrayStride = 0;
+ const descriptor = t.getDescriptor(goodVertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
t.device.createRenderPipeline(descriptor);
- });
- }
- {
- // It's OK if arrayStride is zero
- const goodVertexState = clone(vertexState);
- goodVertexState.vertexBuffers[0].arrayStride = 0;
- const descriptor = t.getDescriptor(goodVertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
- t.device.createRenderPipeline(descriptor);
+ }
}
-});
+);
-g.test('check two attributes overlapping', async t => {
+// TODO: This should be made into an operation test.
+g.test('check_two_attributes_overlapping').fn(async t => {
const vertexState = {
vertexBuffers: [
{
arrayStride: 2 * SIZEOF_FLOAT,
attributes: [
{
- format: C.VertexFormat.Float,
+ format: 'float' as GPUVertexFormat,
offset: 0,
shaderLocation: 0,
},
{
- format: C.VertexFormat.Float,
+ format: 'float' as GPUVertexFormat,
offset: SIZEOF_FLOAT,
shaderLocation: 1,
},
@@ -307,17 +309,14 @@ g.test('check two attributes overlapping', async t => {
}
{
// Test two attributes overlapping
- const badVertexState = clone(vertexState);
- badVertexState.vertexBuffers[0].attributes[0].format = C.VertexFormat.Int2;
- const descriptor = t.getDescriptor(badVertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
-
- t.expectValidationError(() => {
- t.device.createRenderPipeline(descriptor);
- });
+ const overlappingVertexState = clone(vertexState);
+ overlappingVertexState.vertexBuffers[0].attributes[0].format = 'int2';
+ const descriptor = t.getDescriptor(overlappingVertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
+ t.device.createRenderPipeline(descriptor);
}
});
-g.test('check out of bounds condition on total number of vertex buffers', async t => {
+g.test('check_out_of_bounds_condition_on_total_number_of_vertex_buffers').fn(async t => {
const vertexBuffers: GPUVertexBufferLayoutDescriptor[] = [];
for (let i = 0; i < MAX_VERTEX_BUFFERS; i++) {
@@ -363,60 +362,62 @@ g.test('check out of bounds condition on total number of vertex buffers', async
}
});
-g.test('check out of bounds on number of vertex attributes on a single vertex buffer', async t => {
- const vertexAttributes: GPUVertexAttributeDescriptor[] = [];
+g.test('check_out_of_bounds_on_number_of_vertex_attributes_on_a_single_vertex_buffer').fn(
+ async t => {
+ const vertexAttributes: GPUVertexAttributeDescriptor[] = [];
- for (let i = 0; i < MAX_VERTEX_ATTRIBUTES; i++) {
- vertexAttributes.push({
- format: 'float',
- offset: 0,
- shaderLocation: i,
- });
- }
- {
- // Control case, setting max vertex buffer number
- const vertexState: GPUVertexStateDescriptor = {
- vertexBuffers: [
- {
- arrayStride: 0,
- attributes: vertexAttributes,
- },
- ],
- };
- const descriptor = t.getDescriptor(vertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
- t.device.createRenderPipeline(descriptor);
- }
- {
- // Test vertex attribute number exceed the limit
- const vertexState: GPUVertexStateDescriptor = {
- vertexBuffers: [
- {
- arrayStride: 0,
- attributes: [
- ...vertexAttributes,
- {
- format: 'float',
- offset: 0,
- shaderLocation: MAX_VERTEX_ATTRIBUTES,
- },
- ],
- },
- ],
- };
- const descriptor = t.getDescriptor(vertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
-
- t.expectValidationError(() => {
+ for (let i = 0; i < MAX_VERTEX_ATTRIBUTES; i++) {
+ vertexAttributes.push({
+ format: 'float',
+ offset: 0,
+ shaderLocation: i,
+ });
+ }
+ {
+ // Control case, setting max vertex buffer number
+ const vertexState: GPUVertexStateDescriptor = {
+ vertexBuffers: [
+ {
+ arrayStride: 0,
+ attributes: vertexAttributes,
+ },
+ ],
+ };
+ const descriptor = t.getDescriptor(vertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
t.device.createRenderPipeline(descriptor);
- });
+ }
+ {
+ // Test vertex attribute number exceed the limit
+ const vertexState: GPUVertexStateDescriptor = {
+ vertexBuffers: [
+ {
+ arrayStride: 0,
+ attributes: [
+ ...vertexAttributes,
+ {
+ format: 'float',
+ offset: 0,
+ shaderLocation: MAX_VERTEX_ATTRIBUTES,
+ },
+ ],
+ },
+ ],
+ };
+ const descriptor = t.getDescriptor(vertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
+
+ t.expectValidationError(() => {
+ t.device.createRenderPipeline(descriptor);
+ });
+ }
}
-});
+);
-g.test('check out of bounds on number of vertex attributes across vertex buffers', async t => {
+g.test('check_out_of_bounds_on_number_of_vertex_attributes_across_vertex_buffers').fn(async t => {
const vertexBuffers = [];
for (let i = 0; i < MAX_VERTEX_ATTRIBUTES; i++) {
vertexBuffers.push({
arrayStride: 0,
- attributes: [{ format: C.VertexFormat.Float, offset: 0, shaderLocation: i }],
+ attributes: [{ format: 'float' as const, offset: 0, shaderLocation: i }],
});
}
@@ -429,7 +430,7 @@ g.test('check out of bounds on number of vertex attributes across vertex buffers
{
// Test vertex attribute number exceed the limit
vertexBuffers[MAX_VERTEX_ATTRIBUTES - 1].attributes.push({
- format: C.VertexFormat.Float,
+ format: 'float' as const,
offset: 0,
shaderLocation: MAX_VERTEX_ATTRIBUTES,
});
@@ -442,7 +443,7 @@ g.test('check out of bounds on number of vertex attributes across vertex buffers
}
});
-g.test('check out of bounds condition on input strides', async t => {
+g.test('check_out_of_bounds_condition_on_input_strides').fn(async t => {
const vertexState = {
vertexBuffers: [{ arrayStride: MAX_VERTEX_BUFFER_ARRAY_STRIDE, attributes: [] }],
};
@@ -462,12 +463,12 @@ g.test('check out of bounds condition on input strides', async t => {
}
});
-g.test('check multiple of 4 bytes constraint on input arrayStride', async t => {
+g.test('check_multiple_of_4_bytes_constraint_on_input_arrayStride').fn(async t => {
const vertexState = {
vertexBuffers: [
{
arrayStride: 4,
- attributes: [{ format: C.VertexFormat.Uchar2, offset: 0, shaderLocation: 0 }],
+ attributes: [{ format: 'uchar2' as const, offset: 0, shaderLocation: 0 }],
},
],
};
@@ -487,12 +488,12 @@ g.test('check multiple of 4 bytes constraint on input arrayStride', async t => {
}
});
-g.test('identical duplicate attributes are invalid', async t => {
+g.test('identical_duplicate_attributes_are_invalid').fn(async t => {
const vertexState = {
vertexBuffers: [
{
arrayStride: 0,
- attributes: [{ format: C.VertexFormat.Float, offset: 0, shaderLocation: 0 }],
+ attributes: [{ format: 'float' as const, offset: 0, shaderLocation: 0 }],
},
],
};
@@ -504,7 +505,7 @@ g.test('identical duplicate attributes are invalid', async t => {
{
// Oh no, attribute 0 is set twice
vertexState.vertexBuffers[0].attributes.push({
- format: C.VertexFormat.Float,
+ format: 'float' as const,
offset: 0,
shaderLocation: 0,
});
@@ -516,15 +517,15 @@ g.test('identical duplicate attributes are invalid', async t => {
}
});
-g.test('we cannot set same shader location', async t => {
+g.test('we_cannot_set_same_shader_location').fn(async t => {
{
const vertexState = {
vertexBuffers: [
{
arrayStride: 0,
attributes: [
- { format: C.VertexFormat.Float, offset: 0, shaderLocation: 0 },
- { format: C.VertexFormat.Float, offset: SIZEOF_FLOAT, shaderLocation: 1 },
+ { format: 'float' as const, offset: 0, shaderLocation: 0 },
+ { format: 'float' as const, offset: SIZEOF_FLOAT, shaderLocation: 1 },
],
},
],
@@ -578,13 +579,13 @@ g.test('we cannot set same shader location', async t => {
}
});
-g.test('check out of bounds condition on attribute shader location', async t => {
+g.test('check_out_of_bounds_condition_on_attribute_shader_location').fn(async t => {
const vertexState = {
vertexBuffers: [
{
arrayStride: 0,
attributes: [
- { format: C.VertexFormat.Float, offset: 0, shaderLocation: MAX_VERTEX_ATTRIBUTES - 1 },
+ { format: 'float' as const, offset: 0, shaderLocation: MAX_VERTEX_ATTRIBUTES - 1 },
],
},
],
@@ -605,14 +606,14 @@ g.test('check out of bounds condition on attribute shader location', async t =>
}
});
-g.test('check attribute offset out of bounds', async t => {
+g.test('check_attribute_offset_out_of_bounds').fn(async t => {
const vertexState = {
vertexBuffers: [
{
arrayStride: 0,
attributes: [
{
- format: C.VertexFormat.Float2,
+ format: 'float2' as const,
offset: MAX_VERTEX_BUFFER_END - 2 * SIZEOF_FLOAT,
shaderLocation: 0,
},
@@ -642,12 +643,14 @@ g.test('check attribute offset out of bounds', async t => {
}
});
-g.test('check multiple of 4 bytes constraint on offset', async t => {
+g.test('check_multiple_of_4_bytes_constraint_on_offset').fn(async t => {
const vertexState = {
vertexBuffers: [
{
arrayStride: 0,
- attributes: [{ format: C.VertexFormat.Float, offset: SIZEOF_FLOAT, shaderLocation: 0 }],
+ attributes: [
+ { format: 'float' as GPUVertexFormat, offset: SIZEOF_FLOAT, shaderLocation: 0 },
+ ],
},
],
};
@@ -659,7 +662,7 @@ g.test('check multiple of 4 bytes constraint on offset', async t => {
{
// Test offset of 2 bytes with uchar2 format
vertexState.vertexBuffers[0].attributes[0].offset = 2;
- vertexState.vertexBuffers[0].attributes[0].format = C.VertexFormat.Uchar2;
+ vertexState.vertexBuffers[0].attributes[0].format = 'uchar2';
const descriptor = t.getDescriptor(vertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
t.expectValidationError(() => {
t.device.createRenderPipeline(descriptor);
@@ -668,7 +671,7 @@ g.test('check multiple of 4 bytes constraint on offset', async t => {
{
// Test offset of 2 bytes with float format
vertexState.vertexBuffers[0].attributes[0].offset = 2;
- vertexState.vertexBuffers[0].attributes[0].format = C.VertexFormat.Float;
+ vertexState.vertexBuffers[0].attributes[0].format = 'float';
const descriptor = t.getDescriptor(vertexState, VERTEX_SHADER_CODE_WITH_NO_INPUT);
t.expectValidationError(() => {
@@ -677,7 +680,7 @@ g.test('check multiple of 4 bytes constraint on offset', async t => {
}
});
-g.test('check attribute offset overflow', async t => {
+g.test('check_attribute_offset_overflow').fn(async t => {
const vertexState: GPUVertexStateDescriptor = {
vertexBuffers: [
{
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/capability_info.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/capability_info.ts
index 47a1ad806f2..2f17bff08f0 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/capability_info.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/capability_info.ts
@@ -1,11 +1,26 @@
import * as C from '../common/constants.js';
+function keysOf<T extends string>(obj: { [k in T]: unknown }): readonly T[] {
+ return (Object.keys(obj) as unknown[]) as T[];
+}
+
+function numericKeysOf<T>(obj: object): readonly T[] {
+ return (Object.keys(obj).map(n => Number(n)) as unknown[]) as T[];
+}
+
// Textures
export const kTextureFormatInfo: {
- [k in GPUTextureFormat]: {
- renderable: boolean;
- color: boolean;
+ readonly [k in GPUTextureFormat]: {
+ readonly renderable: boolean;
+ readonly color: boolean;
+ readonly depth: boolean;
+ readonly stencil: boolean;
+ readonly storage: boolean;
+ readonly copyable: boolean;
+ readonly bytesPerBlock?: number;
+ readonly blockWidth?: number;
+ readonly blockHeight?: number;
// Add fields as needed
};
} = /* prettier-ignore */ {
@@ -13,99 +28,230 @@ export const kTextureFormatInfo: {
// (Note: this list should always match the one in the spec.)
// 8-bit formats
- 'r8unorm': { renderable: true, color: true },
- 'r8snorm': { renderable: false, color: true },
- 'r8uint': { renderable: true, color: true },
- 'r8sint': { renderable: true, color: true },
+ 'r8unorm': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 1, blockWidth: 1, blockHeight: 1 },
+ 'r8snorm': { renderable: false, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 1, blockWidth: 1, blockHeight: 1 },
+ 'r8uint': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 1, blockWidth: 1, blockHeight: 1 },
+ 'r8sint': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 1, blockWidth: 1, blockHeight: 1 },
// 16-bit formats
- 'r16uint': { renderable: true, color: true },
- 'r16sint': { renderable: true, color: true },
- 'r16float': { renderable: true, color: true },
- 'rg8unorm': { renderable: true, color: true },
- 'rg8snorm': { renderable: false, color: true },
- 'rg8uint': { renderable: true, color: true },
- 'rg8sint': { renderable: true, color: true },
+ 'r16uint': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1 },
+ 'r16sint': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1 },
+ 'r16float': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1 },
+ 'rg8unorm': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1 },
+ 'rg8snorm': { renderable: false, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1 },
+ 'rg8uint': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1 },
+ 'rg8sint': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 2, blockWidth: 1, blockHeight: 1 },
// 32-bit formats
- 'r32uint': { renderable: true, color: true },
- 'r32sint': { renderable: true, color: true },
- 'r32float': { renderable: true, color: true },
- 'rg16uint': { renderable: true, color: true },
- 'rg16sint': { renderable: true, color: true },
- 'rg16float': { renderable: true, color: true },
- 'rgba8unorm': { renderable: true, color: true },
- 'rgba8unorm-srgb': { renderable: true, color: true },
- 'rgba8snorm': { renderable: false, color: true },
- 'rgba8uint': { renderable: true, color: true },
- 'rgba8sint': { renderable: true, color: true },
- 'bgra8unorm': { renderable: true, color: true },
- 'bgra8unorm-srgb': { renderable: true, color: true },
+ 'r32uint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'r32sint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'r32float': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'rg16uint': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'rg16sint': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'rg16float': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'rgba8unorm': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'rgba8unorm-srgb': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'rgba8snorm': { renderable: false, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'rgba8uint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'rgba8sint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'bgra8unorm': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'bgra8unorm-srgb': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
// Packed 32-bit formats
- 'rgb10a2unorm': { renderable: true, color: true },
- 'rg11b10float': { renderable: false, color: true },
+ 'rgb10a2unorm': { renderable: true, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'rg11b10float': { renderable: false, color: true, depth: false, stencil: false, storage: false, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
// 64-bit formats
- 'rg32uint': { renderable: true, color: true },
- 'rg32sint': { renderable: true, color: true },
- 'rg32float': { renderable: true, color: true },
- 'rgba16uint': { renderable: true, color: true },
- 'rgba16sint': { renderable: true, color: true },
- 'rgba16float': { renderable: true, color: true },
+ 'rg32uint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1 },
+ 'rg32sint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1 },
+ 'rg32float': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1 },
+ 'rgba16uint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1 },
+ 'rgba16sint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1 },
+ 'rgba16float': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 8, blockWidth: 1, blockHeight: 1 },
// 128-bit formats
- 'rgba32uint': { renderable: true, color: true },
- 'rgba32sint': { renderable: true, color: true },
- 'rgba32float': { renderable: true, color: true },
+ 'rgba32uint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 16, blockWidth: 1, blockHeight: 1 },
+ 'rgba32sint': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 16, blockWidth: 1, blockHeight: 1 },
+ 'rgba32float': { renderable: true, color: true, depth: false, stencil: false, storage: true, copyable: true, bytesPerBlock: 16, blockWidth: 1, blockHeight: 1 },
// Depth/stencil formats
- 'depth32float': { renderable: true, color: false },
- 'depth24plus': { renderable: true, color: false },
- 'depth24plus-stencil8': { renderable: true, color: false },
+ 'depth32float': { renderable: true, color: false, depth: true, stencil: false, storage: false, copyable: true, bytesPerBlock: 4, blockWidth: 1, blockHeight: 1 },
+ 'depth24plus': { renderable: true, color: false, depth: true, stencil: false, storage: false, copyable: false, },
+ 'depth24plus-stencil8': { renderable: true, color: false, depth: true, stencil: true, storage: false, copyable: false, },
};
-export const kTextureFormats = Object.keys(kTextureFormatInfo) as GPUTextureFormat[];
+export const kTextureFormats = keysOf(kTextureFormatInfo);
-// Bindings
+export const kTextureDimensionInfo: {
+ readonly [k in GPUTextureDimension]: {
+ // Add fields as needed
+ };
+} = /* prettier-ignore */ {
+ '1d': {},
+ '2d': {},
+ '3d': {},
+};
+export const kTextureDimensions = keysOf(kTextureDimensionInfo);
-export const kMaxBindingsPerBindGroup = 16;
+export const kTextureAspectInfo: {
+ readonly [k in GPUTextureAspect]: {
+ // Add fields as needed
+ };
+} = /* prettier-ignore */ {
+ 'all': {},
+ 'depth-only': {},
+ 'stencil-only': {},
+};
+export const kTextureAspects = keysOf(kTextureAspectInfo);
+
+export const kTextureUsageInfo: {
+ readonly [k in C.TextureUsage]: {};
+} = {
+ [C.TextureUsage.CopySrc]: {},
+ [C.TextureUsage.CopyDst]: {},
+ [C.TextureUsage.Sampled]: {},
+ [C.TextureUsage.Storage]: {},
+ [C.TextureUsage.OutputAttachment]: {},
+};
+export const kTextureUsages = numericKeysOf<C.TextureUsage>(kTextureUsageInfo);
+
+// Typedefs for bindings
-export type PerStageBindingLimitType =
- | 'uniform-buffer'
- | 'storage-buffer'
+export type PerStageBindingLimitClass =
+ | 'uniformBuf'
+ | 'storageBuf'
| 'sampler'
+ | 'sampledTex'
+ | 'storageTex';
+export type PerPipelineBindingLimitClass = PerStageBindingLimitClass;
+
+type ValidBindableResource =
+ | 'uniformBuf'
+ | 'storageBuf'
+ | 'plainSamp'
+ | 'compareSamp'
+ | 'sampledTex'
+ | 'storageTex';
+type ErrorBindableResource = 'errorBuf' | 'errorSamp' | 'errorTex';
+export type BindableResource = ValidBindableResource | ErrorBindableResource;
+
+type BufferBindingType = 'uniform-buffer' | 'storage-buffer' | 'readonly-storage-buffer';
+type SamplerBindingType = 'sampler' | 'comparison-sampler';
+type TextureBindingType =
| 'sampled-texture'
- | 'storage-texture';
+ | 'writeonly-storage-texture'
+ | 'readonly-storage-texture';
+
+// Bindings
+
+export const kMaxBindingsPerBindGroup = 16;
+
export const kPerStageBindingLimits: {
- [k in PerStageBindingLimitType]: number;
+ readonly [k in PerStageBindingLimitClass]: {
+ readonly class: k;
+ readonly max: number;
+ // Add fields as needed
+ };
} = /* prettier-ignore */ {
- 'uniform-buffer': 12,
- 'storage-buffer': 4,
- 'sampler': 16,
- 'sampled-texture': 16,
- 'storage-texture': 4,
+ 'uniformBuf': { class: 'uniformBuf', max: 12, },
+ 'storageBuf': { class: 'storageBuf', max: 4, },
+ 'sampler': { class: 'sampler', max: 16, },
+ 'sampledTex': { class: 'sampledTex', max: 16, },
+ 'storageTex': { class: 'storageTex', max: 4, },
};
-const kStagesAll = C.ShaderStage.Vertex | C.ShaderStage.Fragment | C.ShaderStage.Compute;
-const kStagesCompute = C.ShaderStage.Compute;
-export const kBindingTypeInfo: {
- [k in GPUBindingType]: {
- type: 'buffer' | 'texture' | 'sampler';
- validStages: GPUShaderStageFlags;
- perStageLimitType: PerStageBindingLimitType;
- maxDynamicCount: number;
+export const kPerPipelineBindingLimits: {
+ readonly [k in PerPipelineBindingLimitClass]: {
+ readonly class: k;
+ readonly maxDynamic: number;
// Add fields as needed
};
- // TODO: maxDynamicCount should be kPerPipelineLayoutBindingLimits instead
} = /* prettier-ignore */ {
- 'uniform-buffer': { type: 'buffer', validStages: kStagesAll, perStageLimitType: 'uniform-buffer', maxDynamicCount: 8 },
- 'storage-buffer': { type: 'buffer', validStages: kStagesCompute, perStageLimitType: 'storage-buffer', maxDynamicCount: 4 },
- 'readonly-storage-buffer': { type: 'buffer', validStages: kStagesAll, perStageLimitType: 'storage-buffer', maxDynamicCount: 4 },
- 'sampler': { type: 'sampler', validStages: kStagesAll, perStageLimitType: 'sampler', maxDynamicCount: 0 },
- 'comparison-sampler': { type: 'sampler', validStages: kStagesAll, perStageLimitType: 'sampler', maxDynamicCount: 0 },
- 'sampled-texture': { type: 'texture', validStages: kStagesAll, perStageLimitType: 'sampled-texture', maxDynamicCount: 0 },
- 'writeonly-storage-texture': { type: 'texture', validStages: kStagesCompute, perStageLimitType: 'storage-texture', maxDynamicCount: 0 },
- 'readonly-storage-texture': { type: 'texture', validStages: kStagesAll, perStageLimitType: 'storage-texture', maxDynamicCount: 0 },
+ 'uniformBuf': { class: 'uniformBuf', maxDynamic: 8, },
+ 'storageBuf': { class: 'storageBuf', maxDynamic: 4, },
+ 'sampler': { class: 'sampler', maxDynamic: 0, },
+ 'sampledTex': { class: 'sampledTex', maxDynamic: 0, },
+ 'storageTex': { class: 'storageTex', maxDynamic: 0, },
+};
+
+const kBindableResource: {
+ readonly [k in BindableResource]: {};
+} = /* prettier-ignore */ {
+ uniformBuf: {}, storageBuf: {}, plainSamp: {}, compareSamp: {}, sampledTex: {}, storageTex: {},
+ errorBuf: {}, errorSamp: {}, errorTex: {},
+};
+export const kBindableResources = keysOf(kBindableResource);
+
+interface BindingKindInfo {
+ readonly resource: ValidBindableResource;
+ readonly perStageLimitClass: typeof kPerStageBindingLimits[PerStageBindingLimitClass];
+ readonly perPipelineLimitClass: typeof kPerPipelineBindingLimits[PerPipelineBindingLimitClass];
+ // Add fields as needed
+}
+
+const kBindingKind: {
+ readonly [k in ValidBindableResource]: BindingKindInfo;
+} = /* prettier-ignore */ {
+ uniformBuf: { resource: 'uniformBuf', perStageLimitClass: kPerStageBindingLimits.uniformBuf, perPipelineLimitClass: kPerPipelineBindingLimits.uniformBuf, },
+ storageBuf: { resource: 'storageBuf', perStageLimitClass: kPerStageBindingLimits.storageBuf, perPipelineLimitClass: kPerPipelineBindingLimits.storageBuf, },
+ plainSamp: { resource: 'plainSamp', perStageLimitClass: kPerStageBindingLimits.sampler, perPipelineLimitClass: kPerPipelineBindingLimits.sampler, },
+ compareSamp: { resource: 'compareSamp', perStageLimitClass: kPerStageBindingLimits.sampler, perPipelineLimitClass: kPerPipelineBindingLimits.sampler, },
+ sampledTex: { resource: 'sampledTex', perStageLimitClass: kPerStageBindingLimits.sampledTex, perPipelineLimitClass: kPerPipelineBindingLimits.sampledTex, },
+ storageTex: { resource: 'storageTex', perStageLimitClass: kPerStageBindingLimits.storageTex, perPipelineLimitClass: kPerPipelineBindingLimits.storageTex, },
+};
+
+// Binding type info
+
+interface BindingTypeInfo extends BindingKindInfo {
+ readonly validStages: GPUShaderStageFlags;
+ // Add fields as needed
+}
+const kValidStagesAll = {
+ validStages: C.ShaderStage.Vertex | C.ShaderStage.Fragment | C.ShaderStage.Compute,
+};
+const kValidStagesStorageWrite = { validStages: C.ShaderStage.Fragment | C.ShaderStage.Compute };
+
+export const kBufferBindingTypeInfo: {
+ readonly [k in BufferBindingType]: {
+ readonly usage: C.BufferUsage;
+ // Add fields as needed
+ } & BindingTypeInfo;
+} = /* prettier-ignore */ {
+ 'uniform-buffer': { usage: C.BufferUsage.Uniform, ...kBindingKind.uniformBuf, ...kValidStagesAll, },
+ 'storage-buffer': { usage: C.BufferUsage.Storage, ...kBindingKind.storageBuf, ...kValidStagesStorageWrite, },
+ 'readonly-storage-buffer': { usage: C.BufferUsage.Storage, ...kBindingKind.storageBuf, ...kValidStagesAll, },
+};
+export const kBufferBindingTypes = keysOf(kBufferBindingTypeInfo);
+
+export const kSamplerBindingTypeInfo: {
+ readonly [k in SamplerBindingType]: {
+ // Add fields as needed
+ } & BindingTypeInfo;
+} = /* prettier-ignore */ {
+ 'sampler': { ...kBindingKind.plainSamp, ...kValidStagesAll, },
+ 'comparison-sampler': { ...kBindingKind.compareSamp, ...kValidStagesAll, },
+};
+export const kSamplerBindingTypes = keysOf(kSamplerBindingTypeInfo);
+
+export const kTextureBindingTypeInfo: {
+ readonly [k in TextureBindingType]: {
+ readonly usage: C.TextureUsage;
+ // Add fields as needed
+ } & BindingTypeInfo;
+} = /* prettier-ignore */ {
+ 'sampled-texture': { usage: C.TextureUsage.Sampled, ...kBindingKind.sampledTex, ...kValidStagesAll, },
+ 'writeonly-storage-texture': { usage: C.TextureUsage.Storage, ...kBindingKind.storageTex, ...kValidStagesStorageWrite, },
+ 'readonly-storage-texture': { usage: C.TextureUsage.Storage, ...kBindingKind.storageTex, ...kValidStagesAll, },
+};
+export const kTextureBindingTypes = keysOf(kTextureBindingTypeInfo);
+
+// All binding types (merged from above)
+
+export const kBindingTypeInfo: {
+ readonly [k in GPUBindingType]: BindingTypeInfo;
+} = {
+ ...kBufferBindingTypeInfo,
+ ...kSamplerBindingTypeInfo,
+ ...kTextureBindingTypeInfo,
};
-export const kBindingTypes = Object.keys(kBindingTypeInfo) as GPUBindingType[];
+export const kBindingTypes = keysOf(kBindingTypeInfo);
-export const kShaderStages: GPUShaderStageFlags[] = [
+export const kShaderStages: readonly GPUShaderStageFlags[] = [
C.ShaderStage.Vertex,
C.ShaderStage.Fragment,
C.ShaderStage.Compute,
];
-export const kShaderStageCombinations: GPUShaderStageFlags[] = [0, 1, 2, 3, 4, 5, 6, 7];
+export const kShaderStageCombinations: readonly GPUShaderStageFlags[] = [0, 1, 2, 3, 4, 5, 6, 7];
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/examples.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/examples.spec.ts
index 7cbe5b76943..024817fde8e 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/examples.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/examples.spec.ts
@@ -4,7 +4,7 @@ Examples of writing CTS tests with various features.
Start here when looking for examples of basic framework usage.
`;
-import { TestGroup } from '../common/framework/test_group.js';
+import { makeTestGroup } from '../common/framework/test_group.js';
import { GPUTest } from './gpu_test.js';
@@ -18,12 +18,13 @@ import { GPUTest } from './gpu_test.js';
// - ?q=webgpu:examples:basic/
// - ?q=webgpu:examples:
-export const g = new TestGroup(GPUTest);
+export const g = makeTestGroup(GPUTest);
// Note: spaces in test names are replaced with underscores: webgpu:examples:test_name=
-g.test('test name', t => {});
+/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
+g.test('test_name').fn(t => {});
-g.test('basic', t => {
+g.test('basic').fn(t => {
t.expect(true);
t.expect(true, 'true should be true');
@@ -39,7 +40,7 @@ g.test('basic', t => {
);
});
-g.test('basic/async', async t => {
+g.test('basic,async').fn(async t => {
// shouldReject must be awaited to ensure it can wait for the promise before the test ends.
t.shouldReject(
// The expected '.name' of the thrown error.
@@ -68,22 +69,24 @@ g.test('basic/async', async t => {
//
// - webgpu:examples:basic/params={"x":2,"y":4} runs with t.params = {x: 2, y: 5, _result: 6}.
// - webgpu:examples:basic/params={"x":-10,"y":18} runs with t.params = {x: -10, y: 18, _result: 8}.
-g.test('basic/params', t => {
- t.expect(t.params.x + t.params.y === t.params._result);
-}).params([
- { x: 2, y: 4, _result: 6 }, //
- { x: -10, y: 18, _result: 8 },
-]);
+g.test('basic,params')
+ .params([
+ { x: 2, y: 4, _result: 6 }, //
+ { x: -10, y: 18, _result: 8 },
+ ])
+ .fn(t => {
+ t.expect(t.params.x + t.params.y === t.params._result);
+ });
// (note the blank comment above to enforce newlines on autoformat)
-g.test('gpu/async', async t => {
+g.test('gpu,async').fn(async t => {
const fence = t.queue.createFence();
t.queue.signal(fence, 2);
await fence.onCompletion(1);
t.expect(fence.getCompletedValue() === 2);
});
-g.test('gpu/buffers', async t => {
+g.test('gpu,buffers').fn(async t => {
const data = new Uint32Array([0, 1234, 0]);
const [src, map] = t.device.createBufferMapped({
size: 12,
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/gpu_test.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/gpu_test.ts
index daa00c234f9..4b4ec7ab35c 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/gpu_test.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/gpu_test.ts
@@ -1,45 +1,37 @@
import { Fixture } from '../common/framework/fixture.js';
import { compileGLSL, initGLSL } from '../common/framework/glsl.js';
-import { getGPU } from '../common/framework/gpu/implementation.js';
-import { assert, unreachable } from '../common/framework/util/util.js';
+import { DevicePool, TestOOMedShouldAttemptGC } from '../common/framework/gpu/device_pool.js';
+import { attemptGarbageCollection } from '../common/framework/util/collect_garbage.js';
+import { assert } from '../common/framework/util/util.js';
-type ShaderStage = import('@webgpu/glslang/dist/web-devel/glslang').ShaderStage;
-
-class DevicePool {
- device: GPUDevice | undefined = undefined;
- state: 'free' | 'acquired' | 'uninitialized' | 'failed' = 'uninitialized';
-
- private async initialize(): Promise<void> {
- try {
- const gpu = getGPU();
- const adapter = await gpu.requestAdapter();
- this.device = await adapter.requestDevice();
- } catch (ex) {
- this.state = 'failed';
- throw ex;
- }
- }
-
- async acquire(): Promise<GPUDevice> {
- assert(this.state !== 'acquired', 'Device was in use');
- assert(this.state !== 'failed', 'Failed to initialize WebGPU device');
-
- const state = this.state;
- this.state = 'acquired';
- if (state === 'uninitialized') {
- await this.initialize();
- }
+import {
+ fillTextureDataWithTexelValue,
+ getTextureCopyLayout,
+ LayoutOptions as TextureLayoutOptions,
+} from './util/texture/layout.js';
+import { PerTexelComponent, getTexelDataRepresentation } from './util/texture/texelData.js';
- assert(!!this.device);
- return this.device;
- }
+type ShaderStage = import('@webgpu/glslang/dist/web-devel/glslang').ShaderStage;
- release(device: GPUDevice): void {
- assert(this.state === 'acquired');
- assert(device === this.device, 'Released device was the wrong device');
- this.state = 'free';
- }
-}
+type TypedArrayBufferView =
+ | Uint8Array
+ | Uint16Array
+ | Uint32Array
+ | Int8Array
+ | Int16Array
+ | Int32Array
+ | Float32Array
+ | Float64Array;
+
+type TypedArrayBufferViewConstructor =
+ | Uint8ArrayConstructor
+ | Uint16ArrayConstructor
+ | Uint32ArrayConstructor
+ | Int8ArrayConstructor
+ | Int16ArrayConstructor
+ | Int32ArrayConstructor
+ | Float32ArrayConstructor
+ | Float64ArrayConstructor;
const devicePool = new DevicePool();
@@ -64,39 +56,33 @@ export class GPUTest extends Fixture {
const device = await devicePool.acquire();
const queue = device.defaultQueue;
this.objects = { device, queue };
-
- try {
- await device.popErrorScope();
- unreachable('There was an error scope on the stack at the beginning of the test');
- } catch (ex) {}
-
- device.pushErrorScope('out-of-memory');
- device.pushErrorScope('validation');
-
- this.initialized = true;
}
+ // Note: finalize is called even if init was unsuccessful.
async finalize(): Promise<void> {
- // Note: finalize is called even if init was unsuccessful.
await super.finalize();
- if (this.initialized) {
- const gpuValidationError = await this.device.popErrorScope();
- if (gpuValidationError !== null) {
- assert(gpuValidationError instanceof GPUValidationError);
- this.fail(`Unexpected validation error occurred: ${gpuValidationError.message}`);
+ if (this.objects) {
+ let threw: undefined | Error;
+ {
+ const objects = this.objects;
+ this.objects = undefined;
+ try {
+ await devicePool.release(objects.device);
+ } catch (ex) {
+ threw = ex;
+ }
}
+ // The GPUDevice and GPUQueue should now have no outstanding references.
- const gpuOutOfMemoryError = await this.device.popErrorScope();
- if (gpuOutOfMemoryError !== null) {
- assert(gpuOutOfMemoryError instanceof GPUOutOfMemoryError);
- this.fail('Unexpected out-of-memory error occurred');
+ if (threw) {
+ if (threw instanceof TestOOMedShouldAttemptGC) {
+ // Try to clean up, in case there are stray GPU resources in need of collection.
+ await attemptGarbageCollection();
+ }
+ throw threw;
}
}
-
- if (this.objects) {
- devicePool.release(this.objects.device);
- }
}
makeShaderModule(stage: ShaderStage, code: { glsl: string } | { wgsl: string }): GPUShaderModule {
@@ -109,14 +95,14 @@ export class GPUTest extends Fixture {
}
}
- createCopyForMapRead(src: GPUBuffer, size: number): GPUBuffer {
+ createCopyForMapRead(src: GPUBuffer, start: number, size: number): GPUBuffer {
const dst = this.device.createBuffer({
size,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
});
const c = this.device.createCommandEncoder();
- c.copyBufferToBuffer(src, 0, dst, 0, size);
+ c.copyBufferToBuffer(src, start, dst, 0, size);
this.queue.submit([c.finish()]);
@@ -125,16 +111,20 @@ export class GPUTest extends Fixture {
// TODO: add an expectContents for textures, which logs data: uris on failure
- expectContents(src: GPUBuffer, expected: ArrayBufferView): void {
- const exp = new Uint8Array(expected.buffer, expected.byteOffset, expected.byteLength);
- const dst = this.createCopyForMapRead(src, expected.buffer.byteLength);
+ expectContents(src: GPUBuffer, expected: TypedArrayBufferView): void {
+ this.expectSubContents(src, 0, expected);
+ }
+
+ expectSubContents(src: GPUBuffer, start: number, expected: TypedArrayBufferView): void {
+ const dst = this.createCopyForMapRead(src, start, expected.buffer.byteLength);
this.eventualAsyncExpectation(async niceStack => {
- const actual = new Uint8Array(await dst.mapReadAsync());
- const check = this.checkBuffer(actual, exp);
+ const constructor = expected.constructor as TypedArrayBufferViewConstructor;
+ const actual = new constructor(await dst.mapReadAsync());
+ const check = this.checkBuffer(actual, expected);
if (check !== undefined) {
niceStack.message = check;
- this.rec.fail(niceStack);
+ this.rec.expectationFailed(niceStack);
}
dst.destroy();
});
@@ -143,27 +133,42 @@ export class GPUTest extends Fixture {
expectBuffer(actual: Uint8Array, exp: Uint8Array): void {
const check = this.checkBuffer(actual, exp);
if (check !== undefined) {
- this.rec.fail(new Error(check));
+ this.rec.expectationFailed(new Error(check));
}
}
- checkBuffer(actual: Uint8Array, exp: Uint8Array): string | undefined {
+ checkBuffer(
+ actual: TypedArrayBufferView,
+ exp: TypedArrayBufferView,
+ tolerance: number | ((i: number) => number) = 0
+ ): string | undefined {
+ assert(actual.constructor === exp.constructor);
+
const size = exp.byteLength;
if (actual.byteLength !== size) {
return 'size mismatch';
}
- const lines = [];
- let failedPixels = 0;
+ const failedByteIndices: string[] = [];
+ const failedByteExpectedValues: string[] = [];
+ const failedByteActualValues: string[] = [];
for (let i = 0; i < size; ++i) {
- if (actual[i] !== exp[i]) {
- if (failedPixels > 4) {
- lines.push('... and more');
+ const tol = typeof tolerance === 'function' ? tolerance(i) : tolerance;
+ if (Math.abs(actual[i] - exp[i]) > tol) {
+ if (failedByteIndices.length >= 4) {
+ failedByteIndices.push('...');
+ failedByteExpectedValues.push('...');
+ failedByteActualValues.push('...');
break;
}
- failedPixels++;
- lines.push(`at [${i}], expected ${exp[i]}, got ${actual[i]}`);
+ failedByteIndices.push(i.toString());
+ failedByteExpectedValues.push(exp[i].toString());
+ failedByteActualValues.push(actual[i].toString());
}
}
+ const summary = `at [${failedByteIndices.join(', ')}], \
+expected [${failedByteExpectedValues.join(', ')}], \
+got [${failedByteActualValues.join(', ')}]`;
+ const lines = [summary];
// TODO: Could make a more convenient message, which could look like e.g.:
//
@@ -180,19 +185,99 @@ export class GPUTest extends Fixture {
// Or, maybe these diffs aren't actually very useful (given we have the prints just above here),
// and we should remove them. More important will be logging of texture data in a visual format.
- if (size <= 256 && failedPixels > 0) {
- const expHex = Array.from(exp)
+ if (size <= 256 && failedByteIndices.length > 0) {
+ const expHex = Array.from(new Uint8Array(exp.buffer, exp.byteOffset, exp.byteLength))
.map(x => x.toString(16).padStart(2, '0'))
.join('');
- const actHex = Array.from(actual)
+ const actHex = Array.from(new Uint8Array(actual.buffer, actual.byteOffset, actual.byteLength))
.map(x => x.toString(16).padStart(2, '0'))
.join('');
- lines.push('EXPECT: ' + expHex);
- lines.push('ACTUAL: ' + actHex);
+ lines.push('EXPECT:\t ' + exp.join(' '));
+ lines.push('\t0x' + expHex);
+ lines.push('ACTUAL:\t ' + actual.join(' '));
+ lines.push('\t0x' + actHex);
}
- if (failedPixels) {
+ if (failedByteIndices.length) {
return lines.join('\n');
}
return undefined;
}
+
+ expectSingleColor(
+ src: GPUTexture,
+ format: GPUTextureFormat,
+ {
+ size,
+ exp,
+ dimension = '2d',
+ slice = 0,
+ layout,
+ }: {
+ size: [number, number, number];
+ exp: PerTexelComponent<number>;
+ dimension?: GPUTextureDimension;
+ slice?: number;
+ layout?: TextureLayoutOptions;
+ }
+ ): void {
+ const { byteLength, bytesPerRow, rowsPerImage, mipSize } = getTextureCopyLayout(
+ format,
+ dimension,
+ size,
+ layout
+ );
+ const expectedTexelData = getTexelDataRepresentation(format).getBytes(exp);
+
+ const buffer = this.device.createBuffer({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
+ });
+
+ const commandEncoder = this.device.createCommandEncoder();
+ commandEncoder.copyTextureToBuffer(
+ { texture: src, mipLevel: layout?.mipLevel, arrayLayer: slice },
+ { buffer, bytesPerRow, rowsPerImage },
+ mipSize
+ );
+ this.queue.submit([commandEncoder.finish()]);
+ const arrayBuffer = new ArrayBuffer(byteLength);
+ fillTextureDataWithTexelValue(expectedTexelData, format, dimension, arrayBuffer, size, layout);
+ this.expectContents(buffer, new Uint8Array(arrayBuffer));
+ }
+
+ expectGPUError<R>(filter: GPUErrorFilter, fn: () => R): R {
+ this.device.pushErrorScope(filter);
+ const returnValue = fn();
+ const promise = this.device.popErrorScope();
+
+ this.eventualAsyncExpectation(async niceStack => {
+ const error = await promise;
+
+ let failed = false;
+ switch (filter) {
+ case 'none':
+ failed = error !== null;
+ break;
+ case 'out-of-memory':
+ failed = !(error instanceof GPUOutOfMemoryError);
+ break;
+ case 'validation':
+ failed = !(error instanceof GPUValidationError);
+ break;
+ }
+
+ if (failed) {
+ niceStack.message = `Expected ${filter} error`;
+ this.rec.expectationFailed(niceStack);
+ } else {
+ niceStack.message = `Captured ${filter} error`;
+ if (error instanceof GPUValidationError) {
+ niceStack.message += ` - ${error.message}`;
+ }
+ this.rec.debug(niceStack);
+ }
+ });
+
+ return returnValue;
+ }
}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/idl/constants/flags.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/idl/constants/flags.spec.ts
new file mode 100644
index 00000000000..80cc8125a6e
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/idl/constants/flags.spec.ts
@@ -0,0 +1,55 @@
+export const description = `
+Test the values of flags interfaces (e.g. GPUTextureUsage).
+`;
+
+import { BufferUsage, TextureUsage, ColorWrite, ShaderStage } from '../../../common/constants.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { IDLTest } from '../idl_test.js';
+
+export const g = makeTestGroup(IDLTest);
+
+g.test('BufferUsage').fn(t => {
+ const expected = {
+ MAP_READ: BufferUsage.MapRead,
+ MAP_WRITE: BufferUsage.MapWrite,
+ COPY_SRC: BufferUsage.CopySrc,
+ COPY_DST: BufferUsage.CopyDst,
+ INDEX: BufferUsage.Index,
+ VERTEX: BufferUsage.Vertex,
+ UNIFORM: BufferUsage.Uniform,
+ STORAGE: BufferUsage.Storage,
+ INDIRECT: BufferUsage.Indirect,
+ };
+ t.assertMembers(GPUBufferUsage, expected);
+});
+
+g.test('TextureUsage').fn(t => {
+ const expected = {
+ COPY_SRC: TextureUsage.CopySrc,
+ COPY_DST: TextureUsage.CopyDst,
+ SAMPLED: TextureUsage.Sampled,
+ STORAGE: TextureUsage.Storage,
+ OUTPUT_ATTACHMENT: TextureUsage.OutputAttachment,
+ };
+ t.assertMembers(GPUTextureUsage, expected);
+});
+
+g.test('ColorWrite').fn(t => {
+ const expected = {
+ RED: ColorWrite.Red,
+ GREEN: ColorWrite.Green,
+ BLUE: ColorWrite.Blue,
+ ALPHA: ColorWrite.Alpha,
+ ALL: ColorWrite.All,
+ };
+ t.assertMembers(GPUColorWrite, expected);
+});
+
+g.test('ShaderStage').fn(t => {
+ const expected = {
+ VERTEX: ShaderStage.Vertex,
+ FRAGMENT: ShaderStage.Fragment,
+ COMPUTE: ShaderStage.Compute,
+ };
+ t.assertMembers(GPUShaderStage, expected);
+});
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/idl/idl_test.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/idl/idl_test.ts
new file mode 100644
index 00000000000..5eb9a61172d
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/idl/idl_test.ts
@@ -0,0 +1,27 @@
+import { Fixture } from '../../common/framework/fixture.js';
+import { assert } from '../../common/framework/util/util.js';
+
+interface UnknownObject {
+ [k: string]: unknown;
+}
+
+export class IDLTest extends Fixture {
+ /**
+ * Asserts that an IDL interface has the expected members.
+ */
+ // TODO: exp should allow sentinel markers for unnameable values, such as methods and attributes
+ // TODO: handle extensions
+ // TODO: check prototype chains (maybe as separate method)
+ assertMembers(act: UnknownObject, exp: UnknownObject) {
+ const expKeys = Object.keys(exp);
+ for (const k of expKeys) {
+ assert(k in act, () => `Expected key ${k} missing`);
+ assert(act[k] === exp[k], () => `Value of [${k}] was ${act[k]}, expected ${exp[k]}`);
+ }
+ const actKeys = Object.keys(act);
+ assert(
+ actKeys.length === expKeys.length,
+ () => `Had ${actKeys.length} keys, expected ${expKeys.length}`
+ );
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/listing.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/listing.ts
index ba26ed77bd4..2d6f4cf8ecf 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/listing.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/listing.ts
@@ -1,4 +1,4 @@
-import { TestSuiteListing } from '../common/framework/listing.js';
+import { TestSuiteListing } from '../common/framework/test_suite_listing.js';
import { makeListing } from '../common/tools/crawl.js';
export const listing: Promise<TestSuiteListing> = makeListing(__filename);
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/shader/execution/robust_access.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/shader/execution/robust_access.spec.ts
new file mode 100644
index 00000000000..9b31dcfb16a
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/shader/execution/robust_access.spec.ts
@@ -0,0 +1,368 @@
+export const description = `
+Tests to check array clamping in shaders is correctly implemented including vector / matrix indexing
+`;
+
+import { params, poptions } from '../../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
+import { assert } from '../../../common/framework/util/util.js';
+import { GPUTest } from '../../gpu_test.js';
+
+export const g = makeTestGroup(GPUTest);
+
+// Utilities that should probably live in some shared place.
+function copyArrayBuffer(src: ArrayBuffer): ArrayBuffer {
+ const dst = new ArrayBuffer(src.byteLength);
+ new Uint8Array(dst).set(new Uint8Array(src));
+ return dst;
+}
+
+const kUintMax = 4294967295;
+const kIntMax = 2147483647;
+
+// A small utility to test shaders:
+// - it wraps the source into a small harness that checks the runTest() function returns 0.
+// - it runs the shader with the testBindings set as bindgroup 0.
+//
+// The shader also has access to a uniform value that's equal to 1u to avoid constant propagation
+// in the shader compiler.
+function runShaderTest(
+ t: GPUTest,
+ stage: GPUShaderStageFlags,
+ testSource: string,
+ testBindings: GPUBindGroupEntry[]
+): void {
+ assert(stage === GPUShaderStage.COMPUTE, 'Only know how to deal with compute for now');
+
+ const [constantsBuffer, constantsInit] = t.device.createBufferMapped({
+ size: 4,
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM,
+ });
+
+ const constantsData = new Uint32Array(constantsInit);
+ constantsData[0] = 1;
+ constantsBuffer.unmap();
+
+ const resultBuffer = t.device.createBuffer({
+ size: 4,
+ usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE,
+ });
+
+ const source = `#version 450
+ layout(std140, set = 1, binding = 0) uniform Constants {
+ uint one;
+ };
+ layout(std430, set = 1, binding = 1) buffer Result {
+ uint result;
+ };
+
+ ${testSource}
+
+ void main() {
+ result = runTest();
+ }`;
+
+ const pipeline = t.device.createComputePipeline({
+ computeStage: {
+ entryPoint: 'main',
+ module: t.makeShaderModule('compute', { glsl: source }),
+ },
+ });
+
+ const group = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(1),
+ entries: [
+ { binding: 0, resource: { buffer: constantsBuffer } },
+ { binding: 1, resource: { buffer: resultBuffer } },
+ ],
+ });
+
+ const testGroup = t.device.createBindGroup({
+ layout: pipeline.getBindGroupLayout(0),
+ entries: testBindings,
+ });
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginComputePass();
+ pass.setPipeline(pipeline);
+ pass.setBindGroup(0, testGroup);
+ pass.setBindGroup(1, group);
+ pass.dispatch(1);
+ pass.endPass();
+
+ t.queue.submit([encoder.finish()]);
+
+ t.expectContents(resultBuffer, new Uint32Array([0]));
+}
+
+// The definition of base types for aggregate types, for example float, uint, etc.
+interface BaseType {
+ // The name which is also the GLSL type.
+ name: string;
+ // The size in byte in a buffer.
+ byteSize: number;
+ // The prefix when used in aggregate names, the "u" in "uvec2"
+ glslPrefix: string;
+ glslZero: string;
+ // Fill the buffer with 42s, except the regions of `size` elements starting at `zeroStart`
+ // offset from the start of the buffer, which is filled with zeroes instead.
+ fillBuffer: (data: ArrayBuffer, zeroStart: number, size: number) => void;
+}
+
+interface BaseTypeDictionary {
+ [key: string]: BaseType;
+}
+
+const baseTypes: BaseTypeDictionary = {
+ // TODO bools
+ uint: {
+ name: 'uint',
+ byteSize: 4,
+ glslPrefix: 'u',
+ glslZero: '0u',
+ fillBuffer(data: ArrayBuffer, zeroStart: number, size: number): void {
+ const typedData = new Uint32Array(data);
+ typedData.fill(42);
+ for (let i = 0; i < size / 4; i++) {
+ typedData[zeroStart / 4 + i] = 0;
+ }
+ },
+ },
+ int: {
+ name: 'int',
+ byteSize: 4,
+ glslPrefix: 'i',
+ glslZero: '0',
+ fillBuffer(data: ArrayBuffer, zeroStart: number, size: number): void {
+ const typedData = new Int32Array(data);
+ typedData.fill(42);
+ for (let i = 0; i < size / 4; i++) {
+ typedData[zeroStart / 4 + i] = 0;
+ }
+ },
+ },
+ float: {
+ name: 'float',
+ byteSize: 4,
+ glslPrefix: '',
+ glslZero: '0.0f',
+ fillBuffer(data: ArrayBuffer, zeroStart: number, size: number): void {
+ const typedData = new Float32Array(data);
+ typedData.fill(42);
+ for (let i = 0; i < size / 4; i++) {
+ typedData[zeroStart / 4 + i] = 0;
+ }
+ },
+ },
+ bool: {
+ name: 'bool',
+ byteSize: 4,
+ glslPrefix: 'b',
+ glslZero: 'false',
+ fillBuffer(data: ArrayBuffer, zeroStart: number, size: number): void {
+ const typedData = new Uint32Array(data);
+ typedData.fill(42);
+ for (let i = 0; i < size / 4; i++) {
+ typedData[zeroStart / 4 + i] = 0;
+ }
+ },
+ },
+};
+
+// The definition of aggregate types.
+interface Type {
+ // String to declare a variable named "data" of that type.
+ declaration: string;
+ // The array length, which also defines the bounds for this type.
+ length: number;
+ // The footprints in the buffer of this type, in baseTypes
+ std140Length: number;
+ std430Length: number;
+ // String to produce this type filled with zeroes.
+ zero: string;
+ baseType: BaseType;
+ isUnsizedArray?: true;
+}
+
+interface TypeDictionary {
+ [key: string]: Type;
+}
+
+const typeParams: TypeDictionary = (() => {
+ const types: TypeDictionary = {};
+ for (const baseTypeName of Object.keys(baseTypes)) {
+ const baseType = baseTypes[baseTypeName];
+
+ // Arrays
+ types[`${baseTypeName}_sizedArray`] = {
+ declaration: `${baseTypeName} data[3]`,
+ length: 3,
+ std140Length: 2 * 4 + 1,
+ std430Length: 3,
+ zero: baseType.glslZero,
+ baseType,
+ };
+ types[`${baseTypeName}_unsizedArray`] = {
+ declaration: `${baseTypeName} data[]`,
+ length: 3,
+ std140Length: 0, // Unused
+ std430Length: 3,
+ zero: baseType.glslZero,
+ baseType,
+ isUnsizedArray: true,
+ };
+
+ // Vectors
+ for (let dimension = 2; dimension <= 4; dimension++) {
+ types[`${baseTypeName}_vector${dimension}`] = {
+ declaration: `${baseType.glslPrefix}vec${dimension} data`,
+ length: dimension,
+ std140Length: dimension,
+ std430Length: dimension,
+ zero: baseType.glslZero,
+ baseType,
+ };
+ }
+ }
+
+ // Matrices, there are only float matrics in GLSL.
+ for (const transposed of [false, true]) {
+ for (let numColumns = 2; numColumns <= 4; numColumns++) {
+ for (let numRows = 2; numRows <= 4; numRows++) {
+ const majorDim = transposed ? numRows : numColumns;
+ const minorDim = transposed ? numColumns : numRows;
+
+ const std140SizePerMinorDim = 4;
+ const std430SizePerMinorDim = minorDim === 3 ? 4 : minorDim;
+
+ let typeName = `mat${numColumns}`;
+ if (numColumns !== numRows) {
+ typeName += `x${numRows}`;
+ }
+
+ types[(transposed ? 'transposed_' : '') + typeName] = {
+ declaration: (transposed ? 'layout(row_major) ' : '') + `${typeName} data`,
+ length: numColumns,
+ std140Length: std140SizePerMinorDim * (majorDim - 1) + minorDim,
+ std430Length: std430SizePerMinorDim * (majorDim - 1) + minorDim,
+ zero: `vec${numRows}(0.0f)`,
+ baseType: baseTypes['float'],
+ };
+ }
+ }
+ }
+
+ return types;
+})();
+
+g.test('bufferMemory')
+ .params(
+ params()
+ .combine(poptions('type', Object.keys(typeParams)))
+ .combine([
+ { memory: 'storage', access: 'read' },
+ { memory: 'storage', access: 'write' },
+ { memory: 'storage', access: 'atomic' },
+ { memory: 'uniform', access: 'read' },
+ ])
+ // Unsized arrays are only supported with SSBOs
+ .unless(p => typeParams[p.type].isUnsizedArray === true && p.memory !== 'storage')
+ // Atomics are only supported with integers
+ .unless(p => p.access === 'atomic' && !(typeParams[p.type].baseType.name in ['uint', 'int']))
+ )
+ .fn(async t => {
+ const type = typeParams[t.params.type];
+ const baseType = type.baseType;
+
+ const indicesToTest = [
+ // Write to the inside of the type so we can check the size computations were correct.
+ '0',
+ `${type.length} - 1`,
+
+ // Check exact bounds
+ '-1',
+ `${type.length}`,
+
+ // Check large offset
+ '-1000000',
+ '1000000',
+
+ // Check with max uint
+ `${kUintMax}`,
+ `-1 * ${kUintMax}`,
+
+ // Check with max int
+ `${kIntMax}`,
+ `-1 * ${kIntMax}`,
+ ];
+
+ let testSource = '';
+ let byteSize = 0;
+
+ // Declare the data that will be accessed to check robust access.
+ if (t.params.memory === 'uniform') {
+ testSource += `
+ layout(std140, set = 0, binding = 0) uniform TestData {
+ ${type.declaration};
+ };`;
+ byteSize = baseType.byteSize * type.std140Length;
+ } else {
+ testSource += `
+ layout(std430, set = 0, binding = 0) buffer TestData {
+ ${type.declaration};
+ };`;
+ byteSize = baseType.byteSize * type.std430Length;
+ }
+
+ // Build the test function that will do the tests.
+ testSource += `
+ uint runTest() {
+ `;
+
+ for (const indexToTest of indicesToTest) {
+ // TODO check with constants too.
+ const index = `(${indexToTest}) * one`;
+
+ if (t.params.access === 'read') {
+ testSource += `
+ if(data[${index}] != ${type.zero}) {
+ return __LINE__;
+ }`;
+ } else if (t.params.access === 'write') {
+ testSource += `data[${index}] = ${type.zero};`;
+ } else {
+ testSource += `atomicAdd(data[${index}], 1);`;
+ }
+ }
+
+ testSource += `
+ return 0;
+ }`;
+
+ // Create a buffer that contains zeroes in the allowed access area, and 42s everywhere else.
+ const [testBuffer, testInit] = t.device.createBufferMapped({
+ size: 512,
+ usage:
+ GPUBufferUsage.COPY_SRC |
+ GPUBufferUsage.UNIFORM |
+ GPUBufferUsage.STORAGE |
+ GPUBufferUsage.COPY_DST,
+ });
+ baseType.fillBuffer(testInit, 256, byteSize);
+ const testInitCopy = copyArrayBuffer(testInit);
+ testBuffer.unmap();
+
+ // Run the shader, accessing the buffer.
+ runShaderTest(t, GPUShaderStage.COMPUTE, testSource, [
+ { binding: 0, resource: { buffer: testBuffer, offset: 256, size: byteSize } },
+ ]);
+
+ // Check that content of the buffer outside of the allowed area didn't change.
+ t.expectSubContents(testBuffer, 0, new Uint8Array(testInitCopy.slice(0, 256)));
+ const dataEnd = 256 + byteSize;
+ t.expectSubContents(testBuffer, dataEnd, new Uint8Array(testInitCopy.slice(dataEnd, 512)));
+ });
+
+// TODO: also check other shader stages.
+// TODO: also check global, function local, and shared variables.
+// TODO: also check interface variables.
+// TODO: also check storage texture access.
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/util/conversion.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/util/conversion.ts
new file mode 100644
index 00000000000..3d62cdae3f5
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/util/conversion.ts
@@ -0,0 +1,71 @@
+import { assert } from '../../common/framework/util/util.js';
+
+export function floatAsNormalizedInteger(float: number, bits: number, signed: boolean): number {
+ if (signed) {
+ assert(float >= -1 && float <= 1);
+ const max = Math.pow(2, bits - 1) - 1;
+ return Math.round(float * max);
+ } else {
+ assert(float >= 0 && float <= 1);
+ const max = Math.pow(2, bits) - 1;
+ return Math.round(float * max);
+ }
+}
+
+// Does not handle clamping, underflow, overflow, denormalized numbers
+export function float32ToFloatBits(
+ n: number,
+ signBits: 0 | 1,
+ exponentBits: number,
+ fractionBits: number,
+ bias: number
+): number {
+ assert(exponentBits <= 8);
+ assert(fractionBits <= 23);
+ assert(Number.isFinite(n));
+
+ if (n === 0) {
+ return 0;
+ }
+
+ if (signBits === 0) {
+ assert(n >= 0);
+ }
+
+ const buf = new DataView(new ArrayBuffer(Float32Array.BYTES_PER_ELEMENT));
+ buf.setFloat32(0, n, true);
+ const bits = buf.getUint32(0, true);
+ // bits (32): seeeeeeeefffffffffffffffffffffff
+
+ const fractionBitsToDiscard = 23 - fractionBits;
+
+ // 0 or 1
+ const sign = (bits >> 31) & signBits;
+
+ // >> to remove fraction, & to remove sign, - 127 to remove bias.
+ const exp = ((bits >> 23) & 0xff) - 127;
+
+ // Convert to the new biased exponent.
+ const newBiasedExp = bias + exp;
+ assert(newBiasedExp >= 0 && newBiasedExp < 1 << exponentBits);
+
+ // Mask only the fraction, and discard the lower bits.
+ const newFraction = (bits & 0x7fffff) >> fractionBitsToDiscard;
+ return (sign << (exponentBits + fractionBits)) | (newBiasedExp << fractionBits) | newFraction;
+}
+
+export function assertInIntegerRange(n: number, bits: number, signed: boolean): void {
+ if (signed) {
+ const min = -Math.pow(2, bits - 1);
+ const max = Math.pow(2, bits - 1) - 1;
+ assert(n >= min && n <= max);
+ } else {
+ const max = Math.pow(2, bits) - 1;
+ assert(n >= 0 && n <= max);
+ }
+}
+
+export function gammaCompress(n: number): number {
+ n = n <= 0.0031308 ? 12.92 * n : 1.055 * Math.pow(n, 1 / 2.4) - 0.055;
+ return n < 0 ? 0 : n > 1 ? 1 : n;
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/util/math.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/util/math.ts
new file mode 100644
index 00000000000..61f898d6295
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/util/math.ts
@@ -0,0 +1,7 @@
+export function align(n: number, alignment: number): number {
+ return Math.ceil(n / alignment) * alignment;
+}
+
+export function isAligned(n: number, alignment: number): boolean {
+ return n === align(n, alignment);
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/layout.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/layout.ts
new file mode 100644
index 00000000000..ccc0bd2f4fb
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/layout.ts
@@ -0,0 +1,157 @@
+import { assert, unreachable } from '../../../common/framework/util/util.js';
+import { kTextureFormatInfo } from '../../capability_info.js';
+import { align, isAligned } from '../math.js';
+
+export const kBytesPerRowAlignment = 256;
+export const kBufferCopyAlignment = 4;
+
+export interface LayoutOptions {
+ mipLevel: number;
+ bytesPerRow?: number;
+ rowsPerImage?: number;
+}
+
+const kDefaultLayoutOptions = { mipLevel: 0, bytesPerRow: undefined, rowsPerImage: undefined };
+
+export function getMipSizePassthroughLayers(
+ dimension: GPUTextureDimension,
+ size: [number, number, number],
+ mipLevel: number
+): [number, number, number] {
+ const shiftMinOne = (n: number) => Math.max(1, n >> mipLevel);
+ switch (dimension) {
+ case '1d':
+ assert(size[2] === 1);
+ return [shiftMinOne(size[0]), size[1], size[2]];
+ case '2d':
+ return [shiftMinOne(size[0]), shiftMinOne(size[1]), size[2]];
+ case '3d':
+ return [shiftMinOne(size[0]), shiftMinOne(size[1]), shiftMinOne(size[2])];
+ default:
+ unreachable();
+ }
+}
+
+export function getTextureCopyLayout(
+ format: GPUTextureFormat,
+ dimension: GPUTextureDimension,
+ size: [number, number, number],
+ options: LayoutOptions = kDefaultLayoutOptions
+): {
+ bytesPerBlock: number;
+ byteLength: number;
+ minBytesPerRow: number;
+ bytesPerRow: number;
+ rowsPerImage: number;
+ mipSize: [number, number, number];
+} {
+ const { mipLevel } = options;
+ let { bytesPerRow, rowsPerImage } = options;
+
+ const mipSize = getMipSizePassthroughLayers(dimension, size, mipLevel);
+
+ const { blockWidth, blockHeight, bytesPerBlock } = kTextureFormatInfo[format];
+ assert(!!bytesPerBlock && !!blockWidth && !!blockHeight);
+
+ assert(isAligned(mipSize[0], blockWidth));
+ const minBytesPerRow = (mipSize[0] / blockWidth) * bytesPerBlock;
+ const alignedMinBytesPerRow = align(minBytesPerRow, kBytesPerRowAlignment);
+ if (bytesPerRow !== undefined) {
+ assert(bytesPerRow >= alignedMinBytesPerRow);
+ assert(isAligned(bytesPerRow, kBytesPerRowAlignment));
+ } else {
+ bytesPerRow = alignedMinBytesPerRow;
+ }
+
+ if (rowsPerImage !== undefined) {
+ assert(rowsPerImage >= mipSize[1]);
+ } else {
+ rowsPerImage = mipSize[1];
+ }
+
+ assert(isAligned(rowsPerImage, blockHeight));
+ const bytesPerSlice = bytesPerRow * (rowsPerImage / blockHeight);
+ const sliceSize =
+ bytesPerRow * (mipSize[1] / blockHeight - 1) + bytesPerBlock * (mipSize[0] / blockWidth);
+ const byteLength = bytesPerSlice * (mipSize[2] - 1) + sliceSize;
+
+ return {
+ bytesPerBlock,
+ byteLength: align(byteLength, kBufferCopyAlignment),
+ minBytesPerRow,
+ bytesPerRow,
+ rowsPerImage,
+ mipSize,
+ };
+}
+
+export function fillTextureDataWithTexelValue(
+ texelValue: ArrayBuffer,
+ format: GPUTextureFormat,
+ dimension: GPUTextureDimension,
+ outputBuffer: ArrayBuffer,
+ size: [number, number, number],
+ options: LayoutOptions = kDefaultLayoutOptions
+): void {
+ const { blockWidth, blockHeight, bytesPerBlock } = kTextureFormatInfo[format];
+ assert(!!bytesPerBlock && !!blockWidth && !!blockHeight);
+ assert(bytesPerBlock === texelValue.byteLength);
+
+ const { byteLength, rowsPerImage, bytesPerRow } = getTextureCopyLayout(
+ format,
+ dimension,
+ size,
+ options
+ );
+
+ assert(byteLength <= outputBuffer.byteLength);
+
+ const mipSize = getMipSizePassthroughLayers(dimension, size, options.mipLevel);
+
+ const texelValueBytes = new Uint8Array(texelValue);
+ const outputTexelValueBytes = new Uint8Array(outputBuffer);
+ for (let slice = 0; slice < mipSize[2]; ++slice) {
+ for (let row = 0; row < mipSize[1]; row += blockHeight) {
+ for (let col = 0; col < mipSize[0]; col += blockWidth) {
+ const byteOffset =
+ slice * rowsPerImage * bytesPerRow + row * bytesPerRow + col * texelValue.byteLength;
+ outputTexelValueBytes.set(texelValueBytes, byteOffset);
+ }
+ }
+ }
+}
+
+export function createTextureUploadBuffer(
+ texelValue: ArrayBuffer,
+ device: GPUDevice,
+ format: GPUTextureFormat,
+ dimension: GPUTextureDimension,
+ size: [number, number, number],
+ options: LayoutOptions = kDefaultLayoutOptions
+): {
+ buffer: GPUBuffer;
+ bytesPerRow: number;
+ rowsPerImage: number;
+} {
+ const { byteLength, bytesPerRow, rowsPerImage, bytesPerBlock } = getTextureCopyLayout(
+ format,
+ dimension,
+ size,
+ options
+ );
+
+ const [buffer, mapping] = device.createBufferMapped({
+ size: byteLength,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+
+ assert(texelValue.byteLength === bytesPerBlock);
+ fillTextureDataWithTexelValue(texelValue, format, dimension, mapping, size, options);
+ buffer.unmap();
+
+ return {
+ buffer,
+ bytesPerRow,
+ rowsPerImage,
+ };
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/subresource.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/subresource.ts
new file mode 100644
index 00000000000..8201002a5f1
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/subresource.ts
@@ -0,0 +1,55 @@
+export interface BeginCountRange {
+ begin: number;
+ count: number;
+}
+
+export interface BeginEndRange {
+ begin: number;
+ end: number;
+}
+
+function endOfRange(r: BeginEndRange | BeginCountRange): number {
+ return 'count' in r ? r.begin + r.count : r.end;
+}
+
+function* rangeAsIterator(r: BeginEndRange | BeginCountRange): Generator<number> {
+ for (let i = r.begin; i < endOfRange(r); ++i) {
+ yield i;
+ }
+}
+
+export class SubresourceRange {
+ readonly mipRange: BeginEndRange;
+ readonly sliceRange: BeginEndRange;
+
+ constructor(subresources: {
+ mipRange: BeginEndRange | BeginCountRange;
+ sliceRange: BeginEndRange | BeginCountRange;
+ }) {
+ this.mipRange = {
+ begin: subresources.mipRange.begin,
+ end: endOfRange(subresources.mipRange),
+ };
+ this.sliceRange = {
+ begin: subresources.sliceRange.begin,
+ end: endOfRange(subresources.sliceRange),
+ };
+ }
+
+ *each(): Generator<{ level: number; slice: number }> {
+ for (let level = this.mipRange.begin; level < this.mipRange.end; ++level) {
+ for (let slice = this.sliceRange.begin; slice < this.sliceRange.end; ++slice) {
+ yield { level, slice };
+ }
+ }
+ }
+
+ *mipLevels(): Generator<{ level: number; slices: Generator<number> }> {
+ for (let level = this.mipRange.begin; level < this.mipRange.end; ++level) {
+ yield {
+ level,
+ slices: rangeAsIterator(this.sliceRange),
+ };
+ }
+ }
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/texelData.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/texelData.ts
new file mode 100644
index 00000000000..2229a76c16b
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/util/texture/texelData.ts
@@ -0,0 +1,341 @@
+import { assert, unreachable } from '../../../common/framework/util/util.js';
+import { kTextureFormatInfo } from '../../capability_info.js';
+import {
+ assertInIntegerRange,
+ float32ToFloatBits,
+ floatAsNormalizedInteger,
+ gammaCompress,
+} from '../conversion.js';
+
+export const enum TexelComponent {
+ R = 'R',
+ G = 'G',
+ B = 'B',
+ A = 'A',
+ Depth = 'Depth',
+ Stencil = 'Stencil',
+}
+
+export type PerTexelComponent<T> = { [c in TexelComponent]?: T };
+
+const enum TexelWriteType {
+ Sint,
+ Uint,
+ Float,
+}
+
+// Function to convert a value into a texel value. It returns the converted value
+// and the type of the converted value. For example, conversion may convert:
+// - floats to unsigned normalized integers
+// - floats to half floats, interpreted as uint16 bits
+type TexelWriteFn = (value: number) => { value: number; type: TexelWriteType };
+
+interface SingleComponentInfo {
+ write: TexelWriteFn;
+ bitLength: number;
+}
+
+type TexelComponentInfo = PerTexelComponent<null | SingleComponentInfo>;
+
+const kR = [TexelComponent.R];
+const kRG = [TexelComponent.R, TexelComponent.G];
+const kRGB = [TexelComponent.R, TexelComponent.G, TexelComponent.B];
+const kRGBA = [TexelComponent.R, TexelComponent.G, TexelComponent.B, TexelComponent.A];
+const kBGRA = [TexelComponent.B, TexelComponent.G, TexelComponent.R, TexelComponent.A];
+
+const unorm = (bitLength: number) => (n: number) => ({
+ value: floatAsNormalizedInteger(n, bitLength, false),
+ type: TexelWriteType.Uint,
+});
+
+const snorm = (bitLength: number) => (n: number) => ({
+ value: floatAsNormalizedInteger(n, bitLength, true),
+ type: TexelWriteType.Sint,
+});
+
+const uint = (bitLength: number) => (n: number) => ({
+ value: (assertInIntegerRange(n, bitLength, false), n),
+ type: TexelWriteType.Uint,
+});
+
+const sint = (bitLength: number) => (n: number) => ({
+ value: (assertInIntegerRange(n, bitLength, true), n),
+ type: TexelWriteType.Sint,
+});
+
+const unorm2 = { write: unorm(2), bitLength: 2 };
+const unorm8 = { write: unorm(8), bitLength: 8 };
+const unorm10 = { write: unorm(10), bitLength: 10 };
+
+const snorm8 = { write: snorm(8), bitLength: 8 };
+
+const uint8 = { write: uint(8), bitLength: 8 };
+const uint16 = { write: uint(16), bitLength: 16 };
+const uint32 = { write: uint(32), bitLength: 32 };
+
+const sint8 = { write: sint(8), bitLength: 8 };
+const sint16 = { write: sint(16), bitLength: 16 };
+const sint32 = { write: sint(32), bitLength: 32 };
+
+const float10 = {
+ write: (n: number) => ({
+ value: float32ToFloatBits(n, 0, 5, 5, 15),
+ type: TexelWriteType.Uint,
+ }),
+ bitLength: 10,
+};
+
+const float11 = {
+ write: (n: number) => ({
+ value: float32ToFloatBits(n, 0, 5, 6, 15),
+ type: TexelWriteType.Uint,
+ }),
+ bitLength: 11,
+};
+
+const float16 = {
+ write: (n: number) => ({
+ value: float32ToFloatBits(n, 1, 5, 10, 15),
+ type: TexelWriteType.Uint,
+ }),
+ bitLength: 16,
+};
+
+const float32 = {
+ write: (n: number) => ({
+ value: Math.fround(n),
+ type: TexelWriteType.Float,
+ }),
+ bitLength: 32,
+};
+
+const repeatComponents = (
+ componentOrder: TexelComponent[],
+ perComponentInfo: SingleComponentInfo
+) => {
+ const componentInfo = componentOrder.reduce((acc, curr) => {
+ return Object.assign(acc, {
+ [curr]: perComponentInfo,
+ });
+ }, {});
+
+ return {
+ componentOrder,
+ componentInfo,
+ };
+};
+
+const kRepresentationInfo: {
+ [k in GPUTextureFormat]: {
+ componentOrder: TexelComponent[];
+ componentInfo: TexelComponentInfo;
+ sRGB: boolean;
+ // Add fields as needed
+ };
+} = /* prettier-ignore */ {
+ 'r8unorm': { ...repeatComponents( kR, unorm8), sRGB: false },
+ 'r8snorm': { ...repeatComponents( kR, snorm8), sRGB: false },
+ 'r8uint': { ...repeatComponents( kR, uint8), sRGB: false },
+ 'r8sint': { ...repeatComponents( kR, sint8), sRGB: false },
+ 'r16uint': { ...repeatComponents( kR, uint16), sRGB: false },
+ 'r16sint': { ...repeatComponents( kR, sint16), sRGB: false },
+ 'r16float': { ...repeatComponents( kR, float16), sRGB: false },
+ 'rg8unorm': { ...repeatComponents( kRG, unorm8), sRGB: false },
+ 'rg8snorm': { ...repeatComponents( kRG, snorm8), sRGB: false },
+ 'rg8uint': { ...repeatComponents( kRG, uint8), sRGB: false },
+ 'rg8sint': { ...repeatComponents( kRG, sint8), sRGB: false },
+ 'r32uint': { ...repeatComponents( kR, uint32), sRGB: false },
+ 'r32sint': { ...repeatComponents( kR, sint32), sRGB: false },
+ 'r32float': { ...repeatComponents( kR, float32), sRGB: false },
+ 'rg16uint': { ...repeatComponents( kRG, uint16), sRGB: false },
+ 'rg16sint': { ...repeatComponents( kRG, sint16), sRGB: false },
+ 'rg16float': { ...repeatComponents( kRG, float16), sRGB: false },
+
+ 'rgba8unorm': { ...repeatComponents(kRGBA, unorm8), sRGB: false },
+ 'rgba8unorm-srgb': { ...repeatComponents(kRGBA, unorm8), sRGB: true },
+ 'rgba8snorm': { ...repeatComponents(kRGBA, snorm8), sRGB: false },
+ 'rgba8uint': { ...repeatComponents(kRGBA, uint8), sRGB: false },
+ 'rgba8sint': { ...repeatComponents(kRGBA, sint8), sRGB: false },
+ 'bgra8unorm': { ...repeatComponents(kBGRA, unorm8), sRGB: false },
+ 'bgra8unorm-srgb': { ...repeatComponents(kBGRA, unorm8), sRGB: true },
+ 'rg32uint': { ...repeatComponents( kRG, uint32), sRGB: false },
+ 'rg32sint': { ...repeatComponents( kRG, sint32), sRGB: false },
+ 'rg32float': { ...repeatComponents( kRG, float32), sRGB: false },
+ 'rgba16uint': { ...repeatComponents(kRGBA, uint16), sRGB: false },
+ 'rgba16sint': { ...repeatComponents(kRGBA, sint16), sRGB: false },
+ 'rgba16float': { ...repeatComponents(kRGBA, float16), sRGB: false },
+ 'rgba32uint': { ...repeatComponents(kRGBA, uint32), sRGB: false },
+ 'rgba32sint': { ...repeatComponents(kRGBA, sint32), sRGB: false },
+ 'rgba32float': { ...repeatComponents(kRGBA, float32), sRGB: false },
+
+ 'rgb10a2unorm': { componentOrder: kRGBA, componentInfo: { R: unorm10, G: unorm10, B: unorm10, A: unorm2 }, sRGB: false },
+ 'rg11b10float': { componentOrder: kRGB, componentInfo: { R: float11, G: float11, B: float10 }, sRGB: false },
+
+ 'depth32float': { componentOrder: [TexelComponent.Depth], componentInfo: { Depth: float32 }, sRGB: false },
+ 'depth24plus': { componentOrder: [TexelComponent.Depth], componentInfo: { Depth: null }, sRGB: false },
+ 'depth24plus-stencil8': { componentOrder: [TexelComponent.Depth, TexelComponent.Stencil], componentInfo: { Depth: null, Stencil: null }, sRGB: false },
+};
+
+export interface TexelDataRepresentation {
+ readonly componentOrder: TexelComponent[];
+ readonly componentInfo: TexelComponentInfo;
+ getBytes(components: { [c in TexelComponent]?: number }): ArrayBuffer;
+}
+
+class TexelDataRepresentationImpl implements TexelDataRepresentation {
+ // TODO: Determine endianness of the GPU data?
+ private isGPULittleEndian = true;
+
+ constructor(
+ private readonly format: GPUTextureFormat,
+ readonly componentOrder: TexelComponent[],
+ readonly componentInfo: TexelComponentInfo,
+ private readonly sRGB: boolean
+ ) {}
+
+ private totalBitLength(): number {
+ return this.componentOrder.reduce((acc, curr) => {
+ return acc + this.componentInfo[curr]!.bitLength;
+ }, 0);
+ }
+
+ private setComponent(data: ArrayBuffer, component: TexelComponent, n: number): void {
+ const componentIndex = this.componentOrder.indexOf(component);
+ assert(componentIndex !== -1);
+ const bitOffset = this.componentOrder.slice(0, componentIndex).reduce((acc, curr) => {
+ const componentInfo = this.componentInfo[curr];
+ assert(!!componentInfo);
+ return acc + componentInfo.bitLength;
+ }, 0);
+
+ const componentInfo = this.componentInfo[component];
+ assert(!!componentInfo);
+ const { write, bitLength } = componentInfo;
+
+ const { value, type } = write(n);
+ switch (type) {
+ case TexelWriteType.Float: {
+ const byteOffset = Math.floor(bitOffset / 8);
+ const byteLength = Math.ceil(bitLength / 8);
+ assert(byteOffset === bitOffset / 8 && byteLength === bitLength / 8);
+ switch (byteLength) {
+ case 4:
+ new DataView(data, byteOffset, byteLength).setFloat32(0, value, this.isGPULittleEndian);
+ break;
+ default:
+ unreachable();
+ }
+ break;
+ }
+ case TexelWriteType.Sint: {
+ const byteOffset = Math.floor(bitOffset / 8);
+ const byteLength = Math.ceil(bitLength / 8);
+ assert(byteOffset === bitOffset / 8 && byteLength === bitLength / 8);
+ switch (byteLength) {
+ case 1:
+ new DataView(data, byteOffset, byteLength).setInt8(0, value);
+ break;
+ case 2:
+ new DataView(data, byteOffset, byteLength).setInt16(0, value, this.isGPULittleEndian);
+ break;
+ case 4:
+ new DataView(data, byteOffset, byteLength).setInt32(0, value, this.isGPULittleEndian);
+ break;
+ default:
+ unreachable();
+ }
+ break;
+ }
+ case TexelWriteType.Uint: {
+ const byteOffset = Math.floor(bitOffset / 8);
+ const byteLength = Math.ceil(bitLength / 8);
+ if (byteOffset === bitOffset / 8 && byteLength === bitLength / 8) {
+ switch (byteLength) {
+ case 1:
+ new DataView(data, byteOffset, byteLength).setUint8(0, value);
+ break;
+ case 2:
+ new DataView(data, byteOffset, byteLength).setUint16(
+ 0,
+ value,
+ this.isGPULittleEndian
+ );
+ break;
+ case 4:
+ new DataView(data, byteOffset, byteLength).setUint32(
+ 0,
+ value,
+ this.isGPULittleEndian
+ );
+ break;
+ default:
+ unreachable();
+ }
+ } else {
+ // Packed representations are all 32-bit and use Uint as the data type.
+ // ex.) rg10b11float, rgb10a2unorm
+ switch (this.totalBitLength()) {
+ case 32: {
+ const view = new DataView(data);
+ const currentValue = view.getUint32(0, this.isGPULittleEndian);
+
+ let mask = 0xffffffff;
+ const bitsToClearRight = bitOffset;
+ const bitsToClearLeft = 32 - (bitLength + bitOffset);
+
+ mask = (mask >>> bitsToClearRight) << bitsToClearRight;
+ mask = (mask << bitsToClearLeft) >>> bitsToClearLeft;
+
+ const newValue = (currentValue & ~mask) | (value << bitOffset);
+
+ view.setUint32(0, newValue, this.isGPULittleEndian);
+ break;
+ }
+ default:
+ unreachable();
+ }
+ }
+ break;
+ }
+ default:
+ unreachable();
+ }
+ }
+
+ getBytes(components: PerTexelComponent<number>): ArrayBuffer {
+ if (this.sRGB) {
+ components = Object.assign({}, components);
+ assert(components.R !== undefined);
+ assert(components.G !== undefined);
+ assert(components.B !== undefined);
+ [components.R, components.G, components.B] = [
+ gammaCompress(components.R),
+ gammaCompress(components.G),
+ gammaCompress(components.B),
+ ];
+ }
+
+ const bytesPerBlock = kTextureFormatInfo[this.format].bytesPerBlock;
+ assert(!!bytesPerBlock);
+
+ const data = new ArrayBuffer(bytesPerBlock);
+ for (const c of this.componentOrder) {
+ const componentValue = components[c];
+ assert(componentValue !== undefined);
+ this.setComponent(data, c, componentValue);
+ }
+ return data;
+ }
+}
+
+const kRepresentationCache: Map<GPUTextureFormat, TexelDataRepresentationImpl> = new Map();
+export function getTexelDataRepresentation(format: GPUTextureFormat): TexelDataRepresentation {
+ if (!kRepresentationCache.has(format)) {
+ const { componentOrder, componentInfo, sRGB } = kRepresentationInfo[format];
+ kRepresentationCache.set(
+ format,
+ new TexelDataRepresentationImpl(format, componentOrder, componentInfo, sRGB)
+ );
+ }
+ return kRepresentationCache.get(format)!;
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/canvas/context_creation.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/canvas/context_creation.spec.ts
index a3de901e919..e2c79db9fe2 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/canvas/context_creation.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/canvas/context_creation.spec.ts
@@ -1,11 +1,11 @@
-export const description = ``;
+export const description = '';
import { Fixture } from '../../../common/framework/fixture.js';
-import { TestGroup } from '../../../common/framework/test_group.js';
+import { makeTestGroup } from '../../../common/framework/test_group.js';
-export const g = new TestGroup(Fixture);
+export const g = makeTestGroup(Fixture);
-g.test('canvas element getContext returns GPUCanvasContext', async t => {
+g.test('canvas_element_getContext_returns_GPUCanvasContext').fn(async t => {
if (typeof document === 'undefined') {
// Skip if there is no document (Workers, Node)
t.skip('DOM is not available to create canvas element');
@@ -16,8 +16,8 @@ g.test('canvas element getContext returns GPUCanvasContext', async t => {
canvas.height = 10;
// TODO: fix types so these aren't necessary
- // tslint:disable-next-line: no-any
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const ctx: any = canvas.getContext('gpupresent');
- // tslint:disable-next-line: no-any
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
t.expect(ctx instanceof (window as any).GPUCanvasContext);
});
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/copyImageBitmapToTexture.spec.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/copyImageBitmapToTexture.spec.ts
index ce411f2eab6..34cd83982e8 100644
--- a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/copyImageBitmapToTexture.spec.ts
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/copyImageBitmapToTexture.spec.ts
@@ -2,8 +2,8 @@ export const description = `
copy imageBitmap To texture tests.
`;
-import { pcombine, poptions } from '../../common/framework/params.js';
-import { TestGroup } from '../../common/framework/test_group.js';
+import { poptions, params } from '../../common/framework/params_builder.js';
+import { makeTestGroup } from '../../common/framework/test_group.js';
import { GPUTest } from '../gpu_test.js';
function calculateRowPitch(width: number, bytesPerPixel: number): number {
@@ -22,7 +22,7 @@ class F extends GPUTest {
): void {
const exp = new Uint8Array(expected.buffer, expected.byteOffset, expected.byteLength);
const rowPitch = calculateRowPitch(width, bytesPerPixel);
- const dst = this.createCopyForMapRead(src, rowPitch * height);
+ const dst = this.createCopyForMapRead(src, 0, rowPitch * height);
this.eventualAsyncExpectation(async niceStack => {
const actual = new Uint8Array(await dst.mapReadAsync());
@@ -36,7 +36,7 @@ class F extends GPUTest {
);
if (check !== undefined) {
niceStack.message = check;
- this.rec.fail(niceStack);
+ this.rec.expectationFailed(niceStack);
}
dst.destroy();
});
@@ -50,27 +50,33 @@ class F extends GPUTest {
rowPitch: number,
bytesPerPixel: number
): string | undefined {
- const lines = [];
- let failedPixels = 0;
- for (let i = 0; i < height; ++i) {
+ const failedByteIndices: string[] = [];
+ const failedByteExpectedValues: string[] = [];
+ const failedByteActualValues: string[] = [];
+ iLoop: for (let i = 0; i < height; ++i) {
const bytesPerRow = width * bytesPerPixel;
for (let j = 0; j < bytesPerRow; ++j) {
const indexExp = j + i * bytesPerRow;
const indexActual = j + rowPitch * i;
if (actual[indexActual] !== exp[indexExp]) {
- if (failedPixels > 4) {
- break;
+ if (failedByteIndices.length >= 4) {
+ failedByteIndices.push('...');
+ failedByteExpectedValues.push('...');
+ failedByteActualValues.push('...');
+ break iLoop;
}
- failedPixels++;
- lines.push(`at [${indexExp}], expected ${exp[indexExp]}, got ${actual[indexActual]}`);
+ failedByteIndices.push(`(${i},${j})`);
+ failedByteExpectedValues.push(exp[indexExp].toString());
+ failedByteActualValues.push(actual[indexActual].toString());
}
}
- if (failedPixels > 4) {
- lines.push('... and more');
- break;
- }
}
- return failedPixels > 0 ? lines.join('\n') : undefined;
+ if (failedByteIndices.length > 0) {
+ return `at [${failedByteIndices.join(', ')}], \
+expected [${failedByteExpectedValues.join(', ')}], \
+got [${failedByteActualValues.join(', ')}]`;
+ }
+ return undefined;
}
doTestAndCheckResult(
@@ -114,108 +120,156 @@ class F extends GPUTest {
}
}
-export const g = new TestGroup(F);
+export const g = makeTestGroup(F);
-g.test('from ImageData', async t => {
- const { width, height } = t.params;
+g.test('from_ImageData')
+ .params(
+ params()
+ .combine(poptions('width', [1, 2, 4, 15, 255, 256]))
+ .combine(poptions('height', [1, 2, 4, 15, 255, 256]))
+ .combine(poptions('alpha', ['none', 'premultiply']))
+ .combine(poptions('orientation', ['none', 'flipY']))
+ )
+ .fn(async t => {
+ const { width, height, alpha, orientation } = t.params;
- // The texture format is rgba8unorm, so the bytes per pixel is 4.
- const bytesPerPixel = 4;
+ // The texture format is rgba8unorm, so the bytes per pixel is 4.
+ const bytesPerPixel = 4;
- const imagePixels = new Uint8ClampedArray(bytesPerPixel * width * height);
- for (let i = 0; i < width * height * bytesPerPixel; ++i) {
- imagePixels[i] = i % 4 === 3 ? 255 : i % 256;
- }
+ const imagePixels = new Uint8ClampedArray(bytesPerPixel * width * height);
+ if (alpha === 'premultiply') {
+ // Make expected value simple to construct:
+ // Input is (255, 255, 255, a), which will be stored into the ImageBitmap
+ // as (a, a, a, a).
+ for (let i = 0; i < width * height * bytesPerPixel; ++i) {
+ imagePixels[i] = i % 4 !== 3 ? 255 : i % 256;
+ }
+ } else {
+ for (let i = 0; i < width * height * bytesPerPixel; ++i) {
+ imagePixels[i] = i % 4 === 3 ? 255 : i % 256;
+ }
+ }
+
+ const imageData = new ImageData(imagePixels, width, height);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const imageBitmap = await (createImageBitmap as any)(imageData, {
+ premultiplyAlpha: alpha,
+ imageOrientation: orientation,
+ });
+
+ const dst = t.device.createTexture({
+ size: {
+ width: imageBitmap.width,
+ height: imageBitmap.height,
+ depth: 1,
+ },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
+ });
+
+ // Construct expected value
+ const expectedPixels = new Uint8ClampedArray(bytesPerPixel * width * height);
+ for (let i = 0; i < width * height * bytesPerPixel; ++i) {
+ expectedPixels[i] = imagePixels[i];
+ }
+
+ if (orientation === 'flipY') {
+ for (let i = 0; i < height; ++i) {
+ for (let j = 0; j < width * bytesPerPixel; ++j) {
+ const pos_image_pixel = (height - i - 1) * width * bytesPerPixel + j;
+ const pos_expected_value = i * width * bytesPerPixel + j;
+ expectedPixels[pos_expected_value] = imagePixels[pos_image_pixel];
+ }
+ }
+ }
+
+ if (alpha === 'premultiply') {
+ for (let i = 0; i < width * height * bytesPerPixel; ++i) {
+ const alpha_value_position = 3 - (i % 4) + i;
+ if (i % 4 !== 3) {
+ // Expected value is (a, a, a, a)
+ expectedPixels[i] = expectedPixels[alpha_value_position];
+ }
+ }
+ }
- const imageData = new ImageData(imagePixels, width, height);
- const imageBitmap = await createImageBitmap(imageData);
-
- const dst = t.device.createTexture({
- size: {
- width: imageBitmap.width,
- height: imageBitmap.height,
- depth: 1,
- },
- format: 'rgba8unorm',
- usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
+ t.doTestAndCheckResult(
+ { imageBitmap, origin: { x: 0, y: 0 } },
+ { texture: dst },
+ { width: imageBitmap.width, height: imageBitmap.height, depth: 1 },
+ bytesPerPixel,
+ expectedPixels
+ );
});
- t.doTestAndCheckResult(
- { imageBitmap, origin: { x: 0, y: 0 } },
- { texture: dst },
- { width: imageBitmap.width, height: imageBitmap.height, depth: 1 },
- bytesPerPixel,
- imagePixels
- );
-}).params(
- pcombine(
- poptions('width', [1, 2, 4, 15, 255, 256]), //
- poptions('height', [1, 2, 4, 15, 255, 256])
+g.test('from_canvas')
+ .params(
+ params()
+ .combine(poptions('width', [1, 2, 4, 15, 255, 256]))
+ .combine(poptions('height', [1, 2, 4, 15, 255, 256]))
)
-);
-
-g.test('from canvas', async t => {
- const { width, height } = t.params;
-
- // CTS sometimes runs on worker threads, where document is not available.
- // In this case, OffscreenCanvas can be used instead of <canvas>.
- // But some browsers don't support OffscreenCanvas, and some don't
- // support '2d' contexts on OffscreenCanvas.
- // In this situation, the case will be skipped.
- let imageCanvas;
- if (typeof document !== 'undefined') {
- imageCanvas = document.createElement('canvas');
- imageCanvas.width = width;
- imageCanvas.height = height;
- } else if (typeof OffscreenCanvas === 'undefined') {
- t.skip('OffscreenCanvas is not supported');
- return;
- } else {
- imageCanvas = new OffscreenCanvas(width, height);
- }
- const imageCanvasContext = imageCanvas.getContext('2d');
- if (imageCanvasContext === null) {
- t.skip('OffscreenCanvas "2d" context not available');
- return;
- }
+ .fn(async t => {
+ const { width, height } = t.params;
- // The texture format is rgba8unorm, so the bytes per pixel is 4.
- const bytesPerPixel = 4;
+ // CTS sometimes runs on worker threads, where document is not available.
+ // In this case, OffscreenCanvas can be used instead of <canvas>.
+ // But some browsers don't support OffscreenCanvas, and some don't
+ // support '2d' contexts on OffscreenCanvas.
+ // In this situation, the case will be skipped.
+ let imageCanvas;
+ if (typeof document !== 'undefined') {
+ imageCanvas = document.createElement('canvas');
+ imageCanvas.width = width;
+ imageCanvas.height = height;
+ } else if (typeof OffscreenCanvas === 'undefined') {
+ t.skip('OffscreenCanvas is not supported');
+ return;
+ } else {
+ imageCanvas = new OffscreenCanvas(width, height);
+ }
+ const imageCanvasContext = imageCanvas.getContext('2d');
+ if (imageCanvasContext === null) {
+ t.skip('OffscreenCanvas "2d" context not available');
+ return;
+ }
- // Generate original data.
- const imagePixels = new Uint8ClampedArray(bytesPerPixel * width * height);
- for (let i = 0; i < width * height * bytesPerPixel; ++i) {
- imagePixels[i] = i % 256;
- }
+ // The texture format is rgba8unorm, so the bytes per pixel is 4.
+ const bytesPerPixel = 4;
- const imageData = new ImageData(imagePixels, width, height);
- imageCanvasContext.putImageData(imageData, 0, 0);
+ // Generate original data.
+ const imagePixels = new Uint8ClampedArray(bytesPerPixel * width * height);
+ for (let i = 0; i < width * height * bytesPerPixel; ++i) {
+ imagePixels[i] = i % 4 === 3 ? 255 : i % 256;
+ }
- const imageBitmap = await createImageBitmap(imageCanvas);
+ const imageData = new ImageData(imagePixels, width, height);
+ imageCanvasContext.putImageData(imageData, 0, 0);
- const dst = t.device.createTexture({
- size: {
- width: imageBitmap.width,
- height: imageBitmap.height,
- depth: 1,
- },
- format: 'rgba8unorm',
- usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
- });
+ const imageBitmap = await createImageBitmap(imageCanvas);
- const expectedData = imageCanvasContext.getImageData(0, 0, imageBitmap.width, imageBitmap.height)
- .data;
-
- t.doTestAndCheckResult(
- { imageBitmap, origin: { x: 0, y: 0 } },
- { texture: dst },
- { width: imageBitmap.width, height: imageBitmap.height, depth: 1 },
- bytesPerPixel,
- expectedData
- );
-}).params(
- pcombine(
- poptions('width', [1, 2, 4, 15, 255, 256]), //
- poptions('height', [1, 2, 4, 15, 255, 256])
- )
-);
+ const dst = t.device.createTexture({
+ size: {
+ width: imageBitmap.width,
+ height: imageBitmap.height,
+ depth: 1,
+ },
+ format: 'rgba8unorm',
+ usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
+ });
+
+ // This will get origin data and even it has premultiplied-alpha
+ const expectedData = imageCanvasContext.getImageData(
+ 0,
+ 0,
+ imageBitmap.width,
+ imageBitmap.height
+ ).data;
+
+ t.doTestAndCheckResult(
+ { imageBitmap, origin: { x: 0, y: 0 } },
+ { texture: dst },
+ { width: imageBitmap.width, height: imageBitmap.height, depth: 1 },
+ bytesPerPixel,
+ expectedData
+ );
+ });
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_clear.html b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_clear.html
new file mode 100644
index 00000000000..86a3da939db
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_clear.html
@@ -0,0 +1,10 @@
+<html class="reftest-wait">
+ <title>WebGPU canvas_clear</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta name="assert" content="WebGPU cleared canvas should be presented correctly" />
+ <link rel="match" href="./ref/canvas_clear-ref.html" />
+ <canvas id="gpucanvas" width="10" height="10"></canvas>
+ <script src="/common/reftest-wait.js"></script>
+ <script type="module" src="canvas_clear.js"></script>
+</html>
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_clear.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_clear.ts
new file mode 100644
index 00000000000..799e3ad9292
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_clear.ts
@@ -0,0 +1,27 @@
+import { runRefTest } from './gpu_ref_test.js';
+
+runRefTest(async t => {
+ const canvas = document.getElementById('gpucanvas') as HTMLCanvasElement;
+
+ const ctx = (canvas.getContext('gpupresent') as unknown) as GPUCanvasContext;
+ const swapChain = ctx.configureSwapChain({
+ device: t.device,
+ format: 'bgra8unorm',
+ });
+
+ const colorAttachment = swapChain.getCurrentTexture();
+ const colorAttachmentView = colorAttachment.createView();
+
+ const encoder = t.device.createCommandEncoder();
+ const pass = encoder.beginRenderPass({
+ colorAttachments: [
+ {
+ attachment: colorAttachmentView,
+ loadValue: { r: 0.0, g: 1.0, b: 0.0, a: 1.0 },
+ storeOp: 'store',
+ },
+ ],
+ });
+ pass.endPass();
+ t.device.defaultQueue.submit([encoder.finish()]);
+});
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_complex.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_complex.ts
new file mode 100644
index 00000000000..4c8854b732f
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_complex.ts
@@ -0,0 +1,76 @@
+import { unreachable } from '../../../common/framework/util/util.js';
+
+import { runRefTest } from './gpu_ref_test.js';
+
+// <canvas> element from html page
+declare const cvs: HTMLCanvasElement;
+
+export function run(format: GPUTextureFormat) {
+ runRefTest(async t => {
+ const ctx = (cvs.getContext('gpupresent') as unknown) as GPUCanvasContext;
+
+ switch (format) {
+ case 'bgra8unorm':
+ case 'rgba16float':
+ break;
+ default:
+ unreachable();
+ }
+
+ const swapChain = ctx.configureSwapChain({
+ device: t.device,
+ format,
+ usage: GPUTextureUsage.COPY_DST,
+ });
+
+ const rows = 2;
+ const bytesPerRow = 256;
+ const [buffer, mapping] = t.device.createBufferMapped({
+ size: rows * bytesPerRow,
+ usage: GPUBufferUsage.COPY_SRC,
+ });
+ switch (format) {
+ case 'bgra8unorm':
+ {
+ const data = new Uint8Array(mapping);
+ data.set(new Uint8Array([0x00, 0x00, 0x7f, 0xff]), 0); // red
+ data.set(new Uint8Array([0x00, 0x7f, 0x00, 0xff]), 4); // green
+ data.set(new Uint8Array([0x7f, 0x00, 0x00, 0xff]), 256 + 0); // blue
+ data.set(new Uint8Array([0x00, 0x7f, 0x7f, 0xff]), 256 + 4); // yellow
+ }
+ break;
+ case 'rgba16float':
+ {
+ // Untested!
+ const zero = 0x0000;
+ const half = 0x3800;
+ const one = 0x3c00;
+ const data = new DataView(mapping);
+ data.setUint16(0x000, half, false); // red
+ data.setUint16(0x002, zero, false);
+ data.setUint16(0x004, zero, false);
+ data.setUint16(0x008, one, false);
+ data.setUint16(0x010, zero, false); // green
+ data.setUint16(0x020, half, false);
+ data.setUint16(0x040, zero, false);
+ data.setUint16(0x080, one, false);
+ data.setUint16(0x100, zero, false); // blue
+ data.setUint16(0x102, zero, false);
+ data.setUint16(0x104, half, false);
+ data.setUint16(0x108, one, false);
+ data.setUint16(0x110, half, false); // yellow
+ data.setUint16(0x120, half, false);
+ data.setUint16(0x140, zero, false);
+ data.setUint16(0x180, one, false);
+ }
+ break;
+ }
+ buffer.unmap();
+
+ const texture = swapChain.getCurrentTexture();
+
+ const encoder = t.device.createCommandEncoder();
+ encoder.copyBufferToTexture({ buffer, bytesPerRow }, { texture }, [2, 2, 1]);
+ t.device.defaultQueue.submit([encoder.finish()]);
+ });
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_complex_bgra8unorm.html b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_complex_bgra8unorm.html
new file mode 100644
index 00000000000..1310543648e
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/canvas_complex_bgra8unorm.html
@@ -0,0 +1,18 @@
+<html class="reftest-wait">
+ <title>WebGPU canvas_complex_bgra8unorm</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <meta
+ name="assert"
+ content="WebGPU canvas should have correct orientation, components, scaling, filtering, color space"
+ />
+ <link rel="match" href="./ref/canvas_complex-ref.html" />
+
+ <canvas id="cvs" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+ <script src="/common/reftest-wait.js"></script>
+ <script type="module">
+ import { run } from './canvas_complex.js';
+ run('bgra8unorm');
+ // TODO: make a copy of this test for rgba16float
+ </script>
+</html>
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/gpu_ref_test.ts b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/gpu_ref_test.ts
new file mode 100644
index 00000000000..929f143b0ba
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/gpu_ref_test.ts
@@ -0,0 +1,23 @@
+import { assert } from '../../../common/framework/util/util.js';
+
+declare function takeScreenshotDelayed(ms: number): void;
+
+interface GPURefTest {
+ readonly device: GPUDevice;
+ readonly queue: GPUQueue;
+}
+
+export async function runRefTest(fn: (t: GPURefTest) => Promise<void>): Promise<void> {
+ assert(
+ typeof navigator !== 'undefined' && navigator.gpu !== undefined,
+ 'No WebGPU implementation found'
+ );
+
+ const adapter = await navigator.gpu.requestAdapter();
+ const device = await adapter.requestDevice();
+ const queue = device.defaultQueue;
+
+ await fn({ device, queue });
+
+ takeScreenshotDelayed(50);
+}
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/ref/canvas_clear-ref.html b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/ref/canvas_clear-ref.html
new file mode 100644
index 00000000000..2e078118627
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/ref/canvas_clear-ref.html
@@ -0,0 +1,12 @@
+<html>
+ <title>WebGPU canvas_clear (ref)</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <canvas id="myCanvas" width="10" height="10"></canvas>
+ <script>
+ var c = document.getElementById('myCanvas');
+ var ctx = c.getContext('2d');
+ ctx.fillStyle = '#00FF00';
+ ctx.fillRect(0, 0, c.width, c.height);
+ </script>
+</html>
diff --git a/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/ref/canvas_complex-ref.html b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/ref/canvas_complex-ref.html
new file mode 100644
index 00000000000..3d5b3b3376d
--- /dev/null
+++ b/chromium/third_party/webgpu-cts/src/src/webgpu/web-platform/reftests/ref/canvas_complex-ref.html
@@ -0,0 +1,17 @@
+<html>
+ <title>WebGPU canvas_complex (ref)</title>
+ <meta charset="utf-8" />
+ <link rel="help" href="https://gpuweb.github.io/gpuweb/" />
+ <canvas id="cvs" width="2" height="2" style="width: 20px; height: 20px;"></canvas>
+ <script>
+ const ctx = cvs.getContext('2d');
+ ctx.fillStyle = '#7F0000';
+ ctx.fillRect(0, 0, 1, 1);
+ ctx.fillStyle = '#007F00';
+ ctx.fillRect(1, 0, 1, 1);
+ ctx.fillStyle = '#00007F';
+ ctx.fillRect(0, 1, 1, 1);
+ ctx.fillStyle = '#7F7F00';
+ ctx.fillRect(1, 1, 1, 1);
+ </script>
+</html>
diff --git a/chromium/third_party/webgpu-cts/src/standalone/index.html b/chromium/third_party/webgpu-cts/src/standalone/index.html
index 7f59163f409..67e579b2809 100644
--- a/chromium/third_party/webgpu-cts/src/standalone/index.html
+++ b/chromium/third_party/webgpu-cts/src/standalone/index.html
@@ -1,6 +1,6 @@
<html>
<head>
- <title></title>
+ <title>WebGPU CTS</title>
<link
id="favicon"
rel="shortcut icon"
@@ -39,10 +39,15 @@
.nodeheader {
display: flex;
width: 100%;
- padding: 1px 2px 1px 1px;
+ padding: 0px 2px 0px 1px;
}
- .noderun,
+ .nodeheader:hover {
+ background: rgba(0, 0, 0, 0.1);
+ }
+ .subtreerun,
+ .leafrun,
.nodelink,
+ .collapsebtn,
.testcaselogbtn {
display: inline-block;
flex-shrink: 0;
@@ -54,18 +59,22 @@
border: 1px solid #888;
}
@media (pointer: fine) {
- .noderun,
+ .subtreerun,
+ .leafrun,
.nodelink,
+ .collapsebtn,
.testcaselogbtn {
flex-basis: 24px;
border-radius: 4px;
width: 24px;
- height: 24px;
+ height: 18px;
}
}
@media (pointer: coarse) {
- .noderun,
+ .subtreerun,
+ .leafrun,
.nodelink,
+ .collapsebtn,
.testcaselogbtn {
flex-basis: 36px;
border-radius: 6px;
@@ -73,7 +82,10 @@
height: 36px;
}
}
- .noderun {
+ .subtreerun {
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJAQMAAADaX5RTAAAABlBMVEUAAAAAAAClZ7nPAAAAAXRSTlMAQObYZgAAAB5JREFUCNdjOMDAsIGBoYeBoZmBoaEBRPaARQ4wAABTfwX/l/WQvgAAAABJRU5ErkJggg==);
+ }
+ .leafrun {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAANklEQVQoU2NkYGD4zwABjFAagwJJwBTBJDEUY1OEoRifIrhiYhSBHYvuJnSHM5LtJry+wxlOAGPTCQmAB/WwAAAAAElFTkSuQmCC);
}
.nodelink {
@@ -83,12 +95,21 @@
flex: 10 0 4em;
}
.nodename {
- user-select: all;
- word-break: break-word;
- }
- @media only screen and (max-width: 600px) {
- /* TODO: make the uninteresting part of the name be really small or something, such that it gets
- * auto selected but doesn't take space. */
+ margin: 0 0.5em;
+ padding: 2px;
+ }
+ .leafname {
+ background: black;
+ color: white;
+ }
+ .nodequery {
+ background: transparent;
+ border: none;
+ padding: 2px;
+ margin: 0 0.5em;
+ color: #999;
+ width: 50%;
+ max-width: 50%;
}
.nodedescription {
margin: 0;
@@ -101,7 +122,20 @@
margin: 0px;
border-width: 1px 0 0 1px;
border-style: solid;
- border-color: gray;
+ border-color: #ddd;
+ }
+ .subtree:hover {
+ border-left-color: #000;
+ }
+ .subtree.multifile > .subtreechildren > .subtree.multitest,
+ .subtree.multifile > .subtreechildren > .subtree.multicase {
+ border-width: 2px 0 0 1px;
+ border-color: #55f;
+ }
+ .subtree.multitest > .subtreechildren > .subtree.multicase,
+ .subtree.multitest > .subtreechildren > .testcase {
+ border-width: 2px 0 0 1px;
+ border-color: #bbf;
}
.subtreechildren {
margin-left: 6px;
@@ -116,7 +150,7 @@
background: white;
}
.testcase[data-status='fail'] {
- background: #fcc;
+ background: #fdd;
}
.testcase[data-status='warn'] {
background: #ffb;
@@ -125,7 +159,7 @@
background: #cfc;
}
.testcase[data-status='skip'] {
- background: #ccc;
+ background: #eee;
}
.testcasetime {
white-space: nowrap;
@@ -174,18 +208,14 @@
}
}
</style>
- <script>
- if (!window.location.search) {
- window.location += '?runnow=0&worker=0&debug=0&q=webgpu:';
- }
- </script>
</head>
<body>
<h1>WebGPU Conformance Test Suite</h1>
+ <input type="checkbox" id="expandall" /><label for="expandall">Expand All</label>
<div id="info"></div>
<div id="resultsVis"></div>
- <textarea id="resultsJSON"></textarea>
+ <textarea id="resultsJSON" spellcheck="false"></textarea>
<script type="module" src="../out/common/runtime/standalone.js"></script>
</body>
diff --git a/chromium/third_party/webgpu-cts/src/tools/gen_version b/chromium/third_party/webgpu-cts/src/tools/gen_version
index a8194e0f9af..fad05631769 100755
--- a/chromium/third_party/webgpu-cts/src/tools/gen_version
+++ b/chromium/third_party/webgpu-cts/src/tools/gen_version
@@ -3,7 +3,7 @@
// Get the current git hash, and save (overwrite) it into out/framework/version.js
// so it can be read when running inside the browser.
-// tslint:disable: no-console
+/* eslint-disable no-console */
require('../src/common/tools/setup-ts-in-node.js');
const fs = require('fs');
diff --git a/chromium/third_party/webgpu-cts/src/tsconfig.json b/chromium/third_party/webgpu-cts/src/tsconfig.json
index 4b4005c2e2b..7c7ea043d51 100644
--- a/chromium/third_party/webgpu-cts/src/tsconfig.json
+++ b/chromium/third_party/webgpu-cts/src/tsconfig.json
@@ -3,22 +3,17 @@
"compilerOptions": {
"lib": ["dom", "es2016"],
"module": "esnext",
-
/* Output options */
"noEmit": true,
-
/* Strict type-checking options */
"allowJs": false,
"strict": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
-
/* Module Options */
"moduleResolution": "node",
- "esModuleInterop": false,
+ "esModuleInterop": false
},
- "include": [
- "src/**/*.ts",
- ],
+ "include": ["src/**/*.ts"]
}
diff --git a/chromium/third_party/webgpu-cts/src/tslint.json b/chromium/third_party/webgpu-cts/src/tslint.json
deleted file mode 100644
index 9c3e591cba9..00000000000
--- a/chromium/third_party/webgpu-cts/src/tslint.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "extends": "gts/tslint.json",
- "rules": {
- "ban": [
- true,
- {
- "name": "setTimeout",
- "message": "WPT (Web Platform Tests) doesn't allow setTimeout."
- }
- ],
- "linebreak-style": [
- true,
- "LF"
- ],
- "no-console": [
- true
- ],
- "ordered-imports": [
- true,
- {
- "grouped-imports": true,
- "named-imports-order": "lowercase-last"
- }
- ],
- "typedef": [
- true,
- "call-signature",
- "parameter",
- "property-declaration"
- ],
- "no-inferrable-types": false
- },
- "linterOptions": {
- "exclude": [
- "**/*.json"
- ]
- }
-}
diff --git a/chromium/third_party/webgpu-cts/src/yarn.lock b/chromium/third_party/webgpu-cts/src/yarn.lock
deleted file mode 100644
index dd28454d3c8..00000000000
--- a/chromium/third_party/webgpu-cts/src/yarn.lock
+++ /dev/null
@@ -1,3557 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"@babel/cli@^7.7.7":
- version "7.8.4"
- resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.8.4.tgz#505fb053721a98777b2b175323ea4f090b7d3c1c"
- integrity sha512-XXLgAm6LBbaNxaGhMAznXXaxtCWfuv6PIDJ9Alsy9JYTOh+j2jJz+L/162kkfU1j/pTSxK1xGmlwI4pdIMkoag==
- dependencies:
- commander "^4.0.1"
- convert-source-map "^1.1.0"
- fs-readdir-recursive "^1.1.0"
- glob "^7.0.0"
- lodash "^4.17.13"
- make-dir "^2.1.0"
- slash "^2.0.0"
- source-map "^0.5.0"
- optionalDependencies:
- chokidar "^2.1.8"
-
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e"
- integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==
- dependencies:
- "@babel/highlight" "^7.8.3"
-
-"@babel/core@^7.7.7":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e"
- integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==
- dependencies:
- "@babel/code-frame" "^7.8.3"
- "@babel/generator" "^7.9.0"
- "@babel/helper-module-transforms" "^7.9.0"
- "@babel/helpers" "^7.9.0"
- "@babel/parser" "^7.9.0"
- "@babel/template" "^7.8.6"
- "@babel/traverse" "^7.9.0"
- "@babel/types" "^7.9.0"
- convert-source-map "^1.7.0"
- debug "^4.1.0"
- gensync "^1.0.0-beta.1"
- json5 "^2.1.2"
- lodash "^4.17.13"
- resolve "^1.3.2"
- semver "^5.4.1"
- source-map "^0.5.0"
-
-"@babel/generator@^7.9.0":
- version "7.9.4"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.4.tgz#12441e90c3b3c4159cdecf312075bf1a8ce2dbce"
- integrity sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==
- dependencies:
- "@babel/types" "^7.9.0"
- jsesc "^2.5.1"
- lodash "^4.17.13"
- source-map "^0.5.0"
-
-"@babel/helper-create-class-features-plugin@^7.8.3":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.6.tgz#243a5b46e2f8f0f674dc1387631eb6b28b851de0"
- integrity sha512-klTBDdsr+VFFqaDHm5rR69OpEQtO2Qv8ECxHS1mNhJJvaHArR6a1xTf5K/eZW7eZpJbhCx3NW1Yt/sKsLXLblg==
- dependencies:
- "@babel/helper-function-name" "^7.8.3"
- "@babel/helper-member-expression-to-functions" "^7.8.3"
- "@babel/helper-optimise-call-expression" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/helper-replace-supers" "^7.8.6"
- "@babel/helper-split-export-declaration" "^7.8.3"
-
-"@babel/helper-function-name@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca"
- integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==
- dependencies:
- "@babel/helper-get-function-arity" "^7.8.3"
- "@babel/template" "^7.8.3"
- "@babel/types" "^7.8.3"
-
-"@babel/helper-get-function-arity@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5"
- integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==
- dependencies:
- "@babel/types" "^7.8.3"
-
-"@babel/helper-member-expression-to-functions@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c"
- integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==
- dependencies:
- "@babel/types" "^7.8.3"
-
-"@babel/helper-module-imports@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498"
- integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==
- dependencies:
- "@babel/types" "^7.8.3"
-
-"@babel/helper-module-transforms@^7.9.0":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5"
- integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==
- dependencies:
- "@babel/helper-module-imports" "^7.8.3"
- "@babel/helper-replace-supers" "^7.8.6"
- "@babel/helper-simple-access" "^7.8.3"
- "@babel/helper-split-export-declaration" "^7.8.3"
- "@babel/template" "^7.8.6"
- "@babel/types" "^7.9.0"
- lodash "^4.17.13"
-
-"@babel/helper-optimise-call-expression@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9"
- integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==
- dependencies:
- "@babel/types" "^7.8.3"
-
-"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670"
- integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==
-
-"@babel/helper-replace-supers@^7.8.6":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8"
- integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==
- dependencies:
- "@babel/helper-member-expression-to-functions" "^7.8.3"
- "@babel/helper-optimise-call-expression" "^7.8.3"
- "@babel/traverse" "^7.8.6"
- "@babel/types" "^7.8.6"
-
-"@babel/helper-simple-access@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae"
- integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==
- dependencies:
- "@babel/template" "^7.8.3"
- "@babel/types" "^7.8.3"
-
-"@babel/helper-split-export-declaration@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9"
- integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==
- dependencies:
- "@babel/types" "^7.8.3"
-
-"@babel/helper-validator-identifier@^7.9.0":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed"
- integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==
-
-"@babel/helpers@^7.9.0":
- version "7.9.2"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f"
- integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==
- dependencies:
- "@babel/template" "^7.8.3"
- "@babel/traverse" "^7.9.0"
- "@babel/types" "^7.9.0"
-
-"@babel/highlight@^7.8.3":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079"
- integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==
- dependencies:
- "@babel/helper-validator-identifier" "^7.9.0"
- chalk "^2.0.0"
- js-tokens "^4.0.0"
-
-"@babel/parser@^7.8.6", "@babel/parser@^7.9.0":
- version "7.9.4"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8"
- integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==
-
-"@babel/plugin-proposal-class-properties@^7.7.4":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e"
- integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==
- dependencies:
- "@babel/helper-create-class-features-plugin" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
-
-"@babel/plugin-syntax-dynamic-import@^7.7.4":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
- integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.0"
-
-"@babel/plugin-syntax-import-meta@^7.7.4":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.8.3.tgz#230afff79d3ccc215b5944b438e4e266daf3d84d"
- integrity sha512-vYiGd4wQ9gx0Lngb7+bPCwQXGK/PR6FeTIJ+TIOlq+OfOKG/kCAOO2+IBac3oMM9qV7/fU76hfcqxUaLKZf1hQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
-
-"@babel/plugin-syntax-typescript@^7.3.3", "@babel/plugin-syntax-typescript@^7.8.3":
- version "7.8.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz#c1f659dda97711a569cef75275f7e15dcaa6cabc"
- integrity sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
-
-"@babel/plugin-transform-typescript@^7.9.0":
- version "7.9.4"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.4.tgz#4bb4dde4f10bbf2d787fce9707fb09b483e33359"
- integrity sha512-yeWeUkKx2auDbSxRe8MusAG+n4m9BFY/v+lPjmQDgOFX5qnySkUY5oXzkp6FwPdsYqnKay6lorXYdC0n3bZO7w==
- dependencies:
- "@babel/helper-create-class-features-plugin" "^7.8.3"
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/plugin-syntax-typescript" "^7.8.3"
-
-"@babel/preset-typescript@^7.7.7":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz#87705a72b1f0d59df21c179f7c3d2ef4b16ce192"
- integrity sha512-S4cueFnGrIbvYJgwsVFKdvOmpiL0XGw9MFW9D0vgRys5g36PBhZRL8NX8Gr2akz8XRtzq6HuDXPD/1nniagNUg==
- dependencies:
- "@babel/helper-plugin-utils" "^7.8.3"
- "@babel/plugin-transform-typescript" "^7.9.0"
-
-"@babel/template@^7.8.3", "@babel/template@^7.8.6":
- version "7.8.6"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
- integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==
- dependencies:
- "@babel/code-frame" "^7.8.3"
- "@babel/parser" "^7.8.6"
- "@babel/types" "^7.8.6"
-
-"@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892"
- integrity sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==
- dependencies:
- "@babel/code-frame" "^7.8.3"
- "@babel/generator" "^7.9.0"
- "@babel/helper-function-name" "^7.8.3"
- "@babel/helper-split-export-declaration" "^7.8.3"
- "@babel/parser" "^7.9.0"
- "@babel/types" "^7.9.0"
- debug "^4.1.0"
- globals "^11.1.0"
- lodash "^4.17.13"
-
-"@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0":
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5"
- integrity sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==
- dependencies:
- "@babel/helper-validator-identifier" "^7.9.0"
- lodash "^4.17.13"
- to-fast-properties "^2.0.0"
-
-"@nodelib/fs.scandir@2.1.3":
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
- integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==
- dependencies:
- "@nodelib/fs.stat" "2.0.3"
- run-parallel "^1.1.9"
-
-"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3"
- integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==
-
-"@nodelib/fs.walk@^1.2.3":
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976"
- integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==
- dependencies:
- "@nodelib/fs.scandir" "2.1.3"
- fastq "^1.6.0"
-
-"@sindresorhus/is@^0.14.0":
- version "0.14.0"
- resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
- integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
-
-"@szmarczak/http-timer@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
- integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==
- dependencies:
- defer-to-connect "^1.0.1"
-
-"@types/color-name@^1.1.1":
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
- integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
-
-"@types/jquery@^3.3.30":
- version "3.3.34"
- resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.34.tgz#0d3b94057063d3854adaeb579652048fec07ba6c"
- integrity sha512-lW9vsVL53Xu/Nj4gi2hNmHGc4u3KKghjqTkAlO0kF5GIOPxbqqnQpgqJBzmn3yXLrPqHb6cmNJ6URnS23Vtvbg==
- dependencies:
- "@types/sizzle" "*"
-
-"@types/node@^13.1.2":
- version "13.11.0"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b"
- integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==
-
-"@types/offscreencanvas@^2019.6.1":
- version "2019.6.2"
- resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.6.2.tgz#9bd6f5a9a70459ec0ce7ecedf45d63e38d744c86"
- integrity sha512-ndVeLKDF10p4hZswi0KKSUWAmNoTcgz8LUPiIIPeT3qD8bTaYe0pXyuyQ21+DmGRMkT8orxiISm4O+YpMLCDBw==
- dependencies:
- "@types/webgl2" "*"
-
-"@types/sizzle@*":
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47"
- integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==
-
-"@types/webgl2@*":
- version "0.0.5"
- resolved "https://registry.yarnpkg.com/@types/webgl2/-/webgl2-0.0.5.tgz#dd925e20ab8ace80eb4b1e46fda5b109c508fb0d"
- integrity sha512-oGaKsBbxQOY5+aJFV3KECDhGaXt+yZJt2y/OZsnQGLRkH6Fvr7rv4pCt3SRH1somIHfej/c4u7NSpCyd9x+1Ow==
-
-"@webgpu/glslang@^0.0.15":
- version "0.0.15"
- resolved "https://registry.yarnpkg.com/@webgpu/glslang/-/glslang-0.0.15.tgz#f5ccaf6015241e6175f4b90906b053f88483d1f2"
- integrity sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q==
-
-"@webgpu/types@0.0.22":
- version "0.0.22"
- resolved "https://registry.yarnpkg.com/@webgpu/types/-/types-0.0.22.tgz#320ccd7a8560061b5a6a2db7d5965b861bded004"
- integrity sha512-qT2NUglkiWcnqmgyrqDU79F7FdQXQX4h1TEALWIY7od2gI+1FcbKnAPvb6qW9XfGEqGaxOFVliotY5U/ewdQAA==
-
-abbrev@1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
- integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-
-ansi-align@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
- integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==
- dependencies:
- string-width "^3.0.0"
-
-ansi-escapes@^4.2.1:
- version "4.3.1"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61"
- integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==
- dependencies:
- type-fest "^0.11.0"
-
-ansi-regex@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
- integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-
-ansi-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
- integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
-
-ansi-regex@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
- integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
-
-ansi-regex@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
- integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
-
-ansi-styles@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
- integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
-
-ansi-styles@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
- integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
- dependencies:
- color-convert "^1.9.0"
-
-ansi-styles@^4.1.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
- integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==
- dependencies:
- "@types/color-name" "^1.1.1"
- color-convert "^2.0.1"
-
-anymatch@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
- integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==
- dependencies:
- micromatch "^3.1.4"
- normalize-path "^2.1.1"
-
-arg@^4.1.0:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
- integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
-
-argparse@^1.0.7:
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
- integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
- dependencies:
- sprintf-js "~1.0.2"
-
-arr-diff@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
- integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
-
-arr-flatten@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
- integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
-
-arr-union@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
- integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
-
-array-find-index@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
- integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
-
-array-unique@^0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
- integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
-
-arrify@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
- integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
-
-assign-symbols@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
- integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
-
-async-each@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
- integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
-
-async@^1.5.2, async@~1.5.2:
- version "1.5.2"
- resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
- integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
-
-async@^2.6.1, async@^2.6.2:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
- integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
- dependencies:
- lodash "^4.17.14"
-
-atob@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
- integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
-
-babel-plugin-add-header-comment@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/babel-plugin-add-header-comment/-/babel-plugin-add-header-comment-1.0.3.tgz#511c4901062640d5a480b4ac3edd6944195850ec"
- integrity sha1-URxJAQYmQNWkgLSsPt1pRBlYUOw=
-
-babel-plugin-const-enum@^0.0.5:
- version "0.0.5"
- resolved "https://registry.yarnpkg.com/babel-plugin-const-enum/-/babel-plugin-const-enum-0.0.5.tgz#1e807d52572bb193a0df60130ed06b07a59b04b3"
- integrity sha512-EAOnmHcsn+hbMS1yYZoc0jBemNbRR+NATO9RrLJF/1iXJbDTEaOwH0Y7XPb7vvWc5C/nHp7v8WhAsHW7UjxYQA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.0.0"
- "@babel/plugin-syntax-typescript" "^7.3.3"
-
-balanced-match@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
- integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
-
-base@^0.11.1:
- version "0.11.2"
- resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
- integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
- dependencies:
- cache-base "^1.0.1"
- class-utils "^0.3.5"
- component-emitter "^1.2.1"
- define-property "^1.0.0"
- isobject "^3.0.1"
- mixin-deep "^1.2.0"
- pascalcase "^0.1.1"
-
-binary-extensions@^1.0.0:
- version "1.13.1"
- resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
- integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
-
-bindings@^1.5.0:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
- integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
- dependencies:
- file-uri-to-path "1.0.0"
-
-boxen@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb"
- integrity sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==
- dependencies:
- ansi-align "^3.0.0"
- camelcase "^5.3.1"
- chalk "^2.4.2"
- cli-boxes "^2.2.0"
- string-width "^3.0.0"
- term-size "^1.2.0"
- type-fest "^0.3.0"
- widest-line "^2.0.0"
-
-brace-expansion@^1.1.7:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
- integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-braces@^2.3.1, braces@^2.3.2:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
- integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
- dependencies:
- arr-flatten "^1.1.0"
- array-unique "^0.3.2"
- extend-shallow "^2.0.1"
- fill-range "^4.0.0"
- isobject "^3.0.1"
- repeat-element "^1.1.2"
- snapdragon "^0.8.1"
- snapdragon-node "^2.0.1"
- split-string "^3.0.2"
- to-regex "^3.0.1"
-
-braces@^3.0.1:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
- integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
- dependencies:
- fill-range "^7.0.1"
-
-buffer-from@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
- integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-
-builtin-modules@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
- integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
-
-cache-base@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
- integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
- dependencies:
- collection-visit "^1.0.0"
- component-emitter "^1.2.1"
- get-value "^2.0.6"
- has-value "^1.0.0"
- isobject "^3.0.1"
- set-value "^2.0.0"
- to-object-path "^0.3.0"
- union-value "^1.0.0"
- unset-value "^1.0.0"
-
-cacheable-request@^6.0.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912"
- integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==
- dependencies:
- clone-response "^1.0.2"
- get-stream "^5.1.0"
- http-cache-semantics "^4.0.0"
- keyv "^3.0.0"
- lowercase-keys "^2.0.0"
- normalize-url "^4.1.0"
- responselike "^1.0.2"
-
-camelcase-keys@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
- integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc=
- dependencies:
- camelcase "^2.0.0"
- map-obj "^1.0.0"
-
-camelcase-keys@^4.0.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77"
- integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=
- dependencies:
- camelcase "^4.1.0"
- map-obj "^2.0.0"
- quick-lru "^1.0.0"
-
-camelcase@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
- integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
-
-camelcase@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
- integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
-
-camelcase@^5.3.1:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
- integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-
-chalk@^1.1.1:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
- integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
- dependencies:
- ansi-styles "^2.2.1"
- escape-string-regexp "^1.0.2"
- has-ansi "^2.0.0"
- strip-ansi "^3.0.0"
- supports-color "^2.0.0"
-
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.2, chalk@~2.4.1:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
- integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
-chalk@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
- integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
-chardet@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
- integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
-
-chokidar@^2.0.4, chokidar@^2.1.8:
- version "2.1.8"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
- integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
- dependencies:
- anymatch "^2.0.0"
- async-each "^1.0.1"
- braces "^2.3.2"
- glob-parent "^3.1.0"
- inherits "^2.0.3"
- is-binary-path "^1.0.0"
- is-glob "^4.0.0"
- normalize-path "^3.0.0"
- path-is-absolute "^1.0.0"
- readdirp "^2.2.1"
- upath "^1.1.1"
- optionalDependencies:
- fsevents "^1.2.7"
-
-ci-info@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
- integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
-
-clang-format@^1.3.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/clang-format/-/clang-format-1.4.0.tgz#1ee2f10637eb5bb0bd7d0b82c949af68e848367e"
- integrity sha512-NrdyUnHJOGvMa60vbWk7GJTvOdhibj3uK5C0FlwdNG4301OUvqEJTFce9I9x8qw2odBbIVrJ+9xbsFS3a4FbDA==
- dependencies:
- async "^1.5.2"
- glob "^7.0.0"
- resolve "^1.1.6"
-
-class-utils@^0.3.5:
- version "0.3.6"
- resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
- integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
- dependencies:
- arr-union "^3.1.0"
- define-property "^0.2.5"
- isobject "^3.0.0"
- static-extend "^0.1.1"
-
-cli-boxes@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
- integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
-
-cli-cursor@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
- integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
- dependencies:
- restore-cursor "^3.1.0"
-
-cli-width@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
- integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
-
-cliui@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
- integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
- dependencies:
- string-width "^2.1.1"
- strip-ansi "^4.0.0"
- wrap-ansi "^2.0.0"
-
-clone-response@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
- integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
- dependencies:
- mimic-response "^1.0.0"
-
-code-point-at@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
- integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-
-coffeescript@~1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.10.0.tgz#e7aa8301917ef621b35d8a39f348dcdd1db7e33e"
- integrity sha1-56qDAZF+9iGzXYo580jc3R234z4=
-
-collection-visit@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
- integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=
- dependencies:
- map-visit "^1.0.0"
- object-visit "^1.0.0"
-
-color-convert@^1.9.0:
- version "1.9.3"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
- integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
- dependencies:
- color-name "1.1.3"
-
-color-convert@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
- integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
- dependencies:
- color-name "~1.1.4"
-
-color-name@1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
- integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-
-color-name@~1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
- integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-colors@1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
- integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=
-
-colors@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
- integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM=
-
-commander@^2.12.1, commander@^2.19.0:
- version "2.20.3"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
- integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
-
-commander@^4.0.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
- integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
-
-commandpost@^1.0.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/commandpost/-/commandpost-1.4.0.tgz#89218012089dfc9b67a337ba162f15c88e0f1048"
- integrity sha512-aE2Y4MTFJ870NuB/+2z1cXBhSBBzRydVVjzhFC4gtenEhpnj15yu0qptWGJsO9YGrcPZ3ezX8AWb1VA391MKpQ==
-
-component-emitter@^1.2.1:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
- integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
-
-concat-map@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
- integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-
-configstore@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7"
- integrity sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==
- dependencies:
- dot-prop "^4.1.0"
- graceful-fs "^4.1.2"
- make-dir "^1.0.0"
- unique-string "^1.0.0"
- write-file-atomic "^2.0.0"
- xdg-basedir "^3.0.0"
-
-convert-source-map@^1.1.0, convert-source-map@^1.7.0:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
- integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
- dependencies:
- safe-buffer "~5.1.1"
-
-copy-descriptor@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
- integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
-
-core-util-is@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
- integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-
-corser@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/corser/-/corser-2.0.1.tgz#8eda252ecaab5840dcd975ceb90d9370c819ff87"
- integrity sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=
-
-cross-spawn@^5.0.1:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
- integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
- dependencies:
- lru-cache "^4.0.1"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-crypto-random-string@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
- integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=
-
-csproj2ts@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/csproj2ts/-/csproj2ts-1.1.0.tgz#e6a8c20464b0031a16a219431ce5e4017fc780d5"
- integrity sha512-sk0RTT51t4lUNQ7UfZrqjQx7q4g0m3iwNA6mvyh7gLsgQYvwKzfdyoAgicC9GqJvkoIkU0UmndV9c7VZ8pJ45Q==
- dependencies:
- es6-promise "^4.1.1"
- lodash "^4.17.4"
- semver "^5.4.1"
- xml2js "^0.4.19"
-
-currently-unhandled@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
- integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
- dependencies:
- array-find-index "^1.0.1"
-
-dateformat@~1.0.12:
- version "1.0.12"
- resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9"
- integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=
- dependencies:
- get-stdin "^4.0.1"
- meow "^3.3.0"
-
-debug@^2.2.0, debug@^2.3.3:
- version "2.6.9"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
- integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
- dependencies:
- ms "2.0.0"
-
-debug@^3.0.0, debug@^3.1.1:
- version "3.2.6"
- resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
- integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
- dependencies:
- ms "^2.1.1"
-
-debug@^4.1.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
- integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
- dependencies:
- ms "^2.1.1"
-
-decamelize-keys@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
- integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=
- dependencies:
- decamelize "^1.1.0"
- map-obj "^1.0.0"
-
-decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
- integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
-
-decode-uri-component@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
- integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
-
-decompress-response@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
- integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=
- dependencies:
- mimic-response "^1.0.0"
-
-deep-extend@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
- integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
-
-defer-to-connect@^1.0.1:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
- integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
-
-define-property@^0.2.5:
- version "0.2.5"
- resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
- integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=
- dependencies:
- is-descriptor "^0.1.0"
-
-define-property@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
- integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY=
- dependencies:
- is-descriptor "^1.0.0"
-
-define-property@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d"
- integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
- dependencies:
- is-descriptor "^1.0.2"
- isobject "^3.0.1"
-
-detect-indent@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
- integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg=
- dependencies:
- repeating "^2.0.0"
-
-detect-newline@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
- integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
-
-diff@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
- integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
-
-divhide@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/divhide/-/divhide-2.0.1.tgz#8c7b026f7ff0e975803cbb965aeca114de82d9bb"
- integrity sha1-jHsCb3/w6XWAPLuWWuyhFN6C2bs=
- dependencies:
- lodash "=3.9.3"
-
-dot-prop@^4.1.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
- integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==
- dependencies:
- is-obj "^1.0.0"
-
-duplexer3@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
- integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
-
-ecstatic@^3.0.0:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.3.2.tgz#6d1dd49814d00594682c652adb66076a69d46c48"
- integrity sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==
- dependencies:
- he "^1.1.1"
- mime "^1.6.0"
- minimist "^1.1.0"
- url-join "^2.0.5"
-
-editorconfig@^0.15.0:
- version "0.15.3"
- resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
- integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==
- dependencies:
- commander "^2.19.0"
- lru-cache "^4.1.5"
- semver "^5.6.0"
- sigmund "^1.0.1"
-
-emoji-regex@^7.0.1:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
- integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
-
-emoji-regex@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
- integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
-
-end-of-stream@^1.1.0:
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
- integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
- dependencies:
- once "^1.4.0"
-
-error-ex@^1.2.0, error-ex@^1.3.1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
- integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
- dependencies:
- is-arrayish "^0.2.1"
-
-es6-promise@^4.1.1:
- version "4.2.8"
- resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
- integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
-
-es6-promise@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-0.1.2.tgz#f112c29fea5a0998539fcb6a2fd21443d28f05f7"
- integrity sha1-8RLCn+paCZhTn8tqL9IUQ9KPBfc=
-
-escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
- integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
-
-esprima@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
- integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-
-eventemitter2@~0.4.13:
- version "0.4.14"
- resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab"
- integrity sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=
-
-eventemitter3@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
- integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
-
-execa@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
- integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=
- dependencies:
- cross-spawn "^5.0.1"
- get-stream "^3.0.0"
- is-stream "^1.1.0"
- npm-run-path "^2.0.0"
- p-finally "^1.0.0"
- signal-exit "^3.0.0"
- strip-eof "^1.0.0"
-
-exit@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
- integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
-
-expand-brackets@^2.1.4:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
- integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI=
- dependencies:
- debug "^2.3.3"
- define-property "^0.2.5"
- extend-shallow "^2.0.1"
- posix-character-classes "^0.1.0"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.1"
-
-extend-shallow@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
- integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=
- dependencies:
- is-extendable "^0.1.0"
-
-extend-shallow@^3.0.0, extend-shallow@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8"
- integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=
- dependencies:
- assign-symbols "^1.0.0"
- is-extendable "^1.0.1"
-
-external-editor@^3.0.3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
- integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
- dependencies:
- chardet "^0.7.0"
- iconv-lite "^0.4.24"
- tmp "^0.0.33"
-
-extglob@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
- integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
- dependencies:
- array-unique "^0.3.2"
- define-property "^1.0.0"
- expand-brackets "^2.1.4"
- extend-shallow "^2.0.1"
- fragment-cache "^0.2.1"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.1"
-
-fast-glob@^3.1.1:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d"
- integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==
- dependencies:
- "@nodelib/fs.stat" "^2.0.2"
- "@nodelib/fs.walk" "^1.2.3"
- glob-parent "^5.1.0"
- merge2 "^1.3.0"
- micromatch "^4.0.2"
- picomatch "^2.2.1"
-
-fastq@^1.6.0:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.7.0.tgz#fcd79a08c5bd7ec5b55cd3f5c4720db551929801"
- integrity sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ==
- dependencies:
- reusify "^1.0.4"
-
-figures@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
- integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
- dependencies:
- escape-string-regexp "^1.0.5"
-
-file-sync-cmp@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz#a5e7a8ffbfa493b43b923bbd4ca89a53b63b612b"
- integrity sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=
-
-file-uri-to-path@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
- integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
-
-fill-range@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
- integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=
- dependencies:
- extend-shallow "^2.0.1"
- is-number "^3.0.0"
- repeat-string "^1.6.1"
- to-regex-range "^2.1.0"
-
-fill-range@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
- integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
- dependencies:
- to-regex-range "^5.0.1"
-
-find-up@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
- integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
- dependencies:
- path-exists "^2.0.0"
- pinkie-promise "^2.0.0"
-
-find-up@^2.0.0, find-up@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
- integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
- dependencies:
- locate-path "^2.0.0"
-
-findup-sync@~0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16"
- integrity sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=
- dependencies:
- glob "~5.0.0"
-
-follow-redirects@^1.0.0:
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.11.0.tgz#afa14f08ba12a52963140fe43212658897bc0ecb"
- integrity sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==
- dependencies:
- debug "^3.0.0"
-
-for-in@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
- integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
-
-fragment-cache@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
- integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=
- dependencies:
- map-cache "^0.2.2"
-
-fs-readdir-recursive@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27"
- integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==
-
-fs.realpath@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
- integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-
-fsevents@^1.2.7:
- version "1.2.12"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.12.tgz#db7e0d8ec3b0b45724fd4d83d43554a8f1f0de5c"
- integrity sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==
- dependencies:
- bindings "^1.5.0"
- nan "^2.12.1"
-
-gensync@^1.0.0-beta.1:
- version "1.0.0-beta.1"
- resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
- integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==
-
-get-caller-file@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
- integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
-
-get-stdin@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
- integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
-
-get-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
- integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
-
-get-stream@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
- integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
- dependencies:
- pump "^3.0.0"
-
-get-stream@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9"
- integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==
- dependencies:
- pump "^3.0.0"
-
-get-value@^2.0.3, get-value@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
- integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
-
-getobject@~0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c"
- integrity sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=
-
-glob-parent@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
- integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=
- dependencies:
- is-glob "^3.1.0"
- path-dirname "^1.0.0"
-
-glob-parent@^5.1.0:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
- integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
- dependencies:
- is-glob "^4.0.1"
-
-glob@^7.0.0, glob@^7.1.1, glob@^7.1.3:
- version "7.1.6"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
- integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.4"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-glob@~5.0.0:
- version "5.0.15"
- resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
- integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=
- dependencies:
- inflight "^1.0.4"
- inherits "2"
- minimatch "2 || 3"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-glob@~7.0.0:
- version "7.0.6"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a"
- integrity sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.2"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-global-dirs@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
- integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=
- dependencies:
- ini "^1.3.4"
-
-globals@^11.1.0:
- version "11.12.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
- integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-
-got@^9.6.0:
- version "9.6.0"
- resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
- integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==
- dependencies:
- "@sindresorhus/is" "^0.14.0"
- "@szmarczak/http-timer" "^1.1.2"
- cacheable-request "^6.0.0"
- decompress-response "^3.3.0"
- duplexer3 "^0.1.4"
- get-stream "^4.1.0"
- lowercase-keys "^1.0.1"
- mimic-response "^1.0.1"
- p-cancelable "^1.0.0"
- to-readable-stream "^1.0.0"
- url-parse-lax "^3.0.0"
-
-graceful-fs@^4.1.11, graceful-fs@^4.1.2:
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
- integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
-
-grunt-babel@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/grunt-babel/-/grunt-babel-8.0.0.tgz#92ef63aafadf938c488dc2f926ac9846e0c93d1b"
- integrity sha512-WuiZFvGzcyzlEoPIcY1snI234ydDWeWWV5bpnB7PZsOLHcDsxWKnrR1rMWEUsbdVPPjvIirwFNsuo4CbJmsdFQ==
-
-grunt-cli@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.2.0.tgz#562b119ebb069ddb464ace2845501be97b35b6a8"
- integrity sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=
- dependencies:
- findup-sync "~0.3.0"
- grunt-known-options "~1.1.0"
- nopt "~3.0.6"
- resolve "~1.1.0"
-
-grunt-contrib-clean@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/grunt-contrib-clean/-/grunt-contrib-clean-2.0.0.tgz#3be7ca480da4b740aa5e9d863e2f7e8b24f8a68b"
- integrity sha512-g5ZD3ORk6gMa5ugZosLDQl3dZO7cI3R14U75hTM+dVLVxdMNJCPVmwf9OUt4v4eWgpKKWWoVK9DZc1amJp4nQw==
- dependencies:
- async "^2.6.1"
- rimraf "^2.6.2"
-
-grunt-contrib-copy@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz#7060c6581e904b8ab0d00f076e0a8f6e3e7c3573"
- integrity sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=
- dependencies:
- chalk "^1.1.1"
- file-sync-cmp "^0.1.0"
-
-grunt-http-server@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/grunt-http-server/-/grunt-http-server-2.1.0.tgz#d43d9f8d2ac3c16f3cc9e9199751295d09413b69"
- integrity sha512-kv1qgucbRG0XthXu/uyoi15mYeF8W2QDODPurKE9zuRaJPhpuglOkHThGmqKdmJU38CEqc/Q49+Z51VhGFsN8g==
- dependencies:
- divhide "2.0.1"
- http-server "0.11.1"
- lodash "4.17.5"
- opener "1.4.3"
- showdown "1.8.6"
-
-grunt-known-options@~1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/grunt-known-options/-/grunt-known-options-1.1.1.tgz#6cc088107bd0219dc5d3e57d91923f469059804d"
- integrity sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==
-
-grunt-legacy-log-utils@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz#d2f442c7c0150065d9004b08fd7410d37519194e"
- integrity sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==
- dependencies:
- chalk "~2.4.1"
- lodash "~4.17.10"
-
-grunt-legacy-log@~2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz#c8cd2c6c81a4465b9bbf2d874d963fef7a59ffb9"
- integrity sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==
- dependencies:
- colors "~1.1.2"
- grunt-legacy-log-utils "~2.0.0"
- hooker "~0.2.3"
- lodash "~4.17.5"
-
-grunt-legacy-util@~1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz#e10624e7c86034e5b870c8a8616743f0a0845e42"
- integrity sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==
- dependencies:
- async "~1.5.2"
- exit "~0.1.1"
- getobject "~0.1.0"
- hooker "~0.2.3"
- lodash "~4.17.10"
- underscore.string "~3.3.4"
- which "~1.3.0"
-
-grunt-mkdir@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/grunt-mkdir/-/grunt-mkdir-1.0.0.tgz#73e1a26ac24a08596363f4dd954b0d32485e58e9"
- integrity sha1-c+GiasJKCFljY/TdlUsNMkheWOk=
-
-grunt-run@^0.8.1:
- version "0.8.1"
- resolved "https://registry.yarnpkg.com/grunt-run/-/grunt-run-0.8.1.tgz#502f988947a59f9ad567e2dcb5eeedec712980ec"
- integrity sha512-+wvoOJevugcjMLldbVCyspRHHntwVIJiTGjx0HFq+UwXhVPe7AaAiUdY4135CS68pAoRLhd7pAILpL2ITe1tmA==
- dependencies:
- strip-ansi "^3.0.0"
-
-grunt-ts@^6.0.0-beta.22:
- version "6.0.0-beta.22"
- resolved "https://registry.yarnpkg.com/grunt-ts/-/grunt-ts-6.0.0-beta.22.tgz#a628f6fb943b0a6e00afecaa721291611994f553"
- integrity sha512-g9e+ZImQ7W38dfpwhp0+GUltXWidy3YGPfIA/IyGL5HMv6wmVmMMoSgscI5swhs2HSPf8yAvXAAJbwrouijoRg==
- dependencies:
- chokidar "^2.0.4"
- csproj2ts "^1.1.0"
- detect-indent "^4.0.0"
- detect-newline "^2.1.0"
- es6-promise "~0.1.1"
- jsmin2 "^1.2.1"
- lodash "~4.17.10"
- ncp "0.5.1"
- rimraf "2.2.6"
- semver "^5.3.0"
- strip-bom "^2.0.0"
-
-grunt@^1.0.4:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/grunt/-/grunt-1.1.0.tgz#97dc6e6add901459774a988e4f454a12e24c9d3d"
- integrity sha512-+NGod0grmviZ7Nzdi9am7vuRS/h76PcWDsV635mEXF0PEQMUV6Kb+OjTdsVxbi0PZmfQOjCMKb3w8CVZcqsn1g==
- dependencies:
- coffeescript "~1.10.0"
- dateformat "~1.0.12"
- eventemitter2 "~0.4.13"
- exit "~0.1.1"
- findup-sync "~0.3.0"
- glob "~7.0.0"
- grunt-cli "~1.2.0"
- grunt-known-options "~1.1.0"
- grunt-legacy-log "~2.0.0"
- grunt-legacy-util "~1.1.1"
- iconv-lite "~0.4.13"
- js-yaml "~3.13.1"
- minimatch "~3.0.2"
- mkdirp "~1.0.3"
- nopt "~3.0.6"
- path-is-absolute "~1.0.0"
- rimraf "~2.6.2"
-
-gts@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/gts/-/gts-1.1.2.tgz#970003f6633c9c384705dab60251b58f6d659c78"
- integrity sha512-WWuagkjlFpSfQfShnlpbiJoKRuFXq9Yoj75Re1KVzd109vWo2RmcxaSe1lDtzNFtQFixcBy5TfV1QirTDfjZRA==
- dependencies:
- chalk "^3.0.0"
- diff "^4.0.1"
- inquirer "^7.0.0"
- meow "^5.0.0"
- ncp "^2.0.0"
- prettier "^1.19.1"
- rimraf "^3.0.0"
- tslint "^5.12.0"
- tslint-config-prettier "^1.18.0"
- update-notifier "^3.0.0"
- write-file-atomic "^3.0.0"
-
-has-ansi@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
- integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
- dependencies:
- ansi-regex "^2.0.0"
-
-has-flag@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
- integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
-
-has-flag@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
- integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
-
-has-value@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
- integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=
- dependencies:
- get-value "^2.0.3"
- has-values "^0.1.4"
- isobject "^2.0.0"
-
-has-value@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177"
- integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=
- dependencies:
- get-value "^2.0.6"
- has-values "^1.0.0"
- isobject "^3.0.0"
-
-has-values@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771"
- integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E=
-
-has-values@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f"
- integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=
- dependencies:
- is-number "^3.0.0"
- kind-of "^4.0.0"
-
-has-yarn@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77"
- integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==
-
-he@^1.1.1:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
- integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
-
-hooker@~0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/hooker/-/hooker-0.2.3.tgz#b834f723cc4a242aa65963459df6d984c5d3d959"
- integrity sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=
-
-hosted-git-info@^2.1.4:
- version "2.8.8"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
- integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
-
-http-cache-semantics@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
- integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
-
-http-proxy@^1.8.1:
- version "1.18.0"
- resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a"
- integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==
- dependencies:
- eventemitter3 "^4.0.0"
- follow-redirects "^1.0.0"
- requires-port "^1.0.0"
-
-http-server@0.11.1:
- version "0.11.1"
- resolved "https://registry.yarnpkg.com/http-server/-/http-server-0.11.1.tgz#2302a56a6ffef7f9abea0147d838a5e9b6b6a79b"
- integrity sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==
- dependencies:
- colors "1.0.3"
- corser "~2.0.0"
- ecstatic "^3.0.0"
- http-proxy "^1.8.1"
- opener "~1.4.0"
- optimist "0.6.x"
- portfinder "^1.0.13"
- union "~0.4.3"
-
-iconv-lite@^0.4.24, iconv-lite@~0.4.13:
- version "0.4.24"
- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
- integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
- dependencies:
- safer-buffer ">= 2.1.2 < 3"
-
-import-lazy@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
- integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
-
-imurmurhash@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
- integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
-
-indent-string@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
- integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
- dependencies:
- repeating "^2.0.0"
-
-indent-string@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
- integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
-
-inflight@^1.0.4:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
- integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
- dependencies:
- once "^1.3.0"
- wrappy "1"
-
-inherits@2, inherits@^2.0.3, inherits@~2.0.3:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
- integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
-ini@^1.3.4, ini@~1.3.0:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
- integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
-
-inquirer@^7.0.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29"
- integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==
- dependencies:
- ansi-escapes "^4.2.1"
- chalk "^3.0.0"
- cli-cursor "^3.1.0"
- cli-width "^2.0.0"
- external-editor "^3.0.3"
- figures "^3.0.0"
- lodash "^4.17.15"
- mute-stream "0.0.8"
- run-async "^2.4.0"
- rxjs "^6.5.3"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
- through "^2.3.6"
-
-invert-kv@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
- integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
-
-is-accessor-descriptor@^0.1.6:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
- integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=
- dependencies:
- kind-of "^3.0.2"
-
-is-accessor-descriptor@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656"
- integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==
- dependencies:
- kind-of "^6.0.0"
-
-is-arrayish@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
- integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
-
-is-binary-path@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
- integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=
- dependencies:
- binary-extensions "^1.0.0"
-
-is-buffer@^1.1.5:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
- integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-
-is-ci@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
- integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
- dependencies:
- ci-info "^2.0.0"
-
-is-data-descriptor@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
- integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=
- dependencies:
- kind-of "^3.0.2"
-
-is-data-descriptor@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7"
- integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==
- dependencies:
- kind-of "^6.0.0"
-
-is-descriptor@^0.1.0:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
- integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==
- dependencies:
- is-accessor-descriptor "^0.1.6"
- is-data-descriptor "^0.1.4"
- kind-of "^5.0.0"
-
-is-descriptor@^1.0.0, is-descriptor@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
- integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
- dependencies:
- is-accessor-descriptor "^1.0.0"
- is-data-descriptor "^1.0.0"
- kind-of "^6.0.2"
-
-is-extendable@^0.1.0, is-extendable@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
- integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=
-
-is-extendable@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
- integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
- dependencies:
- is-plain-object "^2.0.4"
-
-is-extglob@^2.1.0, is-extglob@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
- integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
-
-is-finite@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
- integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
-
-is-fullwidth-code-point@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
- integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
- dependencies:
- number-is-nan "^1.0.0"
-
-is-fullwidth-code-point@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
- integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
-
-is-fullwidth-code-point@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
- integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
-
-is-glob@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
- integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=
- dependencies:
- is-extglob "^2.1.0"
-
-is-glob@^4.0.0, is-glob@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
- integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
- dependencies:
- is-extglob "^2.1.1"
-
-is-installed-globally@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80"
- integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=
- dependencies:
- global-dirs "^0.1.0"
- is-path-inside "^1.0.0"
-
-is-npm@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053"
- integrity sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==
-
-is-number@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
- integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=
- dependencies:
- kind-of "^3.0.2"
-
-is-number@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
- integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-
-is-obj@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
- integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
-
-is-path-inside@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
- integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
- dependencies:
- path-is-inside "^1.0.1"
-
-is-plain-obj@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
- integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
-
-is-plain-object@^2.0.3, is-plain-object@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
- integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
- dependencies:
- isobject "^3.0.1"
-
-is-promise@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
- integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
-
-is-stream@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
- integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
-
-is-typedarray@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
- integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-
-is-utf8@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
- integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
-
-is-windows@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
- integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
-
-is-yarn-global@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232"
- integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
-
-isarray@1.0.0, isarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
- integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
-
-isexe@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
- integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
-
-isobject@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
- integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=
- dependencies:
- isarray "1.0.0"
-
-isobject@^3.0.0, isobject@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
- integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
-
-js-tokens@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
- integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-
-js-yaml@^3.13.1, js-yaml@~3.13.1:
- version "3.13.1"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
- integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
- dependencies:
- argparse "^1.0.7"
- esprima "^4.0.0"
-
-jsesc@^2.5.1:
- version "2.5.2"
- resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
- integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
-
-jsmin2@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/jsmin2/-/jsmin2-1.2.1.tgz#88fbe2fbf75f0a91f66020fd981cd693f4bfe57e"
- integrity sha1-iPvi+/dfCpH2YCD9mBzWk/S/5X4=
-
-json-buffer@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
- integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
-
-json-parse-better-errors@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
- integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
-
-json5@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.2.tgz#43ef1f0af9835dd624751a6b7fa48874fb2d608e"
- integrity sha512-MoUOQ4WdiN3yxhm7NEVJSJrieAo5hNSLQ5sj05OTRHPL9HOBy8u4Bu88jsC1jvqAdN+E1bJmsUcZH+1HQxliqQ==
- dependencies:
- minimist "^1.2.5"
-
-keyv@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
- integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==
- dependencies:
- json-buffer "3.0.0"
-
-kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
- integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=
- dependencies:
- is-buffer "^1.1.5"
-
-kind-of@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
- integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc=
- dependencies:
- is-buffer "^1.1.5"
-
-kind-of@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
- integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
-
-kind-of@^6.0.0, kind-of@^6.0.2:
- version "6.0.3"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
- integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
-
-latest-version@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face"
- integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==
- dependencies:
- package-json "^6.3.0"
-
-lcid@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
- integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=
- dependencies:
- invert-kv "^1.0.0"
-
-load-json-file@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
- integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
- dependencies:
- graceful-fs "^4.1.2"
- parse-json "^2.2.0"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
- strip-bom "^2.0.0"
-
-load-json-file@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
- integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
- dependencies:
- graceful-fs "^4.1.2"
- parse-json "^4.0.0"
- pify "^3.0.0"
- strip-bom "^3.0.0"
-
-locate-path@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
- integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
- dependencies:
- p-locate "^2.0.0"
- path-exists "^3.0.0"
-
-lodash@4.17.5:
- version "4.17.5"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
- integrity sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==
-
-lodash@=3.9.3:
- version "3.9.3"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.9.3.tgz#0159e86832feffc6d61d852b12a953b99496bd32"
- integrity sha1-AVnoaDL+/8bWHYUrEqlTuZSWvTI=
-
-lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@~4.17.10, lodash@~4.17.5:
- version "4.17.15"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
- integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
-
-loud-rejection@^1.0.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
- integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
- dependencies:
- currently-unhandled "^0.4.1"
- signal-exit "^3.0.0"
-
-lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
- integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
-
-lowercase-keys@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
- integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
-
-lru-cache@^4.0.1, lru-cache@^4.1.5:
- version "4.1.5"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
- integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
- dependencies:
- pseudomap "^1.0.2"
- yallist "^2.1.2"
-
-make-dir@^1.0.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
- integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
- dependencies:
- pify "^3.0.0"
-
-make-dir@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
- integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
- dependencies:
- pify "^4.0.1"
- semver "^5.6.0"
-
-make-error@^1.1.1:
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
- integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
-
-map-cache@^0.2.2:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
- integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
-
-map-obj@^1.0.0, map-obj@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
- integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
-
-map-obj@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9"
- integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk=
-
-map-visit@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
- integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
- dependencies:
- object-visit "^1.0.0"
-
-mem@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
- integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=
- dependencies:
- mimic-fn "^1.0.0"
-
-meow@^3.3.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
- integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
- dependencies:
- camelcase-keys "^2.0.0"
- decamelize "^1.1.2"
- loud-rejection "^1.0.0"
- map-obj "^1.0.1"
- minimist "^1.1.3"
- normalize-package-data "^2.3.4"
- object-assign "^4.0.1"
- read-pkg-up "^1.0.1"
- redent "^1.0.0"
- trim-newlines "^1.0.0"
-
-meow@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4"
- integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==
- dependencies:
- camelcase-keys "^4.0.0"
- decamelize-keys "^1.0.0"
- loud-rejection "^1.0.0"
- minimist-options "^3.0.1"
- normalize-package-data "^2.3.4"
- read-pkg-up "^3.0.0"
- redent "^2.0.0"
- trim-newlines "^2.0.0"
- yargs-parser "^10.0.0"
-
-merge2@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
- integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==
-
-micromatch@^3.1.10, micromatch@^3.1.4:
- version "3.1.10"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
- integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
- dependencies:
- arr-diff "^4.0.0"
- array-unique "^0.3.2"
- braces "^2.3.1"
- define-property "^2.0.2"
- extend-shallow "^3.0.2"
- extglob "^2.0.4"
- fragment-cache "^0.2.1"
- kind-of "^6.0.2"
- nanomatch "^1.2.9"
- object.pick "^1.3.0"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.2"
-
-micromatch@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
- integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
- dependencies:
- braces "^3.0.1"
- picomatch "^2.0.5"
-
-mime@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
- integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
-
-mimic-fn@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
- integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
-
-mimic-fn@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
- integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-
-mimic-response@^1.0.0, mimic-response@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
- integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
-
-"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
- integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
- dependencies:
- brace-expansion "^1.1.7"
-
-minimist-options@^3.0.1:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954"
- integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==
- dependencies:
- arrify "^1.0.1"
- is-plain-obj "^1.1.0"
-
-minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
- integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-
-minimist@~0.0.1:
- version "0.0.10"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
- integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
-
-mixin-deep@^1.2.0:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
- integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
- dependencies:
- for-in "^1.0.2"
- is-extendable "^1.0.1"
-
-mkdirp@^0.5.1, mkdirp@^0.5.3:
- version "0.5.5"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
- integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
- dependencies:
- minimist "^1.2.5"
-
-mkdirp@~1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
- integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-
-ms@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
- integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
-
-ms@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
- integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-
-mute-stream@0.0.8:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
- integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
-
-nan@^2.12.1:
- version "2.14.0"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
- integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
-
-nanomatch@^1.2.9:
- version "1.2.13"
- resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
- integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
- dependencies:
- arr-diff "^4.0.0"
- array-unique "^0.3.2"
- define-property "^2.0.2"
- extend-shallow "^3.0.2"
- fragment-cache "^0.2.1"
- is-windows "^1.0.2"
- kind-of "^6.0.2"
- object.pick "^1.3.0"
- regex-not "^1.0.0"
- snapdragon "^0.8.1"
- to-regex "^3.0.1"
-
-ncp@0.5.1:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/ncp/-/ncp-0.5.1.tgz#743985316e3db459281b587169e845735a05439f"
- integrity sha1-dDmFMW49tFkoG1hxaehFc1oFQ58=
-
-ncp@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3"
- integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=
-
-nopt@~3.0.6:
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
- integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
- dependencies:
- abbrev "1"
-
-normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
- integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
- dependencies:
- hosted-git-info "^2.1.4"
- resolve "^1.10.0"
- semver "2 || 3 || 4 || 5"
- validate-npm-package-license "^3.0.1"
-
-normalize-path@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
- integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
- dependencies:
- remove-trailing-separator "^1.0.1"
-
-normalize-path@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
- integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-
-normalize-url@^4.1.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
- integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
-
-npm-run-path@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
- integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
- dependencies:
- path-key "^2.0.0"
-
-number-is-nan@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
- integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-
-object-assign@^4.0.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
- integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
-
-object-copy@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
- integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw=
- dependencies:
- copy-descriptor "^0.1.0"
- define-property "^0.2.5"
- kind-of "^3.0.3"
-
-object-visit@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
- integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=
- dependencies:
- isobject "^3.0.0"
-
-object.pick@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
- integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
- dependencies:
- isobject "^3.0.1"
-
-once@^1.3.0, once@^1.3.1, once@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
- integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
- dependencies:
- wrappy "1"
-
-onetime@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5"
- integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==
- dependencies:
- mimic-fn "^2.1.0"
-
-opener@1.4.3, opener@~1.4.0:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
- integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=
-
-optimist@0.6.x:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
- integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY=
- dependencies:
- minimist "~0.0.1"
- wordwrap "~0.0.2"
-
-os-locale@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
- integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==
- dependencies:
- execa "^0.7.0"
- lcid "^1.0.0"
- mem "^1.1.0"
-
-os-tmpdir@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
- integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
-
-p-cancelable@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
- integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
-
-p-finally@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
- integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
-
-p-limit@^1.1.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
- integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
- dependencies:
- p-try "^1.0.0"
-
-p-locate@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
- integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=
- dependencies:
- p-limit "^1.1.0"
-
-p-try@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
- integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
-
-package-json@^6.3.0:
- version "6.5.0"
- resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0"
- integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==
- dependencies:
- got "^9.6.0"
- registry-auth-token "^4.0.0"
- registry-url "^5.0.0"
- semver "^6.2.0"
-
-parse-json@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
- integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
- dependencies:
- error-ex "^1.2.0"
-
-parse-json@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
- integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
- dependencies:
- error-ex "^1.3.1"
- json-parse-better-errors "^1.0.1"
-
-pascalcase@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
- integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
-
-path-dirname@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
- integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
-
-path-exists@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
- integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
- dependencies:
- pinkie-promise "^2.0.0"
-
-path-exists@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
- integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
-
-path-is-absolute@^1.0.0, path-is-absolute@~1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
- integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-
-path-is-inside@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
- integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
-
-path-key@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
- integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
-
-path-parse@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
- integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
-
-path-type@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
- integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
- dependencies:
- graceful-fs "^4.1.2"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
-
-path-type@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
- integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
- dependencies:
- pify "^3.0.0"
-
-picomatch@^2.0.5, picomatch@^2.2.1:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
- integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
-
-pify@^2.0.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
- integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
-
-pify@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
- integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
-
-pify@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
- integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
-
-pinkie-promise@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
- integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
- dependencies:
- pinkie "^2.0.0"
-
-pinkie@^2.0.0:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
- integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
-
-portfinder@^1.0.13:
- version "1.0.25"
- resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
- integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==
- dependencies:
- async "^2.6.2"
- debug "^3.1.1"
- mkdirp "^0.5.1"
-
-posix-character-classes@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
- integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
-
-prepend-http@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
- integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
-
-prettier@^1.19.1:
- version "1.19.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
- integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
-
-process-nextick-args@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
- integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-
-pseudomap@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
- integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
-
-pump@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
- integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
-qs@~2.3.3:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404"
- integrity sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=
-
-quick-lru@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
- integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=
-
-quiet-grunt@^0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/quiet-grunt/-/quiet-grunt-0.2.3.tgz#f0908979a97d242ac2d8d6eebcfe558f59c06184"
- integrity sha1-8JCJeal9JCrC2NbuvP5Vj1nAYYQ=
-
-rc@^1.2.8:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
- integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
- dependencies:
- deep-extend "^0.6.0"
- ini "~1.3.0"
- minimist "^1.2.0"
- strip-json-comments "~2.0.1"
-
-read-pkg-up@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
- integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
- dependencies:
- find-up "^1.0.0"
- read-pkg "^1.0.0"
-
-read-pkg-up@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
- integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=
- dependencies:
- find-up "^2.0.0"
- read-pkg "^3.0.0"
-
-read-pkg@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
- integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
- dependencies:
- load-json-file "^1.0.0"
- normalize-package-data "^2.3.2"
- path-type "^1.0.0"
-
-read-pkg@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
- integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
- dependencies:
- load-json-file "^4.0.0"
- normalize-package-data "^2.3.2"
- path-type "^3.0.0"
-
-readable-stream@^2.0.2:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
- integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.3"
- isarray "~1.0.0"
- process-nextick-args "~2.0.0"
- safe-buffer "~5.1.1"
- string_decoder "~1.1.1"
- util-deprecate "~1.0.1"
-
-readdirp@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
- integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==
- dependencies:
- graceful-fs "^4.1.11"
- micromatch "^3.1.10"
- readable-stream "^2.0.2"
-
-redent@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
- integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=
- dependencies:
- indent-string "^2.1.0"
- strip-indent "^1.0.1"
-
-redent@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
- integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=
- dependencies:
- indent-string "^3.0.0"
- strip-indent "^2.0.0"
-
-regex-not@^1.0.0, regex-not@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
- integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
- dependencies:
- extend-shallow "^3.0.2"
- safe-regex "^1.1.0"
-
-registry-auth-token@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479"
- integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==
- dependencies:
- rc "^1.2.8"
-
-registry-url@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009"
- integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==
- dependencies:
- rc "^1.2.8"
-
-remove-trailing-separator@^1.0.1:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
- integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
-
-repeat-element@^1.1.2:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
- integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==
-
-repeat-string@^1.6.1:
- version "1.6.1"
- resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
- integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
-
-repeating@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
- integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
- dependencies:
- is-finite "^1.0.0"
-
-require-directory@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
- integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
-
-require-main-filename@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
- integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
-
-requires-port@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
- integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
-
-resolve-url@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
- integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-
-resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2:
- version "1.15.1"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8"
- integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==
- dependencies:
- path-parse "^1.0.6"
-
-resolve@~1.1.0:
- version "1.1.7"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
- integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
-
-responselike@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
- integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=
- dependencies:
- lowercase-keys "^1.0.0"
-
-restore-cursor@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
- integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
- dependencies:
- onetime "^5.1.0"
- signal-exit "^3.0.2"
-
-ret@~0.1.10:
- version "0.1.15"
- resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
- integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
-
-reusify@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
- integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
-
-rimraf@2.2.6:
- version "2.2.6"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.6.tgz#c59597569b14d956ad29cacc42bdddf5f0ea4f4c"
- integrity sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=
-
-rimraf@^2.6.2:
- version "2.7.1"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
- integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
- dependencies:
- glob "^7.1.3"
-
-rimraf@^3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
- integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
- dependencies:
- glob "^7.1.3"
-
-rimraf@~2.6.2:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
- integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
- dependencies:
- glob "^7.1.3"
-
-run-async@^2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8"
- integrity sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==
- dependencies:
- is-promise "^2.1.0"
-
-run-parallel@^1.1.9:
- version "1.1.9"
- resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679"
- integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==
-
-rxjs@^6.5.3:
- version "6.5.5"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
- integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
- dependencies:
- tslib "^1.9.0"
-
-safe-buffer@~5.1.0, safe-buffer@~5.1.1:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
- integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
-safe-regex@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
- integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4=
- dependencies:
- ret "~0.1.10"
-
-"safer-buffer@>= 2.1.2 < 3":
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
- integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
-sax@>=0.6.0:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
- integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
-
-semver-diff@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
- integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=
- dependencies:
- semver "^5.0.3"
-
-"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.4.1, semver@^5.6.0:
- version "5.7.1"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
- integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
-
-semver@^6.2.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
- integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-
-set-blocking@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
- integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
-
-set-value@^2.0.0, set-value@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
- integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==
- dependencies:
- extend-shallow "^2.0.1"
- is-extendable "^0.1.1"
- is-plain-object "^2.0.3"
- split-string "^3.0.1"
-
-shebang-command@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
- integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
- dependencies:
- shebang-regex "^1.0.0"
-
-shebang-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
- integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
-
-showdown@1.8.6:
- version "1.8.6"
- resolved "https://registry.yarnpkg.com/showdown/-/showdown-1.8.6.tgz#91ea4ee3b7a5448aaca6820a4e27e690c6ad771c"
- integrity sha1-kepO47elRIqspoIKTifmkMatdxw=
- dependencies:
- yargs "^10.0.3"
-
-sigmund@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
- integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
-
-signal-exit@^3.0.0, signal-exit@^3.0.2:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
- integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
-
-slash@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
- integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
-
-snapdragon-node@^2.0.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
- integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
- dependencies:
- define-property "^1.0.0"
- isobject "^3.0.0"
- snapdragon-util "^3.0.1"
-
-snapdragon-util@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
- integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==
- dependencies:
- kind-of "^3.2.0"
-
-snapdragon@^0.8.1:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d"
- integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==
- dependencies:
- base "^0.11.1"
- debug "^2.2.0"
- define-property "^0.2.5"
- extend-shallow "^2.0.1"
- map-cache "^0.2.2"
- source-map "^0.5.6"
- source-map-resolve "^0.5.0"
- use "^3.1.0"
-
-source-map-resolve@^0.5.0:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
- integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==
- dependencies:
- atob "^2.1.2"
- decode-uri-component "^0.2.0"
- resolve-url "^0.2.1"
- source-map-url "^0.4.0"
- urix "^0.1.0"
-
-source-map-support@^0.5.6:
- version "0.5.16"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
- integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
- dependencies:
- buffer-from "^1.0.0"
- source-map "^0.6.0"
-
-source-map-url@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
- integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
-
-source-map@^0.5.0, source-map@^0.5.6:
- version "0.5.7"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
- integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
-
-source-map@^0.6.0:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
- integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
-
-spdx-correct@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4"
- integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==
- dependencies:
- spdx-expression-parse "^3.0.0"
- spdx-license-ids "^3.0.0"
-
-spdx-exceptions@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977"
- integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==
-
-spdx-expression-parse@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0"
- integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==
- dependencies:
- spdx-exceptions "^2.1.0"
- spdx-license-ids "^3.0.0"
-
-spdx-license-ids@^3.0.0:
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
- integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==
-
-split-string@^3.0.1, split-string@^3.0.2:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
- integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
- dependencies:
- extend-shallow "^3.0.0"
-
-sprintf-js@^1.0.3:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
- integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
-
-sprintf-js@~1.0.2:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
- integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-
-static-extend@^0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
- integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=
- dependencies:
- define-property "^0.2.5"
- object-copy "^0.1.0"
-
-string-width@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
- integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
- dependencies:
- code-point-at "^1.0.0"
- is-fullwidth-code-point "^1.0.0"
- strip-ansi "^3.0.0"
-
-string-width@^2.0.0, string-width@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
- integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
- dependencies:
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^4.0.0"
-
-string-width@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
- integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
- dependencies:
- emoji-regex "^7.0.1"
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^5.1.0"
-
-string-width@^4.1.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
- integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.0"
-
-string_decoder@~1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
- integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
- dependencies:
- safe-buffer "~5.1.0"
-
-strip-ansi@^3.0.0, strip-ansi@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
- integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
- dependencies:
- ansi-regex "^2.0.0"
-
-strip-ansi@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
- integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
- dependencies:
- ansi-regex "^3.0.0"
-
-strip-ansi@^5.1.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
- integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
- dependencies:
- ansi-regex "^4.1.0"
-
-strip-ansi@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
- integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
- dependencies:
- ansi-regex "^5.0.0"
-
-strip-bom@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
- integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
- dependencies:
- is-utf8 "^0.2.0"
-
-strip-bom@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
- integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
-
-strip-eof@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
- integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
-
-strip-indent@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
- integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=
- dependencies:
- get-stdin "^4.0.1"
-
-strip-indent@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
- integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
-
-strip-json-comments@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
- integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
-
-supports-color@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
- integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-
-supports-color@^5.3.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
- integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
- dependencies:
- has-flag "^3.0.0"
-
-supports-color@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
- integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
- dependencies:
- has-flag "^4.0.0"
-
-term-size@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
- integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=
- dependencies:
- execa "^0.7.0"
-
-through@^2.3.6:
- version "2.3.8"
- resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
- integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
-
-tmp@^0.0.33:
- version "0.0.33"
- resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
- integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
- dependencies:
- os-tmpdir "~1.0.2"
-
-to-fast-properties@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
- integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
-
-to-object-path@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
- integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=
- dependencies:
- kind-of "^3.0.2"
-
-to-readable-stream@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771"
- integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==
-
-to-regex-range@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
- integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=
- dependencies:
- is-number "^3.0.0"
- repeat-string "^1.6.1"
-
-to-regex-range@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
- integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
- dependencies:
- is-number "^7.0.0"
-
-to-regex@^3.0.1, to-regex@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
- integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==
- dependencies:
- define-property "^2.0.2"
- extend-shallow "^3.0.2"
- regex-not "^1.0.2"
- safe-regex "^1.1.0"
-
-trim-newlines@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
- integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
-
-trim-newlines@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20"
- integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=
-
-ts-node@^8.5.4:
- version "8.8.1"
- resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.8.1.tgz#7c4d3e9ed33aa703b64b28d7f9d194768be5064d"
- integrity sha512-10DE9ONho06QORKAaCBpPiFCdW+tZJuY/84tyypGtl6r+/C7Asq0dhqbRZURuUlLQtZxxDvT8eoj8cGW0ha6Bg==
- dependencies:
- arg "^4.1.0"
- diff "^4.0.1"
- make-error "^1.1.1"
- source-map-support "^0.5.6"
- yn "3.1.1"
-
-tslib@^1.10.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
- integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
-
-tslint-config-prettier@^1.18.0:
- version "1.18.0"
- resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz#75f140bde947d35d8f0d238e0ebf809d64592c37"
- integrity sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==
-
-tslint@^5.12.0:
- version "5.20.1"
- resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.20.1.tgz#e401e8aeda0152bc44dd07e614034f3f80c67b7d"
- integrity sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==
- dependencies:
- "@babel/code-frame" "^7.0.0"
- builtin-modules "^1.1.1"
- chalk "^2.3.0"
- commander "^2.12.1"
- diff "^4.0.1"
- glob "^7.1.1"
- js-yaml "^3.13.1"
- minimatch "^3.0.4"
- mkdirp "^0.5.1"
- resolve "^1.3.2"
- semver "^5.3.0"
- tslib "^1.8.0"
- tsutils "^2.29.0"
-
-tslint@^6.1.1:
- version "6.1.1"
- resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.1.tgz#ac03fbd17f85bfefaae348b353b25a88efe10cde"
- integrity sha512-kd6AQ/IgPRpLn6g5TozqzPdGNZ0q0jtXW4//hRcj10qLYBaa3mTUU2y2MCG+RXZm8Zx+KZi0eA+YCrMyNlF4UA==
- dependencies:
- "@babel/code-frame" "^7.0.0"
- builtin-modules "^1.1.1"
- chalk "^2.3.0"
- commander "^2.12.1"
- diff "^4.0.1"
- glob "^7.1.1"
- js-yaml "^3.13.1"
- minimatch "^3.0.4"
- mkdirp "^0.5.3"
- resolve "^1.3.2"
- semver "^5.3.0"
- tslib "^1.10.0"
- tsutils "^2.29.0"
-
-tsutils@^2.29.0:
- version "2.29.0"
- resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
- integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
- dependencies:
- tslib "^1.8.1"
-
-type-fest@^0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
- integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
-
-type-fest@^0.3.0:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1"
- integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==
-
-typedarray-to-buffer@^3.1.5:
- version "3.1.5"
- resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
- integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
- dependencies:
- is-typedarray "^1.0.0"
-
-typescript-formatter@^7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/typescript-formatter/-/typescript-formatter-7.2.2.tgz#a147181839b7bb09c2377b072f20f6336547c00a"
- integrity sha512-V7vfI9XArVhriOTYHPzMU2WUnm5IMdu9X/CPxs8mIMGxmTBFpDABlbkBka64PZJ9/xgQeRpK8KzzAG4MPzxBDQ==
- dependencies:
- commandpost "^1.0.0"
- editorconfig "^0.15.0"
-
-typescript@^3.8.3:
- version "3.8.3"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
- integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
-
-underscore.string@~3.3.4:
- version "3.3.5"
- resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.5.tgz#fc2ad255b8bd309e239cbc5816fd23a9b7ea4023"
- integrity sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==
- dependencies:
- sprintf-js "^1.0.3"
- util-deprecate "^1.0.2"
-
-union-value@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
- integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==
- dependencies:
- arr-union "^3.1.0"
- get-value "^2.0.6"
- is-extendable "^0.1.1"
- set-value "^2.0.1"
-
-union@~0.4.3:
- version "0.4.6"
- resolved "https://registry.yarnpkg.com/union/-/union-0.4.6.tgz#198fbdaeba254e788b0efcb630bc11f24a2959e0"
- integrity sha1-GY+9rrolTniLDvy2MLwR8kopWeA=
- dependencies:
- qs "~2.3.3"
-
-unique-string@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
- integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=
- dependencies:
- crypto-random-string "^1.0.0"
-
-unset-value@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
- integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=
- dependencies:
- has-value "^0.3.1"
- isobject "^3.0.0"
-
-upath@^1.1.1:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
- integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
-
-update-notifier@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-3.0.1.tgz#78ecb68b915e2fd1be9f767f6e298ce87b736250"
- integrity sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ==
- dependencies:
- boxen "^3.0.0"
- chalk "^2.0.1"
- configstore "^4.0.0"
- has-yarn "^2.1.0"
- import-lazy "^2.1.0"
- is-ci "^2.0.0"
- is-installed-globally "^0.1.0"
- is-npm "^3.0.0"
- is-yarn-global "^0.3.0"
- latest-version "^5.0.0"
- semver-diff "^2.0.0"
- xdg-basedir "^3.0.0"
-
-urix@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
- integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
-
-url-join@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.5.tgz#5af22f18c052a000a48d7b82c5e9c2e2feeda728"
- integrity sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=
-
-url-parse-lax@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
- integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=
- dependencies:
- prepend-http "^2.0.0"
-
-use@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
- integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
-
-util-deprecate@^1.0.2, util-deprecate@~1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-
-validate-npm-package-license@^3.0.1:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
- integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
- dependencies:
- spdx-correct "^3.0.0"
- spdx-expression-parse "^3.0.0"
-
-which-module@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
- integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-
-which@^1.2.9, which@~1.3.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
- integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
- dependencies:
- isexe "^2.0.0"
-
-widest-line@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc"
- integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==
- dependencies:
- string-width "^2.1.1"
-
-wordwrap@~0.0.2:
- version "0.0.3"
- resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
- integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc=
-
-wrap-ansi@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
- integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
- dependencies:
- string-width "^1.0.1"
- strip-ansi "^3.0.1"
-
-wrappy@1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
- integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-
-write-file-atomic@^2.0.0:
- version "2.4.3"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
- integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
- dependencies:
- graceful-fs "^4.1.11"
- imurmurhash "^0.1.4"
- signal-exit "^3.0.2"
-
-write-file-atomic@^3.0.0:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
- integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
- dependencies:
- imurmurhash "^0.1.4"
- is-typedarray "^1.0.0"
- signal-exit "^3.0.2"
- typedarray-to-buffer "^3.1.5"
-
-xdg-basedir@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
- integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=
-
-xml2js@^0.4.19:
- version "0.4.23"
- resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"
- integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==
- dependencies:
- sax ">=0.6.0"
- xmlbuilder "~11.0.0"
-
-xmlbuilder@~11.0.0:
- version "11.0.1"
- resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
- integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
-
-y18n@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
- integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
-
-yallist@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
- integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
-
-yargs-parser@^10.0.0:
- version "10.1.0"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
- integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
- dependencies:
- camelcase "^4.1.0"
-
-yargs-parser@^8.1.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950"
- integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==
- dependencies:
- camelcase "^4.1.0"
-
-yargs@^10.0.3:
- version "10.1.2"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5"
- integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==
- dependencies:
- cliui "^4.0.0"
- decamelize "^1.1.1"
- find-up "^2.1.0"
- get-caller-file "^1.0.1"
- os-locale "^2.0.0"
- require-directory "^2.1.1"
- require-main-filename "^1.0.1"
- set-blocking "^2.0.0"
- string-width "^2.0.0"
- which-module "^2.0.0"
- y18n "^3.2.1"
- yargs-parser "^8.1.0"
-
-yn@3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
- integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==