From 741b29c5a72726f60ae925ab818643a14f5e9131 Mon Sep 17 00:00:00 2001 From: Jesper van den Ende Date: Sat, 8 Jun 2024 17:07:50 +0200 Subject: [PATCH] fix: Update import attribute syntax (#938) --- .vscode/settings.json | 2 +- deno.json | 8 +-- importmap.json | 2 +- scripts/buildEngine.js | 4 +- scripts/buildStudio.js | 16 +++--- scripts/check.js | 3 +- scripts/dev.js | 49 +++++++--------- scripts/shared/overrideDefinesPlugin.js | 2 +- scripts/shared/rollup-css-import-attribute.js | 37 ++++++++++++ scripts/shared/rollup-plugin-wasm-url.js | 50 +++++++++++++++++ scripts/shared/rollupTerserPlugin.js | 2 +- scripts/test.js | 4 +- studio/src/misc/thirdPartyLicenses/rollup.js | 56 +++---------------- studio/src/styles/projectSelectorStyles.js | 6 +- studio/src/styles/shadowStyles.js | 4 +- studio/src/styles/studioStyles.js | 16 +++--- .../src/tasks/workers/bundleScripts/bundle.js | 6 +- .../workers/bundleScripts/resolvePlugin.js | 6 +- studio/src/ui/ArrayGui.js | 10 ++-- .../PropertiesTreeViewEntry.js | 2 +- .../MemoryFileSystemWritableFileStream.js | 11 +++- test/e2e/shared/browser.js | 8 ++- .../renderers/webGpu/WebGpuRenderer.test.js | 6 +- .../devSocket/src/BuiltInAssetManager.test.js | 1 + .../shared/mockTreeView/PropertiesTreeView.js | 9 +-- .../mockTreeView/PropertiesTreeViewEntry.js | 23 ++------ .../PropertiesAssetContentMaterial.test.js | 28 +++++----- .../MaterialMapListUi.test.js | 2 +- .../all/tests/writeFileStream.test.js | 20 +++++++ 29 files changed, 223 insertions(+), 170 deletions(-) create mode 100644 scripts/shared/rollup-css-import-attribute.js create mode 100644 scripts/shared/rollup-plugin-wasm-url.js diff --git a/.vscode/settings.json b/.vscode/settings.json index bc89ec694..ae6e7dee4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "typescript.tsdk": "./npm_packages/typescript/5.0.2/lib", + "typescript.tsdk": "./npm_packages/typescript/5.4.5/lib", "typescript.enablePromptUseWorkspaceTsdk": true, "deno.enable": false, "deno.lint": false, diff --git a/deno.json b/deno.json index a63e620f6..3a097700f 100644 --- a/deno.json +++ b/deno.json @@ -13,10 +13,10 @@ "dev": "deno run --allow-env --allow-run --allow-read --allow-write --allow-net scripts/dev.js", "lint": "deno run --allow-env --allow-read --allow-write --allow-sys --allow-run=git scripts/lint.js", "check": "deno run --allow-env --allow-run --allow-read --allow-write --allow-net scripts/check.js", - "test": "deno run --allow-run --allow-read --allow-write --allow-env --allow-net scripts/test.js", - "build-engine": "deno run --allow-read --allow-write --allow-net --allow-env scripts/buildEngine.js", + "test": "deno run -A scripts/test.js", + "build-engine": "deno run -A scripts/buildEngine.js", "build-studio": "deno run -A scripts/buildStudio.js", - "build-npm-package": "deno run --allow-read --allow-write scripts/buildNpmPackage.js", - "build-jsr-package": "deno run --allow-read --allow-write scripts/buildJsrPackage.js" + "build-npm-package": "deno run -A scripts/buildNpmPackage.js", + "build-jsr-package": "deno run -A scripts/buildJsrPackage.js" } } diff --git a/importmap.json b/importmap.json index 1fb8c0611..bf3002277 100644 --- a/importmap.json +++ b/importmap.json @@ -6,7 +6,7 @@ "fake-imports": "https://deno.land/x/fake_imports@v0.10.0/mod.js", "fake-dom/": "https://deno.land/x/fake_dom@v0.12.0/src/", "puppeteer": "https://raw.githubusercontent.com/jespertheend/deno-puppeteer/7c5ed2e6e9f43d7fc27d4fa49f17db36be220956/mod.ts", - "rollup": "npm:rollup@2.79.1", + "$rollup": "npm:rollup@4.18.0", "rollup-plugin-jscc": "npm:rollup-plugin-jscc@2.0.0", "rollup-plugin-cleanup": "npm:rollup-plugin-cleanup@3.2.1", "rollup-plugin-commonjs": "npm:@rollup/plugin-commonjs@11.1.0", diff --git a/scripts/buildEngine.js b/scripts/buildEngine.js index 1d46ed7d7..795f1ee7e 100755 --- a/scripts/buildEngine.js +++ b/scripts/buildEngine.js @@ -1,6 +1,6 @@ import * as path from "std/path/mod.ts"; import * as fs from "std/fs/mod.ts"; -import { rollup } from "rollup"; +import { rollup } from "$rollup"; import cleanup from "rollup-plugin-cleanup"; import jscc from "rollup-plugin-jscc"; import { overrideDefines } from "./shared/overrideDefinesPlugin.js"; @@ -37,7 +37,7 @@ async function createBundle() { return bundle; } -/** @type {import("rollup").OutputOptions} */ +/** @type {import("$rollup").OutputOptions} */ const outputOptions = { dir: "dist/", format: "esm", diff --git a/scripts/buildStudio.js b/scripts/buildStudio.js index 6ec621c14..1e336082d 100755 --- a/scripts/buildStudio.js +++ b/scripts/buildStudio.js @@ -1,10 +1,8 @@ -import { rollup } from "rollup"; +import { rollup } from "$rollup"; import { copy, ensureDir, walk } from "std/fs/mod.ts"; import * as path from "std/path/mod.ts"; import { minify } from "terser"; import { setCwd } from "chdir-anywhere"; -import { importAssertionsPlugin } from "https://esm.sh/rollup-plugin-import-assert@2.1.0?pin=v87"; -import { importAssertions } from "https://esm.sh/acorn-import-assertions@1.8.0?pin=v87"; import postcss from "https://deno.land/x/postcss@8.4.13/mod.js"; import postcssUrl from "npm:postcss-url@10.1.3"; import resolveUrlObjects from "npm:rollup-plugin-resolve-url-objects@0.0.4"; @@ -12,6 +10,8 @@ import { dev } from "./dev.js"; import { buildEngineSource } from "./buildEngine.js"; import { toHashString } from "std/crypto/mod.ts"; import { overrideDefines } from "./shared/overrideDefinesPlugin.js"; +import { cssImportAttributesPlugin } from "./shared/rollup-css-import-attribute.js"; +import { resolveWasmUrls } from "./shared/rollup-plugin-wasm-url.js"; await dev({ needsDependencies: true, @@ -67,7 +67,7 @@ async function setHtmlAttribute(filePath, tagComment, attributeValue, attribute function rebaseCssUrl({ outputPath, }) { - /** @type {import("rollup").Plugin} */ + /** @type {import("$rollup").Plugin} */ const plugin = { name: "rebaseCssUrl", async load(id) { @@ -143,12 +143,12 @@ const bundle = await rollup({ plugins: [ overrideDefines("/studio/src/studioDefines.js", studioDefines), resolveUrlObjects(), + resolveWasmUrls(), rebaseCssUrl({ outputPath, }), - importAssertionsPlugin(), + cssImportAttributesPlugin(), ], - acornInjectPlugins: [importAssertions], onwarn: (message) => { if (message.code == "CIRCULAR_DEPENDENCY") return; console.error(message.message); @@ -166,9 +166,7 @@ const entryPointPaths = new Map(); /** @type {string[]} */ const createdChunkFiles = []; for (const chunkOrAsset of output) { - if (chunkOrAsset.type != "chunk") { - throw new Error("Assertion failed, unexpected type: " + chunkOrAsset.type); - } + if (chunkOrAsset.type != "chunk") continue; if (chunkOrAsset.facadeModuleId) { entryPointPaths.set(chunkOrAsset.facadeModuleId, chunkOrAsset.fileName); } diff --git a/scripts/check.js b/scripts/check.js index 3db369dea..90e79b574 100644 --- a/scripts/check.js +++ b/scripts/check.js @@ -4,10 +4,11 @@ await dev({ needsTypes: true, needsTypesSync: true, needsDependencies: true, + needsDevDependencies: true, }); const command = new Deno.Command(Deno.execPath(), { - args: ["run", "--allow-env", "--allow-read", "npm:typescript@5.0.2/tsc", "--noEmit", "-p", "./jsconfig.json"], + args: ["run", "--allow-env", "--allow-read", "npm:typescript@5.4.5/tsc", "--noEmit", "-p", "./jsconfig.json"], stdout: "inherit", stderr: "inherit", }); diff --git a/scripts/dev.js b/scripts/dev.js index c66323562..6916563f8 100755 --- a/scripts/dev.js +++ b/scripts/dev.js @@ -104,38 +104,27 @@ export async function dev({ } if (needsDependencies || needsDevDependencies) { - const { dev } = await import("https://deno.land/x/dev@v0.2.0/mod.js"); + const { downloadNpmPackage, esmify, addTsNocheck } = await import("https://deno.land/x/dev@v0.4.0/mod.js"); - await dev({ - actions: [ - // required for during development, can be skipped with ci - { - type: "downloadNpmPackage", - package: "typescript@5.0.2", - ignore: !needsDevDependencies, - }, + if (needsDevDependencies) { + await downloadNpmPackage({ + package: "typescript@5.4.5", + }); + } - // studio dependencies - { - type: "downloadNpmPackage", - package: "rollup@2.60.0", - }, - { - type: "downloadNpmPackage", - package: "rollup-plugin-resolve-url-objects@0.0.4", - downloadDependencies: true, - }, - { - type: "esmify", - entryPointPath: "npm_packages/rollup/2.60.0/dist/rollup.browser.js", - outputPath: "studio/deps/rollup.browser.js", - }, - { - type: "esmify", - entryPointPath: "npm_packages/rollup-plugin-resolve-url-objects/0.0.4/main.js", - outputPath: "studio/deps/rollup-plugin-resolve-url-objects.js", - }, - ], + await downloadNpmPackage({ + package: "@rollup/browser@4.18.0", + }); + await addTsNocheck({ + path: "npm_packages/@rollup/browser/4.18.0", + }); + await downloadNpmPackage({ + package: "rollup-plugin-resolve-url-objects@0.0.4", + downloadDependencies: true, + }); + await esmify({ + entryPointPath: "npm_packages/rollup-plugin-resolve-url-objects/0.0.4/main.js", + outFile: "studio/deps/rollup-plugin-resolve-url-objects.js", }); } diff --git a/scripts/shared/overrideDefinesPlugin.js b/scripts/shared/overrideDefinesPlugin.js index f15e3a693..2ff318c4b 100644 --- a/scripts/shared/overrideDefinesPlugin.js +++ b/scripts/shared/overrideDefinesPlugin.js @@ -1,7 +1,7 @@ /** * @param {string} definesFilePath * @param {Object} defines - * @returns {import("rollup").Plugin} + * @returns {import("$rollup").Plugin} */ export function overrideDefines(definesFilePath, defines) { return { diff --git a/scripts/shared/rollup-css-import-attribute.js b/scripts/shared/rollup-css-import-attribute.js new file mode 100644 index 000000000..d4830f868 --- /dev/null +++ b/scripts/shared/rollup-css-import-attribute.js @@ -0,0 +1,37 @@ +/** + * A rollup plugin that allows you to import css files like so: + * ```js + * import sheet from "./path/to/style.css" with { type: "css" } + * document.adoptedStyleSheets = [sheet]; + * ``` + * @returns {import("$rollup").Plugin} + */ +export function cssImportAttributesPlugin() { + return { + name: "css-import-attributes", + async resolveId(source, importer, options) { + const { attributes } = options; + if ("type" in attributes && attributes.type == "css") { + const resolution = await this.resolve(source, importer, options); + if (!resolution || resolution.external) return resolution; + return { + id: resolution.id, + meta: { + cssImportAttributes: { + isCssType: true, + }, + }, + }; + } + return null; + }, + transform(code, id) { + const moduleInfo = this.getModuleInfo(id); + const meta = moduleInfo?.meta; + if (meta && "cssImportAttributes" in meta && meta.cssImportAttributes.isCssType) { + const newCode = `const sheet = new CSSStyleSheet();sheet.replaceSync(\`${code}\`);export default sheet;`; + return { code: newCode }; + } + }, + }; +} diff --git a/scripts/shared/rollup-plugin-wasm-url.js b/scripts/shared/rollup-plugin-wasm-url.js new file mode 100644 index 000000000..390dca0cc --- /dev/null +++ b/scripts/shared/rollup-plugin-wasm-url.js @@ -0,0 +1,50 @@ +import * as stdPath from "std/path/mod.ts"; + +/** @type {import("$rollup").PluginImpl} */ +export function resolveWasmUrls() { + return { + name: "resolve-wasm-urls", + async transform(code, id) { + const re = /new\s+URL\s*\(\s*['"`](?.+\.wasm)['"`]\s*,\s*import\.meta\.url\s*\)/gid; + for (const match of code.matchAll(re)) { + if (!match.indices) continue; + if (!match.indices.groups) continue; + if (!match.groups) continue; + const startUrlIndex = match.indices.groups.wasmUrl[0] - 1; + const endUrlIndex = match.indices.groups.wasmUrl[1] + 1; + let wasmUrl = match.groups.wasmUrl; + if (!wasmUrl.match(/^.?.?\//)) { + wasmUrl = "./" + wasmUrl; + } + + const resolveResult = await this.resolve(wasmUrl, id, { + attributes: { + type: "webassembly", + }, + }); + if (!resolveResult) continue; + + const parsedPath = stdPath.parse(resolveResult.id); + + const source = await Deno.readFile(resolveResult.id); + const hashBuffer = await crypto.subtle.digest("SHA-256", source); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); + const hash = hashHex.slice(0, 8); + + const chunkRefId = this.emitFile({ + type: "asset", + fileName: `${parsedPath.name}-${hash}.wasm`, + source, + }); + const newUrl = `import.meta.ROLLUP_FILE_URL_${chunkRefId}`; + + code = code.substring(0, startUrlIndex) + newUrl + code.substring(endUrlIndex); + } + + return { + code, + }; + }, + }; +} diff --git a/scripts/shared/rollupTerserPlugin.js b/scripts/shared/rollupTerserPlugin.js index 18632222a..ca7ccba3e 100644 --- a/scripts/shared/rollupTerserPlugin.js +++ b/scripts/shared/rollupTerserPlugin.js @@ -5,7 +5,7 @@ const nameCache = {}; /** * A rollup plugin for minifying builds. * @param {import("terser").MinifyOptions} minifyOptions - * @returns {import("rollup").Plugin} + * @returns {import("$rollup").Plugin} */ export function rollupTerserPlugin(minifyOptions = {}) { return { diff --git a/scripts/test.js b/scripts/test.js index ff1e4d65a..014b4613d 100755 --- a/scripts/test.js +++ b/scripts/test.js @@ -6,7 +6,7 @@ import { setCwd } from "chdir-anywhere"; import { dev } from "./dev.js"; import { parseArgs } from "../test/shared/testArgs.js"; import { buildEngine } from "./buildEngine.js"; -import { rollup } from "rollup"; +import { rollup } from "$rollup"; import { rollupTerserPlugin } from "./shared/rollupTerserPlugin.js"; setCwd(); @@ -106,7 +106,7 @@ if (needsMinifiedTests) { await buildEngine(engineDir); /** - * @returns {import("rollup").Plugin} + * @returns {import("$rollup").Plugin} */ function rollupRedirectBuildPlugin() { return { diff --git a/studio/src/misc/thirdPartyLicenses/rollup.js b/studio/src/misc/thirdPartyLicenses/rollup.js index 4477bf612..b9016168f 100644 --- a/studio/src/misc/thirdPartyLicenses/rollup.js +++ b/studio/src/misc/thirdPartyLicenses/rollup.js @@ -54,52 +54,9 @@ License: MIT By: Rich Harris Repository: rollup/plugins ---------------------------------------- - -## acorn -License: MIT -By: Marijn Haverbeke, Ingvar Stepanyan, Adrian Heine -Repository: https://github.com/acornjs/acorn.git - -> MIT License -> -> Copyright (C) 2012-2022 by various contributors (see AUTHORS) -> -> Permission is hereby granted, free of charge, to any person obtaining a copy -> of this software and associated documentation files (the "Software"), to deal -> in the Software without restriction, including without limitation the rights -> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -> copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: -> -> The above copyright notice and this permission notice shall be included in -> all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -> THE SOFTWARE. - ---------------------------------------- - -## acorn-import-assertions -License: MIT -By: Sven Sauleau -Repository: https://github.com/xtuc/acorn-import-assertions - ---------------------------------------- - -## acorn-walk -License: MIT -By: Marijn Haverbeke, Ingvar Stepanyan, Adrian Heine -Repository: https://github.com/acornjs/acorn.git - -> MIT License +> The MIT License (MIT) > -> Copyright (C) 2012-2020 by various contributors (see AUTHORS) +> Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors) > > Permission is hereby granted, free of charge, to any person obtaining a copy > of this software and associated documentation files (the "Software"), to deal @@ -151,7 +108,8 @@ Repository: sindresorhus/binary-extensions > MIT License > -> Copyright (c) 2019 Sindre Sorhus (https://sindresorhus.com), Paul Miller (https://paulmillr.com) +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) +> Copyright (c) Paul Miller (https://paulmillr.com) > > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: > @@ -168,7 +126,7 @@ Repository: micromatch/braces > The MIT License (MIT) > -> Copyright (c) 2014-2018, Jon Schlinkert. +> Copyright (c) 2014-present, Jon Schlinkert. > > Permission is hereby granted, free of charge, to any person obtaining a copy > of this software and associated documentation files (the "Software"), to deal @@ -451,7 +409,7 @@ Repository: git+https://github.com/Rich-Harris/is-reference.git ## locate-character License: MIT By: Rich Harris -Repository: Rich-Harris/locate-character +Repository: git+https://gitlab.com/Rich-Harris/locate-character.git --------------------------------------- @@ -615,7 +573,7 @@ Repository: https://github.com/tapjs/signal-exit.git > The ISC License > -> Copyright (c) 2015, Contributors +> Copyright (c) 2015-2023 Benjamin Coe, Isaac Z. Schlueter, and Contributors > > Permission to use, copy, modify, and/or distribute this software > for any purpose with or without fee is hereby granted, provided diff --git a/studio/src/styles/projectSelectorStyles.js b/studio/src/styles/projectSelectorStyles.js index 83a2f3524..06a8d8f50 100644 --- a/studio/src/styles/projectSelectorStyles.js +++ b/studio/src/styles/projectSelectorStyles.js @@ -1,9 +1,9 @@ // @ts-ignore -import initialLoad from "./initialLoad.css" assert {type: "css"}; +import initialLoad from "./initialLoad.css" with {type: "css"}; // @ts-ignore -import variables from "./variables.css" assert {type: "css"}; +import variables from "./variables.css" with {type: "css"}; // @ts-ignore -import projectSelector from "../projectSelector/projectSelector.css" assert {type: "css"}; +import projectSelector from "../projectSelector/projectSelector.css" with {type: "css"}; document.adoptedStyleSheets = [ ...document.adoptedStyleSheets, diff --git a/studio/src/styles/shadowStyles.js b/studio/src/styles/shadowStyles.js index f687a4de6..82324c4bc 100644 --- a/studio/src/styles/shadowStyles.js +++ b/studio/src/styles/shadowStyles.js @@ -6,10 +6,10 @@ // @ts-nocheck -import contentWindowHistorySheet from "../windowManagement/contentWindows/ContentWindowHistory.css" assert {type: "css"}; +import contentWindowHistorySheet from "../windowManagement/contentWindows/ContentWindowHistory.css" with {type: "css"}; export {contentWindowHistorySheet}; -import contentWindowEntityEditorSheet from "../windowManagement/contentWindows/ContentWindowEntityEditor/ContentWindowEntityEditor.css" assert {type: "css"}; +import contentWindowEntityEditorSheet from "../windowManagement/contentWindows/ContentWindowEntityEditor/ContentWindowEntityEditor.css" with {type: "css"}; export {contentWindowEntityEditorSheet}; // HEADS UP: When adding a new import to this file, diff --git a/studio/src/styles/studioStyles.js b/studio/src/styles/studioStyles.js index bbe8b8a61..95bda6e35 100644 --- a/studio/src/styles/studioStyles.js +++ b/studio/src/styles/studioStyles.js @@ -1,19 +1,19 @@ // @ts-ignore -import mainSheet from "./studio.css" assert {type: "css"}; +import mainSheet from "./studio.css" with {type: "css"}; // @ts-ignore -import zIndex from "./zIndex.css" assert {type: "css"}; +import zIndex from "./zIndex.css" with {type: "css"}; // @ts-ignore -import windowManagement from "../windowManagement/windowManagement.css" assert {type: "css"}; +import windowManagement from "../windowManagement/windowManagement.css" with {type: "css"}; // @ts-ignore -import contentWindowAbout from "../windowManagement/contentWindows/ContentWindowAbout.css" assert {type: "css"}; +import contentWindowAbout from "../windowManagement/contentWindows/ContentWindowAbout.css" with {type: "css"}; // @ts-ignore -import popoverMenus from "../ui/popoverMenus/popoverMenus.css" assert {type: "css"}; +import popoverMenus from "../ui/popoverMenus/popoverMenus.css" with {type: "css"}; // @ts-ignore -import guis from "../ui/guis.css" assert {type: "css"}; +import guis from "../ui/guis.css" with {type: "css"}; // @ts-ignore -import spinner from "../ui/spinner.css" assert {type: "css"}; +import spinner from "../ui/spinner.css" with {type: "css"}; // @ts-ignore -import treeView from "../ui/treeView.css" assert {type: "css"}; +import treeView from "../ui/treeView.css" with {type: "css"}; document.adoptedStyleSheets = [ ...document.adoptedStyleSheets, diff --git a/studio/src/tasks/workers/bundleScripts/bundle.js b/studio/src/tasks/workers/bundleScripts/bundle.js index ffa6b26c2..16bee6d68 100644 --- a/studio/src/tasks/workers/bundleScripts/bundle.js +++ b/studio/src/tasks/workers/bundleScripts/bundle.js @@ -1,8 +1,8 @@ -import transpiledRollup from "../../../../deps/rollup.browser.js"; +import { rollup as rollupWithoutTypes } from "../../../../../npm_packages/@rollup/browser/4.18.0/dist/es/rollup.browser.js"; import { resolvePlugin } from "./resolvePlugin.js"; import resolveUrlObjects from "../../../../deps/rollup-plugin-resolve-url-objects.js"; -const rollup = /** @type {import("rollup")} */ (transpiledRollup); +const rollup = /** @type {import("$rollup").rollup} */ (rollupWithoutTypes); /** * @typedef BundleOptions @@ -31,7 +31,7 @@ export async function bundle({ inputPaths, outputPath, readScriptCallbackId, ser return result; }; - const bundle = await rollup.rollup({ + const bundle = await rollup({ input: inputPaths, plugins: [ resolvePlugin({ diff --git a/studio/src/tasks/workers/bundleScripts/resolvePlugin.js b/studio/src/tasks/workers/bundleScripts/resolvePlugin.js index 3ba30ffd0..43ea97b64 100644 --- a/studio/src/tasks/workers/bundleScripts/resolvePlugin.js +++ b/studio/src/tasks/workers/bundleScripts/resolvePlugin.js @@ -22,13 +22,13 @@ const scriptTypes = [ * @param {GetScriptContentFn} options.getScriptContentFn * @param {string} options.servicesSource The generated code that will be placed * in the file that a user can import via "renda:services". - * @return {import("rollup").Plugin} + * @return {import("$rollup").Plugin} */ export function resolvePlugin({ getScriptContentFn, servicesSource }) { return { name: "studio-resolve-scripts", resolveId(source, importer, opts) { - const castThis = /** @type {import("rollup").PluginContext} */ (/** @type {unknown} */ (this)); + const castThis = /** @type {import("$rollup").PluginContext} */ (/** @type {unknown} */ (this)); let importerInfo = null; if (importer) { importerInfo = castThis.getModuleInfo(importer); @@ -76,7 +76,7 @@ export function resolvePlugin({ getScriptContentFn, servicesSource }) { }; }, async load(id) { - const castThis = /** @type {import("rollup").PluginContext} */ (/** @type {unknown} */ (this)); + const castThis = /** @type {import("$rollup").PluginContext} */ (/** @type {unknown} */ (this)); const moduleInfo = castThis.getModuleInfo(id); /** @type {ScriptType?} */ const scriptType = moduleInfo?.meta?.studioResolve?.scriptType ?? null; diff --git a/studio/src/ui/ArrayGui.js b/studio/src/ui/ArrayGui.js index 2ada33ad1..72ab4578d 100644 --- a/studio/src/ui/ArrayGui.js +++ b/studio/src/ui/ArrayGui.js @@ -181,11 +181,13 @@ export class ArrayGui { const valueArray = []; for (const item of this.valueItems) { let value = null; - const gui = /** @type {import("./propertiesTreeView/PropertiesTreeViewEntry.js").GuiInterface} */ (item.gui); - if (gui.getValue) { - value = gui.getValue(guiOpts); + // @ts-ignore + const gui = item.gui; + const castGui = /** @type {import("./propertiesTreeView/PropertiesTreeViewEntry.js").GuiInterface} */ (gui); + if (castGui.getValue) { + value = castGui.getValue(guiOpts); } else { - value = gui.value; + value = castGui.value; } valueArray.push(value); } diff --git a/studio/src/ui/propertiesTreeView/PropertiesTreeViewEntry.js b/studio/src/ui/propertiesTreeView/PropertiesTreeViewEntry.js index 43c9b7268..5f2d8a5f6 100644 --- a/studio/src/ui/propertiesTreeView/PropertiesTreeViewEntry.js +++ b/studio/src/ui/propertiesTreeView/PropertiesTreeViewEntry.js @@ -50,7 +50,7 @@ export class PropertiesTreeViewEntry extends TreeView { */ static of(opts) { const x = new PropertiesTreeViewEntry(opts); - return /** @type {import("./types.ts").TreeViewEntryFactoryReturnType} */ (x); + return /** @type {import("./types.ts").TreeViewEntryFactoryReturnType} */ (/** @type {unknown} */ (x)); } #labelText = ""; diff --git a/studio/src/util/fileSystems/MemoryFileSystemWritableFileStream.js b/studio/src/util/fileSystems/MemoryFileSystemWritableFileStream.js index 4fd4e93f2..d5318b215 100644 --- a/studio/src/util/fileSystems/MemoryFileSystemWritableFileStream.js +++ b/studio/src/util/fileSystems/MemoryFileSystemWritableFileStream.js @@ -18,11 +18,20 @@ export class MemoryFileSystemWritableFileStream extends WritableStream { if (data instanceof ArrayBuffer || ArrayBuffer.isView(data) || data instanceof Blob || typeof data == "string") { await this.#writeChunk(data); } else if (data.type == "seek") { + if (data.position == undefined) { + throw new DOMException("Invalid params passed. seek requires a position argument"); + } return await this.seek(data.position); } else if (data.type == "truncate") { + if (data.size == undefined) { + throw new DOMException("Invalid params passed. truncate requires a size argument"); + } return await this.truncate(data.size); } else if (data.type == "write") { - if (data.position !== undefined) { + if (!data.data) { + throw new DOMException("Invalid params passed. write requires a data argument"); + } + if (data.position != undefined) { await this.seek(data.position); } await this.#writeChunk(data.data); diff --git a/test/e2e/shared/browser.js b/test/e2e/shared/browser.js index bf5d24e78..c695587bf 100644 --- a/test/e2e/shared/browser.js +++ b/test/e2e/shared/browser.js @@ -28,7 +28,13 @@ export async function installIfNotInstalled() { // Ideally we would use the revision bundled with puppeteer, // but unfortunately some tests seem to be failing when we do this. // This version seems to work though, so we'll roll with it. - const revision = "1235267"; + let revision; + if (Deno.build.os == "windows" || Deno.build.os == "darwin") { + revision = "1287751"; + } else { + // Linux seems to have a different snapshot, not sure why + revision = "1287757"; + } let revisionInfo = fetcher.revisionInfo(revision); if (!revisionInfo.local) { console.log(`Downloading chromium ${revision}...`); diff --git a/test/unit/src/rendering/renderers/webGpu/WebGpuRenderer.test.js b/test/unit/src/rendering/renderers/webGpu/WebGpuRenderer.test.js index e6034cbd6..4d136127d 100644 --- a/test/unit/src/rendering/renderers/webGpu/WebGpuRenderer.test.js +++ b/test/unit/src/rendering/renderers/webGpu/WebGpuRenderer.test.js @@ -157,7 +157,8 @@ Deno.test({ assertEquals(writeBufferSpy.calls[0].args[0].label, "viewUniforms-chunk0"); const viewUniformsBuffer = writeBufferSpy.calls[0].args[2]; assertInstanceOf(viewUniformsBuffer, ArrayBuffer); - const view = new DataView(viewUniformsBuffer); + const castViewUniformsBuffer = /** @type {ArrayBuffer} */ (viewUniformsBuffer); + const view = new DataView(castViewUniformsBuffer); const screenWidth = view.getFloat32(0, true); assertEquals(screenWidth, 128); @@ -232,7 +233,8 @@ Deno.test({ assertEquals(writeBufferSpy.calls[3].args[0].label, "objectUniforms-chunk0"); const viewUniformsBuffer = writeBufferSpy.calls[3].args[2]; assertInstanceOf(viewUniformsBuffer, ArrayBuffer); - const view = new DataView(viewUniformsBuffer); + const castViewUniformsBuffer = /** @type {ArrayBuffer} */ (viewUniformsBuffer); + const view = new DataView(castViewUniformsBuffer); const expectedViewMatrix = cam.worldMatrix.inverse(); const expectedViewProjectionMatrix = Mat4.multiplyMatrices(expectedViewMatrix, camComponent.projectionMatrix); diff --git a/test/unit/studio/devSocket/src/BuiltInAssetManager.test.js b/test/unit/studio/devSocket/src/BuiltInAssetManager.test.js index d26ddbea2..f8529f6bb 100644 --- a/test/unit/studio/devSocket/src/BuiltInAssetManager.test.js +++ b/test/unit/studio/devSocket/src/BuiltInAssetManager.test.js @@ -68,6 +68,7 @@ function installMockDenoCalls({ [Symbol.asyncIterator]() { return /** @type {any} */ (this); }, + [Symbol.dispose]() {}, }; }; diff --git a/test/unit/studio/shared/mockTreeView/PropertiesTreeView.js b/test/unit/studio/shared/mockTreeView/PropertiesTreeView.js index 78d0efdb7..7eb78d6f2 100644 --- a/test/unit/studio/shared/mockTreeView/PropertiesTreeView.js +++ b/test/unit/studio/shared/mockTreeView/PropertiesTreeView.js @@ -6,18 +6,11 @@ export class PropertiesTreeView extends TreeView { constructor() { super(); - /** @type {import("./TreeView.js").TreeViewSpy} */ - const superSpy = this.spy; - const generateFromSerializableStructureSpy = spy(this, "generateFromSerializableStructure"); - const newSpy = { - ...superSpy, + this.propertiesTreeViewSpy = { generateFromSerializableStructureSpy, }; - - /** @type {typeof newSpy} */ - this.spy = newSpy; } addCollapsable() { diff --git a/test/unit/studio/shared/mockTreeView/PropertiesTreeViewEntry.js b/test/unit/studio/shared/mockTreeView/PropertiesTreeViewEntry.js index 7b4844f10..2b409199e 100644 --- a/test/unit/studio/shared/mockTreeView/PropertiesTreeViewEntry.js +++ b/test/unit/studio/shared/mockTreeView/PropertiesTreeViewEntry.js @@ -1,24 +1,17 @@ import { TreeView } from "./TreeView.js"; /** - * @typedef {object} PropertiesTreeViewEntrySpyOnly + * @typedef {object} PropertiesTreeViewEntrySpy * @property {unknown[][]} setValueCalls * @property {import("../../../../../studio/src/ui/propertiesTreeView/types.ts").PropertiesTreeViewEntryOptions} constructorOptions */ -/** - * @typedef {import("./TreeView.js").TreeViewSpy & PropertiesTreeViewEntrySpyOnly} PropertiesTreeViewEntrySpy - */ /** * @template {import("../../../../../studio/src/ui/propertiesTreeView/types.ts").GuiTypeInstances} T - * @typedef {object} PropertiesTreeViewEntryMockObjectOnly + * @typedef {object} PropertiesTreeViewEntryMockObject * @property {import("../../../../../studio/src/ui/propertiesTreeView/types.ts").PropertiesTreeViewEntryChangeCallback>} fireOnValueChangeCbs * @property {(value: unknown) => void} setGetValueReturn */ -/** - * @template {import("../../../../../studio/src/ui/propertiesTreeView/types.ts").GuiTypeInstances} T - * @typedef {import("./TreeView.js").TreeViewMockObject & PropertiesTreeViewEntryMockObjectOnly} PropertiesTreeViewEntryMockObject - */ /** * @template {import("../../../../../studio/src/ui/propertiesTreeView/types.ts").GuiTypeInstances} [T = any] @@ -33,20 +26,14 @@ export class PropertiesTreeViewEntry extends TreeView { constructor(opts) { super(); - /** @type {import("./TreeView.js").TreeViewSpy} */ - const superSpy = this.spy; /** @type {PropertiesTreeViewEntrySpy} */ - this.spy = { - ...superSpy, + this.propertiesTreeViewEntrySpy = { setValueCalls: [], constructorOptions: opts, }; - /** @type {import("./TreeView.js").TreeViewMockObject} */ - const superMock = this.mock; /** @type {PropertiesTreeViewEntryMockObject} */ - this.mock = { - ...superMock, + this.propertiesTreeViewEntryMock = { /** * @param {any} event */ @@ -85,7 +72,7 @@ export class PropertiesTreeViewEntry extends TreeView { * @param {unknown[]} args */ setValue(...args) { - this.spy.setValueCalls.push(args); + this.propertiesTreeViewEntrySpy.setValueCalls.push(args); } get value() { diff --git a/test/unit/studio/src/propertiesAssetContent/PropertiesAssetContentMaterial.test.js b/test/unit/studio/src/propertiesAssetContent/PropertiesAssetContentMaterial.test.js index 74488e37e..5f95e7602 100644 --- a/test/unit/studio/src/propertiesAssetContent/PropertiesAssetContentMaterial.test.js +++ b/test/unit/studio/src/propertiesAssetContent/PropertiesAssetContentMaterial.test.js @@ -97,12 +97,12 @@ Deno.test({ liveAsset: new Material(), }); const mockMapTreeView = castTreeView(assetContent.mapTreeView); - mockMapTreeView.mock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); + mockMapTreeView.propertiesTreeViewEntryMock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); await assetContent.selectionUpdated([mockMaterialAsset]); const mockTreeView = castTreeView(assetContent.mapTreeView); - assertEquals(mockTreeView.spy.setValueCalls, [[null]]); + assertEquals(mockTreeView.propertiesTreeViewEntrySpy.setValueCalls, [[null]]); }, }); @@ -116,14 +116,14 @@ Deno.test({ liveAsset: material, }); const mockMapTreeView = castTreeView(assetContent.mapTreeView); - mockMapTreeView.mock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); + mockMapTreeView.propertiesTreeViewEntryMock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); await assetContent.selectionUpdated([mockMaterialAsset]); const mockTreeView = castTreeView(assetContent.mapTreeView); - assertEquals(mockTreeView.spy.setValueCalls.length, 1); - assertEquals(mockTreeView.spy.setValueCalls[0].length, 1); - assertStrictEquals(mockTreeView.spy.setValueCalls[0][0], materialMap); + assertEquals(mockTreeView.propertiesTreeViewEntrySpy.setValueCalls.length, 1); + assertEquals(mockTreeView.propertiesTreeViewEntrySpy.setValueCalls[0].length, 1); + assertStrictEquals(mockTreeView.propertiesTreeViewEntrySpy.setValueCalls[0][0], materialMap); }, }); @@ -188,7 +188,7 @@ Deno.test({ return values; }); const mockMapTreeView = castTreeView(assetContent.mapTreeView); - mockMapTreeView.mock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); + mockMapTreeView.propertiesTreeViewEntryMock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); const materialMap = new MaterialMap(); const material = new Material(materialMap); const { projectAsset: mockMaterialAsset } = createMockProjectAsset({ @@ -202,7 +202,7 @@ Deno.test({ for (const child of assetContent.mapValuesTreeView.children) { const castChildEntry = /** @type {import("../../../../../studio/src/ui/propertiesTreeView/PropertiesTreeViewEntry.js").PropertiesTreeViewEntry} */ (child); const castMockChild = castTreeView(castChildEntry); - createdValueOptions.push(castMockChild.spy.constructorOptions); + createdValueOptions.push(castMockChild.propertiesTreeViewEntrySpy.constructorOptions); } assertEquals(createdValueOptions, [ { @@ -290,14 +290,14 @@ Deno.test({ liveAsset: material, }); const mockMapTreeView = castTreeView(assetContent.mapTreeView); - mockMapTreeView.mock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); + mockMapTreeView.propertiesTreeViewEntryMock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); await assetContent.selectionUpdated([mockMaterialAsset]); const mockTreeView = castTreeView(assetContent.mapTreeView); const materialMap = new MaterialMap(); - mockTreeView.mock.setGetValueReturn(materialMap); - mockTreeView.mock.fireOnValueChangeCbs({ value: DEFAULT_ASSET_MAP_UUID, trigger: "user" }); + mockTreeView.propertiesTreeViewEntryMock.setGetValueReturn(materialMap); + mockTreeView.propertiesTreeViewEntryMock.fireOnValueChangeCbs({ value: DEFAULT_ASSET_MAP_UUID, trigger: "user" }); await waitForMicrotasks(); @@ -325,8 +325,8 @@ Deno.test({ const mockTreeView = castTreeView(assetContent.mapTreeView); const materialMap = new MaterialMap(); - mockTreeView.mock.setGetValueReturn(materialMap); - mockTreeView.mock.fireOnValueChangeCbs({ value: DEFAULT_ASSET_MAP_UUID, trigger: "application" }); + mockTreeView.propertiesTreeViewEntryMock.setGetValueReturn(materialMap); + mockTreeView.propertiesTreeViewEntryMock.fireOnValueChangeCbs({ value: DEFAULT_ASSET_MAP_UUID, trigger: "application" }); triggerLiveAssetReturns(); await waitForMicrotasks(); @@ -354,7 +354,7 @@ Deno.test({ liveAsset: new Material(), }); const mockMapTreeView = castTreeView(assetContent.mapTreeView); - mockMapTreeView.mock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); + mockMapTreeView.propertiesTreeViewEntryMock.setGetValueReturn(DEFAULT_ASSET_MAP_UUID); await assetContent.selectionUpdated([mockMaterialAsset1]); await assetContent.selectionUpdated([mockMaterialAsset1, mockMaterialAsset2]); diff --git a/test/unit/studio/src/propertiesAssetContent/propertiesAssetContentMaterialMap/MaterialMapListUi.test.js b/test/unit/studio/src/propertiesAssetContent/propertiesAssetContentMaterialMap/MaterialMapListUi.test.js index ff2a7d52b..d14ce1063 100644 --- a/test/unit/studio/src/propertiesAssetContent/propertiesAssetContentMaterialMap/MaterialMapListUi.test.js +++ b/test/unit/studio/src/propertiesAssetContent/propertiesAssetContentMaterialMap/MaterialMapListUi.test.js @@ -161,7 +161,7 @@ Deno.test({ const expectedStructure = expectedStructures[i]; const child = /** @type {import("../../../../../../studio/src/ui/propertiesTreeView/PropertiesTreeView.js").PropertiesTreeView} */ (mapListUi.treeView.children[i]); const childTreeView = castTreeView(child); - const generateSpy = childTreeView.spy.generateFromSerializableStructureSpy; + const generateSpy = childTreeView.propertiesTreeViewSpy.generateFromSerializableStructureSpy; assertSpyCalls(generateSpy, 1); assertSpyCall(generateSpy, 0, { args: [expectedStructure], diff --git a/test/unit/studio/src/util/fileSystems/all/tests/writeFileStream.test.js b/test/unit/studio/src/util/fileSystems/all/tests/writeFileStream.test.js index 529a7ac88..2e6372651 100644 --- a/test/unit/studio/src/util/fileSystems/all/tests/writeFileStream.test.js +++ b/test/unit/studio/src/util/fileSystems/all/tests/writeFileStream.test.js @@ -51,3 +51,23 @@ testAll({ }, Error, `Failed to write "root/file1/newfile", "root/file1" is not a directory.`); }, }); + +testAll({ + name: "writing to file streams fail when missing arguments", + ignore: ["indexedDb", "fsa", "remote", "serialized-remote"], + async fn(ctx) { + const fs = await ctx.createBasicFs(); + + const stream = await fs.writeFileStream(["root", "newfile"]); + + await assertRejects(async () => { + await stream.write({ type: "seek" }); + }, DOMException, "Invalid params passed. seek requires a position argument"); + await assertRejects(async () => { + await stream.write({ type: "truncate" }); + }, DOMException, "Invalid params passed. truncate requires a size argument"); + await assertRejects(async () => { + await stream.write({ type: "write" }); + }, DOMException, "Invalid params passed. write requires a data argument"); + }, +});