Fix the dangling promises
This commit is contained in:
parent
27f918f53c
commit
041627f7e4
19 changed files with 112 additions and 67 deletions
|
@ -66,6 +66,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'@typescript-eslint/no-unused-vars': 'off',
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
'@typescript-eslint/no-floating-promises': 'warn',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,6 +106,6 @@ async function test1() {
|
||||||
iterateOnSequence()
|
iterateOnSequence()
|
||||||
}
|
}
|
||||||
|
|
||||||
test1().then(() => {
|
void test1().then(() => {
|
||||||
console.log('test1 done')
|
console.log('test1 done')
|
||||||
})
|
})
|
||||||
|
|
|
@ -35,14 +35,14 @@ function createBundles(watch: boolean) {
|
||||||
// format: 'iife',
|
// format: 'iife',
|
||||||
// })
|
// })
|
||||||
|
|
||||||
build({
|
void build({
|
||||||
...esbuildConfig,
|
...esbuildConfig,
|
||||||
entryPoints: [path.join(pathToPackage, 'src/core-and-studio.ts')],
|
entryPoints: [path.join(pathToPackage, 'src/core-and-studio.ts')],
|
||||||
outfile: path.join(pathToPackage, 'dist/core-and-studio.js'),
|
outfile: path.join(pathToPackage, 'dist/core-and-studio.js'),
|
||||||
format: 'iife',
|
format: 'iife',
|
||||||
})
|
})
|
||||||
|
|
||||||
build({
|
void build({
|
||||||
...esbuildConfig,
|
...esbuildConfig,
|
||||||
entryPoints: [path.join(pathToPackage, 'src/core-only.ts')],
|
entryPoints: [path.join(pathToPackage, 'src/core-only.ts')],
|
||||||
outfile: path.join(pathToPackage, 'dist/core-only.min.js'),
|
outfile: path.join(pathToPackage, 'dist/core-only.min.js'),
|
||||||
|
|
|
@ -17,7 +17,7 @@ function createBundles(watch: boolean) {
|
||||||
conditions: ['browser', 'node'],
|
conditions: ['browser', 'node'],
|
||||||
}
|
}
|
||||||
|
|
||||||
build({
|
void build({
|
||||||
...esbuildConfig,
|
...esbuildConfig,
|
||||||
outfile: path.join(pathToPackage, 'dist/index.js'),
|
outfile: path.join(pathToPackage, 'dist/index.js'),
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
|
|
|
@ -53,7 +53,7 @@ const ImageTypeExample: React.FC<{}> = (props) => {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (sheet.sequence.position === 0) {
|
if (sheet.sequence.position === 0) {
|
||||||
sheet.sequence.position = 0
|
sheet.sequence.position = 0
|
||||||
sheet.sequence.play()
|
void sheet.sequence.play()
|
||||||
} else {
|
} else {
|
||||||
sheet.sequence.position = 0
|
sheet.sequence.position = 0
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,10 @@ const ImageTypeExample: React.FC<{}> = (props) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
project.ready.then(() => {
|
project.ready
|
||||||
|
.then(() => {
|
||||||
render(<ImageTypeExample />, document.getElementById('root'))
|
render(<ImageTypeExample />, document.getElementById('root'))
|
||||||
})
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {Scene} from './Scene'
|
||||||
studio.initialize()
|
studio.initialize()
|
||||||
|
|
||||||
// trigger warning notification
|
// trigger warning notification
|
||||||
getProject('Sample project').sheet('Scene').sequence.play()
|
void getProject('Sample project').sheet('Scene').sequence.play()
|
||||||
|
|
||||||
// fire an info notification
|
// fire an info notification
|
||||||
notify.info(
|
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.',
|
'(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
|
// fire a success notification on project load
|
||||||
notify.success(
|
notify.success(
|
||||||
'Project loaded!',
|
'Project loaded!',
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {render} from 'react-dom'
|
||||||
import React, {useState} from 'react'
|
import React, {useState} from 'react'
|
||||||
import state from './state.json'
|
import state from './state.json'
|
||||||
|
|
||||||
initialize({state})
|
void initialize({state})
|
||||||
|
|
||||||
function SomeComponent({id}: {id: string}) {
|
function SomeComponent({id}: {id: string}) {
|
||||||
const {foo, $get, $set} = useControls(
|
const {foo, $get, $set} = useControls(
|
||||||
|
|
|
@ -76,7 +76,7 @@ function App() {
|
||||||
const bg = bgs[bgIndex]
|
const bg = bgs[bgIndex]
|
||||||
const project = getProject('SpaceStress', {state})
|
const project = getProject('SpaceStress', {state})
|
||||||
const sheet = project.sheet('Scene')
|
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)
|
const allPropsObj = sheet.object('All Props Tester', allPropsObjectConfig)
|
||||||
console.log('allPropsObj', allPropsObj)
|
console.log('allPropsObj', allPropsObj)
|
||||||
|
|
|
@ -39,13 +39,13 @@ const elements = new Array(TOTAL_ELEMENTS).fill(0).map((_, idx) => {
|
||||||
return {el, sheet, obj}
|
return {el, sheet, obj}
|
||||||
})
|
})
|
||||||
|
|
||||||
project.ready.then(() => {
|
void project.ready.then(() => {
|
||||||
// select the playback controls obj so it shows as a tweakable control
|
// select the playback controls obj so it shows as a tweakable control
|
||||||
studio.setSelection([playbackControlObj])
|
studio.setSelection([playbackControlObj])
|
||||||
for (let i = 0; i < elements.length; i++) {
|
for (let i = 0; i < elements.length; i++) {
|
||||||
const sheet = elements[i].sheet
|
const sheet = elements[i].sheet
|
||||||
sheet.sequence.position = i * TOTAL_ELEMENTS_R * 5
|
sheet.sequence.position = i * TOTAL_ELEMENTS_R * 5
|
||||||
sheet.sequence.play({
|
void sheet.sequence.play({
|
||||||
iterationCount: Infinity,
|
iterationCount: Infinity,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,10 @@ const definedGlobals = {
|
||||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||||
}
|
}
|
||||||
|
|
||||||
createBundles()
|
void createBundles()
|
||||||
|
|
||||||
async function createBundles() {
|
async function createBundles() {
|
||||||
createMainBundle()
|
await Promise.all([createMainBundle(), createExtensionBundle()])
|
||||||
createExtensionBundle()
|
|
||||||
|
|
||||||
async function createMainBundle() {
|
async function createMainBundle() {
|
||||||
const pathToEntry = path.join(__dirname, '../src/index.ts')
|
const pathToEntry = path.join(__dirname, '../src/index.ts')
|
||||||
|
|
|
@ -24,7 +24,7 @@ const definedGlobals = {
|
||||||
global: 'window',
|
global: 'window',
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBundles(watch: boolean) {
|
async function createBundles(watch: boolean) {
|
||||||
const pathToPackage = path.join(__dirname, '../')
|
const pathToPackage = path.join(__dirname, '../')
|
||||||
const esbuildConfig: Parameters<typeof build>[0] = {
|
const esbuildConfig: Parameters<typeof build>[0] = {
|
||||||
entryPoints: [path.join(pathToPackage, 'src/index.ts')],
|
entryPoints: [path.join(pathToPackage, 'src/index.ts')],
|
||||||
|
@ -39,7 +39,7 @@ function createBundles(watch: boolean) {
|
||||||
plugins: [externalPlugin([/^[\@a-zA-Z]+/])],
|
plugins: [externalPlugin([/^[\@a-zA-Z]+/])],
|
||||||
}
|
}
|
||||||
|
|
||||||
build({
|
await build({
|
||||||
...esbuildConfig,
|
...esbuildConfig,
|
||||||
outfile: path.join(pathToPackage, 'dist/index.js'),
|
outfile: path.join(pathToPackage, 'dist/index.js'),
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
|
@ -52,4 +52,4 @@ function createBundles(watch: boolean) {
|
||||||
// })
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
createBundles(false)
|
void createBundles(false)
|
||||||
|
|
|
@ -24,7 +24,7 @@ const definedGlobals = {
|
||||||
global: 'window',
|
global: 'window',
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBundles(watch: boolean) {
|
async function createBundles(watch: boolean) {
|
||||||
const pathToPackage = path.join(__dirname, '../')
|
const pathToPackage = path.join(__dirname, '../')
|
||||||
const pkgJson = require(path.join(pathToPackage, 'package.json'))
|
const pkgJson = require(path.join(pathToPackage, 'package.json'))
|
||||||
const listOfDependencies = Object.keys(pkgJson.dependencies || {})
|
const listOfDependencies = Object.keys(pkgJson.dependencies || {})
|
||||||
|
@ -52,7 +52,7 @@ function createBundles(watch: boolean) {
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
build({
|
await build({
|
||||||
...esbuildConfig,
|
...esbuildConfig,
|
||||||
outfile: path.join(pathToPackage, 'dist/index.js'),
|
outfile: path.join(pathToPackage, 'dist/index.js'),
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
|
@ -65,4 +65,4 @@ function createBundles(watch: boolean) {
|
||||||
// })
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
createBundles(false)
|
void createBundles(false)
|
||||||
|
|
|
@ -196,7 +196,8 @@ export default class Project {
|
||||||
}
|
}
|
||||||
this._studio = studio
|
this._studio = studio
|
||||||
|
|
||||||
studio.initialized.then(async () => {
|
studio.initialized
|
||||||
|
.then(async () => {
|
||||||
await initialiseProjectState(studio, this, this.config.state)
|
await initialiseProjectState(studio, this, this.config.state)
|
||||||
|
|
||||||
this._pointerProxies.historic.setPointer(
|
this._pointerProxies.historic.setPointer(
|
||||||
|
@ -210,7 +211,7 @@ export default class Project {
|
||||||
)
|
)
|
||||||
|
|
||||||
// asset storage has to be initialized after the pointers are set
|
// asset storage has to be initialized after the pointers are set
|
||||||
studio
|
await studio
|
||||||
.createAssetStorage(this, this.config.assets?.baseUrl)
|
.createAssetStorage(this, this.config.assets?.baseUrl)
|
||||||
.then((assetStorage) => {
|
.then((assetStorage) => {
|
||||||
this.assetStorage = assetStorage
|
this.assetStorage = assetStorage
|
||||||
|
@ -219,6 +220,10 @@ export default class Project {
|
||||||
|
|
||||||
this._studioReadyDeferred.resolve(undefined)
|
this._studioReadyDeferred.resolve(undefined)
|
||||||
})
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
get isAttachedToStudio() {
|
get isAttachedToStudio() {
|
||||||
|
|
|
@ -354,7 +354,9 @@ async function resolveAudioBuffer(args: IAttachAudioArgs): Promise<{
|
||||||
}
|
}
|
||||||
return new Promise<AudioContext>((resolve) => {
|
return new Promise<AudioContext>((resolve) => {
|
||||||
const listener = () => {
|
const listener = () => {
|
||||||
ctx.resume()
|
ctx.resume().catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const eventsToHookInto: Array<keyof WindowEventMap> = [
|
const eventsToHookInto: Array<keyof WindowEventMap> = [
|
||||||
|
@ -412,6 +414,7 @@ async function resolveAudioBuffer(args: IAttachAudioArgs): Promise<{
|
||||||
|
|
||||||
const audioContext = await audioContextPromise
|
const audioContext = await audioContextPromise
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
audioContext.decodeAudioData(
|
audioContext.decodeAudioData(
|
||||||
arrayBuffer,
|
arrayBuffer,
|
||||||
decodedBufferDeferred.resolve,
|
decodedBufferDeferred.resolve,
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import {createBundles} from './createBundles'
|
import {createBundles} from './createBundles'
|
||||||
|
|
||||||
createBundles(false)
|
void createBundles(false)
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import {createBundles} from './createBundles'
|
import {createBundles} from './createBundles'
|
||||||
|
|
||||||
createBundles(true)
|
void createBundles(true)
|
||||||
|
|
|
@ -28,7 +28,7 @@ const defaultProps = {
|
||||||
let lastProjectN = 0
|
let lastProjectN = 0
|
||||||
|
|
||||||
const studio = getStudio()!
|
const studio = getStudio()!
|
||||||
studio.initialize({usePersistentStorage: false})
|
void studio.initialize({usePersistentStorage: false})
|
||||||
|
|
||||||
export async function setupTestSheet(sheetState: SheetState_Historic) {
|
export async function setupTestSheet(sheetState: SheetState_Historic) {
|
||||||
const projectState: ProjectState_Historic = {
|
const projectState: ProjectState_Historic = {
|
||||||
|
|
|
@ -203,7 +203,9 @@ export class Studio {
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'test') {
|
if (process.env.NODE_ENV !== 'test') {
|
||||||
this.ui.render()
|
this.ui.render()
|
||||||
checkForUpdates()
|
checkForUpdates().catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +268,7 @@ export class Studio {
|
||||||
return this._coreAtom.pointer.core
|
return this._coreAtom.pointer.core
|
||||||
}
|
}
|
||||||
|
|
||||||
extend(extension: IExtension) {
|
extend(extension: IExtension, opts?: {__experimental_reconfigure?: boolean}) {
|
||||||
if (!extension || typeof extension !== 'object') {
|
if (!extension || typeof extension !== 'object') {
|
||||||
throw new Error(`Extensions must be JS objects`)
|
throw new Error(`Extensions must be JS objects`)
|
||||||
}
|
}
|
||||||
|
@ -275,11 +277,15 @@ export class Studio {
|
||||||
throw new Error(`extension.id must be a string`)
|
throw new Error(`extension.id must be a string`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const reconfigure = opts?.__experimental_reconfigure === true
|
||||||
|
|
||||||
const extensionId = extension.id
|
const extensionId = extension.id
|
||||||
|
|
||||||
const prevExtension =
|
const prevExtension =
|
||||||
this._store.getState().ephemeral.extensions.byId[extensionId]
|
this._store.getState().ephemeral.extensions.byId[extensionId]
|
||||||
if (prevExtension) {
|
if (prevExtension) {
|
||||||
|
if (reconfigure) {
|
||||||
|
} else {
|
||||||
if (
|
if (
|
||||||
extension === prevExtension ||
|
extension === prevExtension ||
|
||||||
shallowEqual(extension, prevExtension)
|
shallowEqual(extension, prevExtension)
|
||||||
|
@ -288,7 +294,10 @@ export class Studio {
|
||||||
// as long as it's the same extension, we can safely ignore.
|
// as long as it's the same extension, we can safely ignore.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw new Error(`Extension id "${extension.id}" is already defined`)
|
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})})`,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.transaction(({drafts}) => {
|
this.transaction(({drafts}) => {
|
||||||
|
@ -296,6 +305,14 @@ export class Studio {
|
||||||
|
|
||||||
const allPaneClasses = drafts.ephemeral.extensions.paneClasses
|
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) => {
|
extension.panes?.forEach((classDefinition) => {
|
||||||
if (typeof classDefinition.class !== 'string') {
|
if (typeof classDefinition.class !== 'string') {
|
||||||
throw new Error(`pane.class must be a string`)
|
throw new Error(`pane.class must be a string`)
|
||||||
|
@ -309,10 +326,17 @@ export class Studio {
|
||||||
|
|
||||||
const existing = allPaneClasses[classDefinition.class]
|
const existing = allPaneClasses[classDefinition.class]
|
||||||
if (existing) {
|
if (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(
|
throw new Error(
|
||||||
`Pane class "${classDefinition.class}" already exists and is supplied by extension ${existing}`,
|
`Pane class "${classDefinition.class}" already exists and is supplied by extension ${existing}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
allPaneClasses[classDefinition.class] = {
|
allPaneClasses[classDefinition.class] = {
|
||||||
extensionId: extension.id,
|
extensionId: extension.id,
|
||||||
|
|
|
@ -24,9 +24,14 @@ export default class UI {
|
||||||
}
|
}
|
||||||
this._rendered = true
|
this._rendered = true
|
||||||
|
|
||||||
this._nonSSRBits.then((b) => {
|
this._nonSSRBits
|
||||||
|
.then((b) => {
|
||||||
b.render()
|
b.render()
|
||||||
})
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
|
@ -53,10 +58,14 @@ export default class UI {
|
||||||
|
|
||||||
let unmount: null | (() => void) = null
|
let unmount: null | (() => void) = null
|
||||||
|
|
||||||
this._nonSSRBits.then((nonSSRBits) => {
|
this._nonSSRBits
|
||||||
|
.then((nonSSRBits) => {
|
||||||
if (shouldUnmount) return // unmount requested before the toolset is mounted, so, abort
|
if (shouldUnmount) return // unmount requested before the toolset is mounted, so, abort
|
||||||
unmount = nonSSRBits.renderToolset(toolsetId, htmlNode)
|
unmount = nonSSRBits.renderToolset(toolsetId, htmlNode)
|
||||||
})
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (unmount) {
|
if (unmount) {
|
||||||
|
|
Loading…
Reference in a new issue