@@ -6,12 +6,14 @@ import { getDetails } from './script-handler.js';
6
6
import { registry as defaultRegistry , prefixes , configs } from './interpreters.js' ;
7
7
import { getRuntimeID } from './loader.js' ;
8
8
import { addAllListeners } from './listeners.js' ;
9
- import { Hook , XWorker } from './xworker.js' ;
9
+ import { Hook , XWorker as XW } from './xworker.js' ;
10
10
import { polluteJS , js as jsHooks , code as codeHooks } from './hooks.js' ;
11
11
import workerURL from './worker/url.js' ;
12
12
13
13
export const CUSTOM_SELECTORS = [ ] ;
14
14
15
+ export const customObserver = new Map ( ) ;
16
+
15
17
/**
16
18
* @typedef {Object } Runtime custom configuration
17
19
* @prop {object } interpreter the bootstrapped interpreter
@@ -30,131 +32,137 @@ const waitList = new Map();
30
32
/**
31
33
* @param {Element } node any DOM element registered via define.
32
34
*/
33
- export const handleCustomType = ( node ) => {
35
+ export const handleCustomType = async ( node ) => {
34
36
for ( const selector of CUSTOM_SELECTORS ) {
35
37
if ( node . matches ( selector ) ) {
36
38
const type = types . get ( selector ) ;
37
39
const details = registry . get ( type ) ;
38
40
const { resolve } = waitList . get ( type ) ;
39
41
const { options, known } = details ;
40
- if ( ! known . has ( node ) ) {
41
- known . add ( node ) ;
42
- const {
43
- interpreter : runtime ,
44
- configURL,
45
- config,
46
- version,
47
- env,
48
- onerror,
49
- hooks,
50
- } = options ;
51
-
52
- let error ;
53
- try {
54
- const worker = workerURL ( node ) ;
55
- if ( worker ) {
56
- const xworker = XWorker . call ( new Hook ( null , hooks ) , worker , {
57
- ...nodeInfo ( node , type ) ,
58
- version,
59
- configURL,
60
- type : runtime ,
61
- custom : type ,
62
- config : node . getAttribute ( 'config' ) || config || { } ,
63
- async : node . hasAttribute ( 'async' )
64
- } ) ;
65
- defineProperty ( node , 'xworker' , { value : xworker } ) ;
66
- resolve ( { type, xworker } ) ;
67
- return ;
68
- }
69
- }
70
- // let the custom type handle errors via its `io`
71
- catch ( workerError ) {
72
- error = workerError ;
42
+
43
+ if ( known . has ( node ) ) return ;
44
+ known . add ( node ) ;
45
+
46
+ for ( const [ selector , callback ] of customObserver ) {
47
+ if ( node . matches ( selector ) ) await callback ( node ) ;
48
+ }
49
+
50
+ const {
51
+ interpreter : runtime ,
52
+ configURL,
53
+ config,
54
+ version,
55
+ env,
56
+ onerror,
57
+ hooks,
58
+ } = options ;
59
+
60
+ let error ;
61
+ try {
62
+ const worker = workerURL ( node ) ;
63
+ if ( worker ) {
64
+ const xworker = XW . call ( new Hook ( null , hooks ) , worker , {
65
+ ...nodeInfo ( node , type ) ,
66
+ version,
67
+ configURL,
68
+ type : runtime ,
69
+ custom : type ,
70
+ config : node . getAttribute ( 'config' ) || config || { } ,
71
+ async : node . hasAttribute ( 'async' )
72
+ } ) ;
73
+ defineProperty ( node , 'xworker' , { value : xworker } ) ;
74
+ resolve ( { type, xworker } ) ;
75
+ return ;
73
76
}
77
+ }
78
+ // let the custom type handle errors via its `io`
79
+ catch ( workerError ) {
80
+ error = workerError ;
81
+ }
82
+
83
+ const name = getRuntimeID ( runtime , version ) ;
84
+ const id = env || `${ name } ${ config ? `|${ config } ` : '' } ` ;
85
+ const { interpreter : engine , XWorker : Worker } = getDetails (
86
+ type ,
87
+ id ,
88
+ name ,
89
+ version ,
90
+ config ,
91
+ configURL ,
92
+ runtime
93
+ ) ;
94
+
95
+ const interpreter = await engine ;
74
96
75
- const name = getRuntimeID ( runtime , version ) ;
76
- const id = env || `${ name } ${ config ? `|${ config } ` : '' } ` ;
77
- const { interpreter : engine , XWorker : Worker } = getDetails (
97
+ const module = create ( defaultRegistry . get ( runtime ) ) ;
98
+
99
+ const hook = new Hook ( interpreter , hooks ) ;
100
+
101
+ const XWorker = function XWorker ( ...args ) {
102
+ return Worker . apply ( hook , args ) ;
103
+ } ;
104
+
105
+ const resolved = {
106
+ ...createResolved (
107
+ module ,
78
108
type ,
79
- id ,
80
- name ,
81
- version ,
82
- config ,
83
- configURL ,
84
- runtime
85
- ) ;
86
- engine . then ( ( interpreter ) => {
87
- const module = create ( defaultRegistry . get ( runtime ) ) ;
88
-
89
- const hook = new Hook ( interpreter , hooks ) ;
90
-
91
- const XWorker = function XWorker ( ...args ) {
92
- return Worker . apply ( hook , args ) ;
93
- } ;
94
-
95
- const resolved = {
96
- ...createResolved (
97
- module ,
98
- type ,
99
- structuredClone ( configs . get ( name ) ) ,
100
- interpreter ,
101
- ) ,
102
- XWorker,
103
- } ;
104
-
105
- registerJSModules ( runtime , module , interpreter , JSModules ) ;
106
- module . registerJSModule ( interpreter , 'polyscript' , {
107
- XWorker,
108
- currentScript : type . startsWith ( '_' ) ? null : node ,
109
- js_modules : JSModules ,
110
- } ) ;
109
+ structuredClone ( configs . get ( name ) ) ,
110
+ interpreter ,
111
+ ) ,
112
+ XWorker,
113
+ } ;
111
114
112
- // patch methods accordingly to hooks (and only if needed)
113
- for ( const suffix of [ 'Run' , 'RunAsync' ] ) {
114
- let before = '' ;
115
- let after = '' ;
116
-
117
- for ( const key of codeHooks ) {
118
- const value = hooks ?. main ?. [ key ] ;
119
- if ( value && key . endsWith ( suffix ) ) {
120
- if ( key . startsWith ( 'codeBefore' ) )
121
- before = dedent ( value ( ) ) ;
122
- else
123
- after = dedent ( value ( ) ) ;
124
- }
125
- }
126
-
127
- if ( before || after ) {
128
- createOverload (
129
- module ,
130
- `r${ suffix . slice ( 1 ) } ` ,
131
- before ,
132
- after ,
133
- ) ;
134
- }
135
-
136
- let beforeCB , afterCB ;
137
- // ignore onReady and onWorker
138
- for ( let i = 2 ; i < jsHooks . length ; i ++ ) {
139
- const key = jsHooks [ i ] ;
140
- const value = hooks ?. main ?. [ key ] ;
141
- if ( value && key . endsWith ( suffix ) ) {
142
- if ( key . startsWith ( 'onBefore' ) )
143
- beforeCB = value ;
144
- else
145
- afterCB = value ;
146
- }
147
- }
148
- polluteJS ( module , resolved , node , suffix . endsWith ( 'Async' ) , beforeCB , afterCB ) ;
115
+ registerJSModules ( runtime , module , interpreter , JSModules ) ;
116
+ module . registerJSModule ( interpreter , 'polyscript' , {
117
+ XWorker,
118
+ currentScript : type . startsWith ( '_' ) ? null : node ,
119
+ js_modules : JSModules ,
120
+ } ) ;
121
+
122
+ // patch methods accordingly to hooks (and only if needed)
123
+ for ( const suffix of [ 'Run' , 'RunAsync' ] ) {
124
+ let before = '' ;
125
+ let after = '' ;
126
+
127
+ for ( const key of codeHooks ) {
128
+ const value = hooks ?. main ?. [ key ] ;
129
+ if ( value && key . endsWith ( suffix ) ) {
130
+ if ( key . startsWith ( 'codeBefore' ) )
131
+ before = dedent ( value ( ) ) ;
132
+ else
133
+ after = dedent ( value ( ) ) ;
149
134
}
135
+ }
150
136
151
- details . queue = details . queue . then ( ( ) => {
152
- resolve ( resolved ) ;
153
- if ( error ) onerror ?. ( error , node ) ;
154
- return hooks ?. main ?. onReady ?. ( resolved , node ) ;
155
- } ) ;
156
- } ) ;
137
+ if ( before || after ) {
138
+ createOverload (
139
+ module ,
140
+ `r${ suffix . slice ( 1 ) } ` ,
141
+ before ,
142
+ after ,
143
+ ) ;
144
+ }
145
+
146
+ let beforeCB , afterCB ;
147
+ // ignore onReady and onWorker
148
+ for ( let i = 2 ; i < jsHooks . length ; i ++ ) {
149
+ const key = jsHooks [ i ] ;
150
+ const value = hooks ?. main ?. [ key ] ;
151
+ if ( value && key . endsWith ( suffix ) ) {
152
+ if ( key . startsWith ( 'onBefore' ) )
153
+ beforeCB = value ;
154
+ else
155
+ afterCB = value ;
156
+ }
157
+ }
158
+ polluteJS ( module , resolved , node , suffix . endsWith ( 'Async' ) , beforeCB , afterCB ) ;
157
159
}
160
+
161
+ details . queue = details . queue . then ( ( ) => {
162
+ resolve ( resolved ) ;
163
+ if ( error ) onerror ?. ( error , node ) ;
164
+ return hooks ?. main ?. onReady ?. ( resolved , node ) ;
165
+ } ) ;
158
166
}
159
167
}
160
168
} ;
0 commit comments