diff --git a/.eslintrc.js b/.eslintrc.js
index ad524b5..d6a599c 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -66,6 +66,7 @@ module.exports = {
},
],
'@typescript-eslint/no-unused-vars': 'off',
+ '@typescript-eslint/no-floating-promises': 'warn',
},
},
{
diff --git a/packages/benchmarks/src/index.tsx b/packages/benchmarks/src/index.tsx
index 11361c5..a13045a 100644
--- a/packages/benchmarks/src/index.tsx
+++ b/packages/benchmarks/src/index.tsx
@@ -106,6 +106,6 @@ async function test1() {
iterateOnSequence()
}
-test1().then(() => {
+void test1().then(() => {
console.log('test1 done')
})
diff --git a/packages/browser-bundles/devEnv/build.ts b/packages/browser-bundles/devEnv/build.ts
index eb87eb0..f76894a 100644
--- a/packages/browser-bundles/devEnv/build.ts
+++ b/packages/browser-bundles/devEnv/build.ts
@@ -35,14 +35,14 @@ function createBundles(watch: boolean) {
// format: 'iife',
// })
- build({
+ void build({
...esbuildConfig,
entryPoints: [path.join(pathToPackage, 'src/core-and-studio.ts')],
outfile: path.join(pathToPackage, 'dist/core-and-studio.js'),
format: 'iife',
})
- build({
+ void build({
...esbuildConfig,
entryPoints: [path.join(pathToPackage, 'src/core-only.ts')],
outfile: path.join(pathToPackage, 'dist/core-only.min.js'),
diff --git a/packages/dataverse/devEnv/build.ts b/packages/dataverse/devEnv/build.ts
index 063e614..e0998be 100644
--- a/packages/dataverse/devEnv/build.ts
+++ b/packages/dataverse/devEnv/build.ts
@@ -17,7 +17,7 @@ function createBundles(watch: boolean) {
conditions: ['browser', 'node'],
}
- build({
+ void build({
...esbuildConfig,
outfile: path.join(pathToPackage, 'dist/index.js'),
format: 'cjs',
diff --git a/packages/playground/src/shared/image/index.tsx b/packages/playground/src/shared/image/index.tsx
index 7b445de..e216aa1 100644
--- a/packages/playground/src/shared/image/index.tsx
+++ b/packages/playground/src/shared/image/index.tsx
@@ -53,7 +53,7 @@ const ImageTypeExample: React.FC<{}> = (props) => {
onClick={() => {
if (sheet.sequence.position === 0) {
sheet.sequence.position = 0
- sheet.sequence.play()
+ void sheet.sequence.play()
} else {
sheet.sequence.position = 0
}
@@ -64,6 +64,10 @@ const ImageTypeExample: React.FC<{}> = (props) => {
)
}
-project.ready.then(() => {
- render(, document.getElementById('root'))
-})
+project.ready
+ .then(() => {
+ render(, document.getElementById('root'))
+ })
+ .catch((err) => {
+ console.error(err)
+ })
diff --git a/packages/playground/src/shared/notifications/index.tsx b/packages/playground/src/shared/notifications/index.tsx
index 00bd26f..5d2f0d8 100644
--- a/packages/playground/src/shared/notifications/index.tsx
+++ b/packages/playground/src/shared/notifications/index.tsx
@@ -7,7 +7,7 @@ import {Scene} from './Scene'
studio.initialize()
// trigger warning notification
-getProject('Sample project').sheet('Scene').sequence.play()
+void getProject('Sample project').sheet('Scene').sequence.play()
// fire an info notification
notify.info(
@@ -16,7 +16,7 @@ notify.info(
'(and all others) at the start of index.tsx. You can also see examples of success and warnign notifications.',
)
-getProject('Sample project').ready.then(() => {
+void getProject('Sample project').ready.then(() => {
// fire a success notification on project load
notify.success(
'Project loaded!',
diff --git a/packages/playground/src/shared/theatric/index.tsx b/packages/playground/src/shared/theatric/index.tsx
index ce0cc13..6d2b273 100644
--- a/packages/playground/src/shared/theatric/index.tsx
+++ b/packages/playground/src/shared/theatric/index.tsx
@@ -3,7 +3,7 @@ import {render} from 'react-dom'
import React, {useState} from 'react'
import state from './state.json'
-initialize({state})
+void initialize({state})
function SomeComponent({id}: {id: string}) {
const {foo, $get, $set} = useControls(
diff --git a/packages/playground/src/tests/r3f-stress-test/App.tsx b/packages/playground/src/tests/r3f-stress-test/App.tsx
index c5a83ae..43ed8f7 100644
--- a/packages/playground/src/tests/r3f-stress-test/App.tsx
+++ b/packages/playground/src/tests/r3f-stress-test/App.tsx
@@ -76,7 +76,7 @@ function App() {
const bg = bgs[bgIndex]
const project = getProject('SpaceStress', {state})
const sheet = project.sheet('Scene')
- project.ready.then(() => sheet.sequence.play({iterationCount: Infinity}))
+ void project.ready.then(() => sheet.sequence.play({iterationCount: Infinity}))
const allPropsObj = sheet.object('All Props Tester', allPropsObjectConfig)
console.log('allPropsObj', allPropsObj)
diff --git a/packages/playground/src/tests/reading-obj-value/index.tsx b/packages/playground/src/tests/reading-obj-value/index.tsx
index 4886def..16183ea 100644
--- a/packages/playground/src/tests/reading-obj-value/index.tsx
+++ b/packages/playground/src/tests/reading-obj-value/index.tsx
@@ -39,13 +39,13 @@ const elements = new Array(TOTAL_ELEMENTS).fill(0).map((_, idx) => {
return {el, sheet, obj}
})
-project.ready.then(() => {
+void project.ready.then(() => {
// select the playback controls obj so it shows as a tweakable control
studio.setSelection([playbackControlObj])
for (let i = 0; i < elements.length; i++) {
const sheet = elements[i].sheet
sheet.sequence.position = i * TOTAL_ELEMENTS_R * 5
- sheet.sequence.play({
+ void sheet.sequence.play({
iterationCount: Infinity,
})
}
diff --git a/packages/r3f/devEnv/bundle.ts b/packages/r3f/devEnv/bundle.ts
index 7518abd..6a4b1be 100644
--- a/packages/r3f/devEnv/bundle.ts
+++ b/packages/r3f/devEnv/bundle.ts
@@ -8,11 +8,10 @@ const definedGlobals = {
'process.env.NODE_ENV': JSON.stringify('production'),
}
-createBundles()
+void createBundles()
async function createBundles() {
- createMainBundle()
- createExtensionBundle()
+ await Promise.all([createMainBundle(), createExtensionBundle()])
async function createMainBundle() {
const pathToEntry = path.join(__dirname, '../src/index.ts')
diff --git a/packages/react/devEnv/build.ts b/packages/react/devEnv/build.ts
index 599d720..69c3856 100644
--- a/packages/react/devEnv/build.ts
+++ b/packages/react/devEnv/build.ts
@@ -24,7 +24,7 @@ const definedGlobals = {
global: 'window',
}
-function createBundles(watch: boolean) {
+async function createBundles(watch: boolean) {
const pathToPackage = path.join(__dirname, '../')
const esbuildConfig: Parameters[0] = {
entryPoints: [path.join(pathToPackage, 'src/index.ts')],
@@ -39,7 +39,7 @@ function createBundles(watch: boolean) {
plugins: [externalPlugin([/^[\@a-zA-Z]+/])],
}
- build({
+ await build({
...esbuildConfig,
outfile: path.join(pathToPackage, 'dist/index.js'),
format: 'cjs',
@@ -52,4 +52,4 @@ function createBundles(watch: boolean) {
// })
}
-createBundles(false)
+void createBundles(false)
diff --git a/packages/theatric/devEnv/build.ts b/packages/theatric/devEnv/build.ts
index cb4c484..fad8649 100644
--- a/packages/theatric/devEnv/build.ts
+++ b/packages/theatric/devEnv/build.ts
@@ -24,7 +24,7 @@ const definedGlobals = {
global: 'window',
}
-function createBundles(watch: boolean) {
+async function createBundles(watch: boolean) {
const pathToPackage = path.join(__dirname, '../')
const pkgJson = require(path.join(pathToPackage, 'package.json'))
const listOfDependencies = Object.keys(pkgJson.dependencies || {})
@@ -52,7 +52,7 @@ function createBundles(watch: boolean) {
],
}
- build({
+ await build({
...esbuildConfig,
outfile: path.join(pathToPackage, 'dist/index.js'),
format: 'cjs',
@@ -65,4 +65,4 @@ function createBundles(watch: boolean) {
// })
}
-createBundles(false)
+void createBundles(false)
diff --git a/theatre/core/src/projects/Project.ts b/theatre/core/src/projects/Project.ts
index 1b0e5c1..e4d5895 100644
--- a/theatre/core/src/projects/Project.ts
+++ b/theatre/core/src/projects/Project.ts
@@ -196,29 +196,34 @@ export default class Project {
}
this._studio = studio
- studio.initialized.then(async () => {
- await initialiseProjectState(studio, this, this.config.state)
+ studio.initialized
+ .then(async () => {
+ await initialiseProjectState(studio, this, this.config.state)
- this._pointerProxies.historic.setPointer(
- studio.atomP.historic.coreByProject[this.address.projectId],
- )
- this._pointerProxies.ahistoric.setPointer(
- studio.atomP.ahistoric.coreByProject[this.address.projectId],
- )
- this._pointerProxies.ephemeral.setPointer(
- studio.atomP.ephemeral.coreByProject[this.address.projectId],
- )
+ this._pointerProxies.historic.setPointer(
+ studio.atomP.historic.coreByProject[this.address.projectId],
+ )
+ this._pointerProxies.ahistoric.setPointer(
+ studio.atomP.ahistoric.coreByProject[this.address.projectId],
+ )
+ this._pointerProxies.ephemeral.setPointer(
+ studio.atomP.ephemeral.coreByProject[this.address.projectId],
+ )
- // asset storage has to be initialized after the pointers are set
- studio
- .createAssetStorage(this, this.config.assets?.baseUrl)
- .then((assetStorage) => {
- this.assetStorage = assetStorage
- this._assetStorageReadyDeferred.resolve(undefined)
- })
+ // asset storage has to be initialized after the pointers are set
+ await studio
+ .createAssetStorage(this, this.config.assets?.baseUrl)
+ .then((assetStorage) => {
+ this.assetStorage = assetStorage
+ this._assetStorageReadyDeferred.resolve(undefined)
+ })
- this._studioReadyDeferred.resolve(undefined)
- })
+ this._studioReadyDeferred.resolve(undefined)
+ })
+ .catch((err) => {
+ console.error(err)
+ throw err
+ })
}
get isAttachedToStudio() {
diff --git a/theatre/core/src/sequences/TheatreSequence.ts b/theatre/core/src/sequences/TheatreSequence.ts
index 0121810..9c5d630 100644
--- a/theatre/core/src/sequences/TheatreSequence.ts
+++ b/theatre/core/src/sequences/TheatreSequence.ts
@@ -354,7 +354,9 @@ async function resolveAudioBuffer(args: IAttachAudioArgs): Promise<{
}
return new Promise((resolve) => {
const listener = () => {
- ctx.resume()
+ ctx.resume().catch((err) => {
+ console.error(err)
+ })
}
const eventsToHookInto: Array = [
@@ -412,6 +414,7 @@ async function resolveAudioBuffer(args: IAttachAudioArgs): Promise<{
const audioContext = await audioContextPromise
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
audioContext.decodeAudioData(
arrayBuffer,
decodedBufferDeferred.resolve,
diff --git a/theatre/devEnv/bundle.ts b/theatre/devEnv/bundle.ts
index 5e3b9df..7396b41 100644
--- a/theatre/devEnv/bundle.ts
+++ b/theatre/devEnv/bundle.ts
@@ -1,3 +1,3 @@
import {createBundles} from './createBundles'
-createBundles(false)
+void createBundles(false)
diff --git a/theatre/devEnv/watch.ts b/theatre/devEnv/watch.ts
index edd9759..71de62a 100644
--- a/theatre/devEnv/watch.ts
+++ b/theatre/devEnv/watch.ts
@@ -1,3 +1,3 @@
import {createBundles} from './createBundles'
-createBundles(true)
+void createBundles(true)
diff --git a/theatre/shared/src/testUtils.ts b/theatre/shared/src/testUtils.ts
index 9c51b75..bc3d443 100644
--- a/theatre/shared/src/testUtils.ts
+++ b/theatre/shared/src/testUtils.ts
@@ -28,7 +28,7 @@ const defaultProps = {
let lastProjectN = 0
const studio = getStudio()!
-studio.initialize({usePersistentStorage: false})
+void studio.initialize({usePersistentStorage: false})
export async function setupTestSheet(sheetState: SheetState_Historic) {
const projectState: ProjectState_Historic = {
diff --git a/theatre/studio/src/Studio.ts b/theatre/studio/src/Studio.ts
index e1bd052..12ddb0d 100644
--- a/theatre/studio/src/Studio.ts
+++ b/theatre/studio/src/Studio.ts
@@ -203,7 +203,9 @@ export class Studio {
if (process.env.NODE_ENV !== 'test') {
this.ui.render()
- checkForUpdates()
+ checkForUpdates().catch((err) => {
+ console.error(err)
+ })
}
}
@@ -266,7 +268,7 @@ export class Studio {
return this._coreAtom.pointer.core
}
- extend(extension: IExtension) {
+ extend(extension: IExtension, opts?: {__experimental_reconfigure?: boolean}) {
if (!extension || typeof extension !== 'object') {
throw new Error(`Extensions must be JS objects`)
}
@@ -275,20 +277,27 @@ export class Studio {
throw new Error(`extension.id must be a string`)
}
+ const reconfigure = opts?.__experimental_reconfigure === true
+
const extensionId = extension.id
const prevExtension =
this._store.getState().ephemeral.extensions.byId[extensionId]
if (prevExtension) {
- if (
- extension === prevExtension ||
- shallowEqual(extension, prevExtension)
- ) {
- // probably running studio.extend() several times because of hot reload.
- // as long as it's the same extension, we can safely ignore.
- return
+ if (reconfigure) {
+ } else {
+ if (
+ extension === prevExtension ||
+ shallowEqual(extension, prevExtension)
+ ) {
+ // probably running studio.extend() several times because of hot reload.
+ // as long as it's the same extension, we can safely ignore.
+ return
+ }
+ throw new Error(
+ `Extension id "${extension.id}" is already defined. If you mean to re-configure the extension, do it like this: studio.extend(extension, {__experimental_reconfigure: true})})`,
+ )
}
- throw new Error(`Extension id "${extension.id}" is already defined`)
}
this.transaction(({drafts}) => {
@@ -296,6 +305,14 @@ export class Studio {
const allPaneClasses = drafts.ephemeral.extensions.paneClasses
+ if (reconfigure && prevExtension) {
+ // remove all pane classes that were set by the previous version of the extension
+ prevExtension.panes?.forEach((classDefinition) => {
+ delete allPaneClasses[classDefinition.class]
+ })
+ }
+
+ // if the extension defines pane classes, add them to the list of all pane classes
extension.panes?.forEach((classDefinition) => {
if (typeof classDefinition.class !== 'string') {
throw new Error(`pane.class must be a string`)
@@ -309,9 +326,16 @@ export class Studio {
const existing = allPaneClasses[classDefinition.class]
if (existing) {
- throw new Error(
- `Pane class "${classDefinition.class}" already exists and is supplied by extension ${existing}`,
- )
+ if (reconfigure && existing.extensionId === extension.id) {
+ // well this should never happen because we already deleted the pane class above
+ console.warn(
+ `Pane class "${classDefinition.class}" already exists. This is a bug in Theatre.js. Please report it at https://github.com/theatre-js/theatre/issues/new`,
+ )
+ } else {
+ throw new Error(
+ `Pane class "${classDefinition.class}" already exists and is supplied by extension ${existing}`,
+ )
+ }
}
allPaneClasses[classDefinition.class] = {
diff --git a/theatre/studio/src/UI/UI.ts b/theatre/studio/src/UI/UI.ts
index b7d9704..4ecd79d 100644
--- a/theatre/studio/src/UI/UI.ts
+++ b/theatre/studio/src/UI/UI.ts
@@ -24,9 +24,14 @@ export default class UI {
}
this._rendered = true
- this._nonSSRBits.then((b) => {
- b.render()
- })
+ this._nonSSRBits
+ .then((b) => {
+ b.render()
+ })
+ .catch((err) => {
+ console.error(err)
+ throw err
+ })
}
hide() {
@@ -53,10 +58,14 @@ export default class UI {
let unmount: null | (() => void) = null
- this._nonSSRBits.then((nonSSRBits) => {
- if (shouldUnmount) return // unmount requested before the toolset is mounted, so, abort
- unmount = nonSSRBits.renderToolset(toolsetId, htmlNode)
- })
+ this._nonSSRBits
+ .then((nonSSRBits) => {
+ if (shouldUnmount) return // unmount requested before the toolset is mounted, so, abort
+ unmount = nonSSRBits.renderToolset(toolsetId, htmlNode)
+ })
+ .catch((err) => {
+ console.error(err)
+ })
return () => {
if (unmount) {