diff options
-rw-r--r-- | client/src/root-helpers/plugins-manager.ts | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/client/src/root-helpers/plugins-manager.ts b/client/src/root-helpers/plugins-manager.ts index f1687d91d..a1b763ff2 100644 --- a/client/src/root-helpers/plugins-manager.ts +++ b/client/src/root-helpers/plugins-manager.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-implied-eval */ | ||
1 | import * as debug from 'debug' | 2 | import * as debug from 'debug' |
2 | import { firstValueFrom, ReplaySubject } from 'rxjs' | 3 | import { firstValueFrom, ReplaySubject } from 'rxjs' |
3 | import { first, shareReplay } from 'rxjs/operators' | 4 | import { first, shareReplay } from 'rxjs/operators' |
@@ -227,7 +228,7 @@ class PluginsManager { | |||
227 | console.log('Loading script %s of plugin %s.', clientScript.script, plugin.name) | 228 | console.log('Loading script %s of plugin %s.', clientScript.script, plugin.name) |
228 | 229 | ||
229 | const absURL = (environment.apiUrl || window.location.origin) + clientScript.script | 230 | const absURL = (environment.apiUrl || window.location.origin) + clientScript.script |
230 | return import(/* webpackIgnore: true */ absURL) | 231 | return dynamicImport(absURL) |
231 | .then((script: ClientScriptModule) => script.register({ registerHook, registerVideoField, registerSettingsScript, peertubeHelpers })) | 232 | .then((script: ClientScriptModule) => script.register({ registerHook, registerVideoField, registerSettingsScript, peertubeHelpers })) |
232 | .then(() => this.sortHooksByPriority()) | 233 | .then(() => this.sortHooksByPriority()) |
233 | .catch(err => console.error('Cannot import or register plugin %s.', pluginInfo.plugin.name, err)) | 234 | .catch(err => console.error('Cannot import or register plugin %s.', pluginInfo.plugin.name, err)) |
@@ -250,3 +251,45 @@ export { | |||
250 | OnFormFields, | 251 | OnFormFields, |
251 | OnSettingsScripts | 252 | OnSettingsScripts |
252 | } | 253 | } |
254 | |||
255 | // --------------------------------------------------------------------------- | ||
256 | |||
257 | async function dynamicImport (url: string) { | ||
258 | try { | ||
259 | // eslint-disable-next-line no-new-func | ||
260 | return new Function(`return import('${url}')`)() | ||
261 | } catch { | ||
262 | console.log('Fallback to import polyfill') | ||
263 | |||
264 | return new Promise((resolve, reject) => { | ||
265 | const vector = '$importModule$' + Math.random().toString(32).slice(2) | ||
266 | const script = document.createElement('script') | ||
267 | |||
268 | const destructor = () => { | ||
269 | delete window[vector] | ||
270 | script.onerror = null | ||
271 | script.onload = null | ||
272 | script.remove() | ||
273 | URL.revokeObjectURL(script.src) | ||
274 | script.src = '' | ||
275 | } | ||
276 | |||
277 | script.defer = true | ||
278 | script.type = 'module' | ||
279 | |||
280 | script.onerror = () => { | ||
281 | reject(new Error(`Failed to import: ${url}`)) | ||
282 | destructor() | ||
283 | } | ||
284 | script.onload = () => { | ||
285 | resolve(window[vector]) | ||
286 | destructor() | ||
287 | } | ||
288 | const loader = `import * as m from "${url}"; window.${vector} = m;` // export Module | ||
289 | const blob = new Blob([ loader ], { type: 'text/javascript' }) | ||
290 | script.src = URL.createObjectURL(blob) | ||
291 | |||
292 | document.head.appendChild(script) | ||
293 | }) | ||
294 | } | ||
295 | } | ||