fix(vast): [PKG-VAST-03] preserve npm initialization with explicit workspace mode

This commit is contained in:
Harvey Zhao committed 2026-09-14 22:42:57 +08:00
1 parent 314a1c3163
commit c162d2b3b3
27 files changed
+13189 -191

No files matched your search

+12 -3
View File
@@ -1,9 +1,13 @@
import type Artplayer from 'artplayer'
import type { Callback, Result } from './types'
import type { Callback, CompatibilityOptions, Result } from './types'
import { loadImaSdk } from './sdk'
import { createSession } from './session'
function artplayerPluginVast(callback?: Callback) {
function artplayerPluginVast(callback?: Callback, options: CompatibilityOptions = {}) {
const compatibility = options.compatibility
if (compatibility !== undefined && compatibility !== 'workspace-1.2')
throw new TypeError('Unsupported VAST compatibility mode')
const workspaceMode = compatibility === 'workspace-1.2'
return async (art: Artplayer): Promise<Result> => {
let disposed = false
let session: ReturnType<typeof createSession> | undefined
@@ -28,11 +32,16 @@ function artplayerPluginVast(callback?: Callback) {
if (closed())
return result
const utils = (art.constructor as typeof Artplayer).utils
session = createSession(art, ima, utils, closed)
session = createSession(art, ima, utils, closed, workspaceMode)
if (closed()) {
dispose()
return result
}
if (!workspaceMode) {
session.context.init()
if (closed())
return result
}
if (typeof callback === 'function')
await callback(session.context)
return result
+45 -22
View File
@@ -12,16 +12,39 @@ interface Owner {
released: boolean
}
export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, closed: () => boolean) {
export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, closed: () => boolean, workspaceMode: boolean) {
const { $video, $player } = art.template
const adsRenderingSettings = new ima.AdsRenderingSettings()
adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true
adsRenderingSettings.enablePreloading = true
if (workspaceMode) {
adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true
adsRenderingSettings.enablePreloading = true
}
const playerOptions = new PlayerOptions()
let current: Owner | null = null
let initializing = false
let releasing = 0
const context: Context = {
art,
playUrl: (url, config = {}) => play('adTagUrl', url, config),
playRes: (response, config = {}) => play('adsResponse', response, config),
init,
ima,
adsRenderingSettings,
playerOptions,
imaPlayer: null,
id: null,
$container: null,
get container() { return current?.container || null },
}
if (workspaceMode) {
Object.defineProperties(context, {
imaPlayer: { get: () => current?.player || null },
id: { get: () => current?.container.id || null },
$container: { get: () => current?.container || null },
})
}
const live = (owner: Owner) => current === owner && !owner.released && !closed()
function release(owner: Owner): void {
@@ -77,7 +100,7 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo
initializing = true
let owner: Owner | undefined
try {
owner = { container: createContainer(utils), player: null, listeners: [], playing: false, released: false }
owner = { container: createContainer(utils, workspaceMode), player: null, listeners: [], playing: false, released: false }
current = owner
if (!live(owner)) {
release(owner)
@@ -94,12 +117,15 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo
return null
}
const allocated = owner
for (const [name, playing] of [
['AdContentPauseRequested', true],
['AdContentResumeRequested', false],
['AdStarted', true],
['AdError', false],
] as const) {
const events = workspaceMode
? [
['AdContentPauseRequested', true],
['AdContentResumeRequested', false],
['AdStarted', true],
['AdError', false],
] as const
: []
for (const [name, playing] of events) {
const callback: EventListener = (event) => {
if (!live(allocated))
return
@@ -115,6 +141,14 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo
return null
}
}
if (!workspaceMode) {
// Published fields are writable data properties, not the workspace getters.
Object.defineProperties(context, {
imaPlayer: { value: owner.player },
id: { value: owner.container.id },
$container: { value: owner.container },
})
}
return owner.player
}
catch (error) {
@@ -132,7 +166,7 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo
}
function play(field: 'adTagUrl' | 'adsResponse', value: string, config: RequestConfig): void {
if (closed() || current?.playing)
if (closed() || (workspaceMode && current?.playing))
return
const player = init()
const owner = current
@@ -149,16 +183,5 @@ export function createSession(art: Artplayer, ima: ImaSdk, utils: Utilities, clo
release(current)
}
const context: Context = {
art,
playUrl: (url, config = {}) => play('adTagUrl', url, config),
playRes: (response, config = {}) => play('adsResponse', response, config),
init,
ima,
adsRenderingSettings,
playerOptions,
get imaPlayer() { return current?.player || null },
get container() { return current?.container || null },
}
return { context, destroy }
}
@@ -5,6 +5,10 @@ import type Artplayer from 'artplayer'
export type Utilities = Pick<typeof Artplayer.utils, 'createElement' | 'setStyles'>
export type RequestConfig = Record<string, unknown>
export interface CompatibilityOptions {
compatibility?: 'workspace-1.2'
}
export interface Context {
art: Artplayer
playUrl: (url: string, config?: RequestConfig) => void
@@ -14,6 +18,8 @@ export interface Context {
adsRenderingSettings: google.ima.AdsRenderingSettings
playerOptions: PlayerOptions
readonly imaPlayer: Player | null
readonly id: string | null
readonly $container: HTMLDivElement | null
readonly container: HTMLDivElement | null
}
+4 -4
View File
@@ -2,18 +2,18 @@ import type { Utilities } from './types'
let nextId = 0
export function createContainer(utils: Utilities): HTMLDivElement {
export function createContainer(utils: Utilities, workspaceMode: boolean): HTMLDivElement {
const container = utils.createElement('div')
container.id = `art-vast-${Date.now()}-${++nextId}`
container.id = `${workspaceMode ? 'art-vast-' : 'art-'}${Date.now()}-${++nextId}`
utils.setStyles(container, {
position: 'absolute',
inset: '0',
width: '100%',
height: '100%',
zIndex: '150',
backgroundColor: 'black',
display: 'none',
pointerEvents: 'auto',
})
if (workspaceMode)
utils.setStyles(container, { backgroundColor: 'black', pointerEvents: 'auto' })
return container
}