Skip to content

Commit

Permalink
fix(script)!: eventContext option, skip onabort, onprogress events
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw committed Mar 23, 2024
1 parent 7cba505 commit 335f419
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 23 deletions.
6 changes: 6 additions & 0 deletions packages/schema/src/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,10 @@ export interface UseScriptOptions<T> extends Omit<HeadEntryOptions, 'transform'>
* - `Promise` - Load the script when the promise resolves.
*/
trigger?: 'idle' | 'manual' | Promise<void>
trigger?: 'manual' | Promise<void>
/**
* Context to run events with. This is useful in Vue to attach the current instance context before
* calling the event, allowing the event to be reactive.
*/
eventContext?: any
}
1 change: 1 addition & 0 deletions packages/shared/src/script.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const NetworkEvents = ['onload', 'onerror', 'onabort', 'onprogress', 'onloadstart']
export const ScriptNetworkEvents = ['onload', 'onerror', 'onloadstart']
20 changes: 9 additions & 11 deletions packages/unhead/src/composables/useScript.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NetworkEvents, hashCode } from '@unhead/shared'
import { ScriptNetworkEvents, hashCode } from '@unhead/shared'
import type {
DomRenderTagContext,
Head,
Expand Down Expand Up @@ -84,16 +84,14 @@ export function useScript<T>(_input: UseScriptInput, _options?: UseScriptOptions
})

const hookCtx = { script }

NetworkEvents.forEach((fn) => {
// clone fn
const _fn = typeof input[fn] === 'function' ? input[fn].bind({}) : null
input[fn] = (e: Event) => {
script.status = fn === 'onload' ? 'loaded' : fn === 'onerror' ? 'error' : 'loading'
head.hooks.callHook(`script:updated`, hookCtx)
_fn && _fn(e)
}
})
ScriptNetworkEvents
.forEach((fn) => {
input[fn] = (e: Event) => {
script.status = fn === 'onload' ? 'loaded' : fn === 'onerror' ? 'error' : 'loading'
head.hooks.callHook(`script:updated`, hookCtx)
typeof input[fn] === 'function' && input[fn].call(options.eventContext, e)
}
})

const trigger = options.trigger
if (options.trigger)
Expand Down
12 changes: 1 addition & 11 deletions packages/vue/src/composables/useScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,12 @@ export type UseScriptInput = string | (MaybeComputedRefEntriesOnly<Omit<ScriptBa
export function useScript<T>(_input: UseScriptInput, _options?: UseScriptOptions<T>): T & { $script: VueScriptInstance<T> } {
const input = typeof _input === 'string' ? { src: _input } : _input
const head = injectHead()
const ctx = getCurrentInstance()
const options = _options || {}
// @ts-expect-error untyped
options.head = head
options.eventContext = getCurrentInstance()
const status = ref('awaitingLoad')

NetworkEvents.forEach((fn) => {
// @ts-expect-error untyped
const _fn = typeof input[fn] === 'function' ? input[fn].bind(ctx) : null
// rebinding the events for the vue context
if (_fn) {
// @ts-expect-error untyped
input[fn] = (e: Event) => _fn(e)
}
})

options.stub = ({ script, fn }) => {
if (fn === '$script') {
return Object.assign(script, {
Expand Down
2 changes: 1 addition & 1 deletion test/unhead/dom/useScript.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('dom useScript', () => {
expect(await useDelayedSerializedDom()).toMatchInlineSnapshot(`
"<!DOCTYPE html><html><head>
<script data-onload="" data-onerror="" data-onabort="" data-onprogress="" data-onloadstart="" defer="" fetchpriority="low" src="https://cdn.example.com/script.js" data-hid="438d65b"></script></head>
<script data-onload="" data-onerror="" data-onloadstart="" defer="" fetchpriority="low" src="https://cdn.example.com/script.js" data-hid="438d65b"></script></head>
<body>
<div>
Expand Down

0 comments on commit 335f419

Please sign in to comment.