@coderline/alphatab 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * alphaTab v1.3.0 (, build 9)
2
+ * alphaTab v1.3.1 (, build 11)
3
3
  *
4
4
  * Copyright © 2024, Daniel Kuschny and Contributors, All rights reserved.
5
5
  *
@@ -18,12 +18,6 @@
18
18
 
19
19
  var fs = require('fs');
20
20
  var path = require('path');
21
- var webpack = require('webpack');
22
- var identifier = require('webpack/lib/util/identifier');
23
- var ModuleTypeConstants = require('webpack/lib/ModuleTypeConstants');
24
- var makeSerializable = require('webpack/lib/util/makeSerializable');
25
- var EnableChunkLoadingPlugin = require('webpack/lib/javascript/EnableChunkLoadingPlugin');
26
- var WorkerDependency = require('webpack/lib/dependencies/WorkerDependency');
27
21
 
28
22
  function _interopNamespaceDefault(e) {
29
23
  var n = Object.create(null);
@@ -45,211 +39,124 @@ function _interopNamespaceDefault(e) {
45
39
  var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
46
40
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
47
41
 
48
- /**@target web */
49
- class AlphaTabWorkerRuntimeModule extends webpack.RuntimeModule {
50
- constructor() {
51
- super("alphaTab audio worker chunk loading", webpack.RuntimeModule.STAGE_BASIC);
52
- }
53
- generate() {
54
- const compilation = this.compilation;
55
- const runtimeTemplate = compilation.runtimeTemplate;
56
- const globalObject = runtimeTemplate.globalObject;
57
- const chunkLoadingGlobalExpr = `${globalObject}[${JSON.stringify(compilation.outputOptions.chunkLoadingGlobal)}]`;
58
- const initialChunkIds = new Set(this.chunk.ids);
59
- for (const c of this.chunk.getAllInitialChunks()) {
60
- if (webpack.javascript.JavascriptModulesPlugin.chunkHasJs(c, this.chunkGraph)) {
61
- continue;
62
- }
63
- for (const id of c.ids) {
64
- initialChunkIds.add(id);
65
- }
66
- }
67
- return webpack.Template.asString([
68
- `if ( ! ('AudioWorkletGlobalScope' in ${globalObject}) ) { return; }`,
69
- `const installedChunks = {`,
70
- webpack.Template.indent(Array.from(initialChunkIds, id => `${JSON.stringify(id)}: 1`).join(",\n")),
71
- "};",
72
- "// importScripts chunk loading",
73
- `const installChunk = ${runtimeTemplate.basicFunction("data", [
74
- runtimeTemplate.destructureArray(["chunkIds", "moreModules", "runtime"], "data"),
75
- "for(const moduleId in moreModules) {",
76
- webpack.Template.indent([
77
- `if(${webpack.RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
78
- webpack.Template.indent(`${webpack.RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`),
79
- "}"
80
- ]),
81
- "}",
82
- `if(runtime) runtime(${webpack.RuntimeGlobals.require});`,
83
- "while(chunkIds.length)",
84
- webpack.Template.indent("installedChunks[chunkIds.pop()] = 1;"),
85
- "parentChunkLoadingFunction(data);"
86
- ])};`,
87
- `const chunkLoadingGlobal = ${chunkLoadingGlobalExpr} = ${chunkLoadingGlobalExpr} || [];`,
88
- "const parentChunkLoadingFunction = chunkLoadingGlobal.push.bind(chunkLoadingGlobal);",
89
- "chunkLoadingGlobal.forEach(installChunk);",
90
- "chunkLoadingGlobal.push = installChunk;"
91
- ]);
92
- }
93
- }
94
- AlphaTabWorkerRuntimeModule.Key = "AlphaTabWorkerRuntime";
95
-
96
- /**@target web */
97
- class AlphaTabWorkletStartRuntimeModule extends webpack.RuntimeModule {
98
- constructor() {
99
- super("alphaTab audio worklet chunk lookup", webpack.RuntimeModule.STAGE_BASIC);
100
- }
101
- generate() {
102
- const compilation = this.compilation;
103
- const workletChunkLookup = new Map();
104
- const chunkGraph = this.chunkGraph;
105
- const allChunks = compilation.chunks;
106
- for (const chunk of allChunks) {
107
- const isWorkletEntry = chunkGraph
108
- .getTreeRuntimeRequirements(chunk)
109
- .has(AlphaTabWorkerRuntimeModule.Key);
110
- if (isWorkletEntry) {
111
- const workletChunks = Array.from(chunk.getAllReferencedChunks()).map(c => {
112
- // force content chunk to be created
113
- compilation.hooks.contentHash.call(c);
114
- return compilation.getPath(webpack.javascript.JavascriptModulesPlugin.getChunkFilenameTemplate(c, compilation.outputOptions), {
115
- chunk: c,
116
- contentHashType: "javascript"
117
- });
118
- });
119
- workletChunkLookup.set(String(chunk.id), workletChunks);
42
+ const JAVASCRIPT_MODULE_TYPE_AUTO = 'javascript/auto';
43
+ const JAVASCRIPT_MODULE_TYPE_ESM = 'javascript/esm';
44
+ function makeDependencySerializable(webPackWithAlphaTab, dependency, key) {
45
+ webPackWithAlphaTab.webpack.util.serialization.register(dependency, key, null, {
46
+ serialize(obj, context) {
47
+ obj.serialize(context);
48
+ },
49
+ deserialize(context) {
50
+ if (typeof dependency.deserialize === 'function') {
51
+ return dependency.deserialize(context);
120
52
  }
53
+ const obj = new dependency();
54
+ obj.deserialize(context);
55
+ return obj;
121
56
  }
122
- return webpack.Template.asString([
123
- `${AlphaTabWorkletStartRuntimeModule.RuntimeGlobalWorkletGetStartupChunks} = (() => {`,
124
- webpack.Template.indent([
125
- "const lookup = new Map(",
126
- webpack.Template.indent(JSON.stringify(Array.from(workletChunkLookup.entries()))),
127
- ");",
128
- "return (chunkId) => lookup.get(String(chunkId)) ?? [];"
129
- ]),
130
- "})();"
131
- ]);
132
- }
133
- }
134
- AlphaTabWorkletStartRuntimeModule.RuntimeGlobalWorkletGetStartupChunks = "__webpack_require__.wsc";
135
-
136
- /**@target web */
137
- function makeDependencySerializable(dependency, key) {
138
- makeSerializable(dependency, key);
57
+ });
139
58
  }
140
59
  function tapJavaScript(normalModuleFactory, pluginName, parserPlugin) {
141
- normalModuleFactory.hooks.parser
142
- .for(ModuleTypeConstants.JAVASCRIPT_MODULE_TYPE_AUTO)
143
- .tap(pluginName, parserPlugin);
144
- normalModuleFactory.hooks.parser
145
- .for(ModuleTypeConstants.JAVASCRIPT_MODULE_TYPE_ESM)
146
- .tap(pluginName, parserPlugin);
60
+ normalModuleFactory.hooks.parser.for(JAVASCRIPT_MODULE_TYPE_AUTO).tap(pluginName, parserPlugin);
61
+ normalModuleFactory.hooks.parser.for(JAVASCRIPT_MODULE_TYPE_ESM).tap(pluginName, parserPlugin);
147
62
  }
148
63
  function parseModuleUrl(parser, expr) {
149
- if (expr.type !== "NewExpression" || expr.arguments.length !== 2) {
64
+ if (expr.type !== 'NewExpression' || expr.arguments.length !== 2) {
150
65
  return;
151
66
  }
152
67
  const newExpr = expr;
153
68
  const [arg1, arg2] = newExpr.arguments;
154
69
  const callee = parser.evaluateExpression(newExpr.callee);
155
- if (!callee.isIdentifier() || callee.identifier !== "URL") {
70
+ if (!callee.isIdentifier() || callee.identifier !== 'URL') {
156
71
  return;
157
72
  }
158
73
  const arg1Value = parser.evaluateExpression(arg1);
159
- return [
160
- arg1Value,
161
- [
162
- (arg1.range)[0],
163
- (arg2.range)[1]
164
- ]
165
- ];
74
+ return [arg1Value, [arg1.range[0], arg2.range[1]]];
166
75
  }
76
+ const ALPHATAB_WORKER_RUNTIME_PREFIX = 'atworker_';
167
77
  function getWorkerRuntime(parser, compilation, cachedContextify, workerIndexMap) {
168
78
  let i = workerIndexMap.get(parser.state) || 0;
169
79
  workerIndexMap.set(parser.state, i + 1);
170
80
  let name = `${cachedContextify(parser.state.module.identifier())}|${i}`;
171
- const hash = webpack.util.createHash(compilation.outputOptions.hashFunction);
81
+ const hash = compilation.compiler.webpack.util.createHash(compilation.outputOptions.hashFunction);
172
82
  hash.update(name);
173
83
  const digest = hash.digest(compilation.outputOptions.hashDigest);
174
84
  const runtime = digest.slice(0, compilation.outputOptions.hashDigestLength);
175
- return runtime;
85
+ return ALPHATAB_WORKER_RUNTIME_PREFIX + runtime;
86
+ }
87
+ function isWorkerRuntime(runtime) {
88
+ if (typeof runtime !== 'string') {
89
+ return false;
90
+ }
91
+ return runtime.startsWith(ALPHATAB_WORKER_RUNTIME_PREFIX);
176
92
  }
177
93
 
178
94
  /**@target web */
179
- /**
180
- * This module dependency injects the relevant code into a worklet bootstrap script
181
- * to install chunks which have been added to the worklet via addModule before the bootstrap script starts.
182
- */
183
- class AlphaTabWorkletDependency extends webpack.dependencies.ModuleDependency {
184
- constructor(url, range, publicPath) {
185
- super(url);
186
- this.range = range;
187
- this.publicPath = publicPath;
188
- }
189
- get type() {
190
- return "alphaTabWorklet";
191
- }
192
- get category() {
193
- return "worker";
194
- }
195
- updateHash(hash) {
196
- if (this._hashUpdate === undefined) {
197
- this._hashUpdate = JSON.stringify(this.publicPath);
95
+ function injectWorkerRuntimeModule(webPackWithAlphaTab) {
96
+ class AlphaTabWorkerRuntimeModule extends webPackWithAlphaTab.webpack.RuntimeModule {
97
+ constructor() {
98
+ super('alphaTab audio worker chunk loading', webPackWithAlphaTab.webpack.RuntimeModule.STAGE_BASIC);
99
+ }
100
+ generate() {
101
+ const compilation = this.compilation;
102
+ const runtimeTemplate = compilation.runtimeTemplate;
103
+ const globalObject = runtimeTemplate.globalObject;
104
+ const chunkLoadingGlobalExpr = `${globalObject}[${JSON.stringify(compilation.outputOptions.chunkLoadingGlobal)}]`;
105
+ const initialChunkIds = new Set(this.chunk.ids);
106
+ for (const c of this.chunk.getAllInitialChunks()) {
107
+ if (webPackWithAlphaTab.webpack.javascript.JavascriptModulesPlugin.chunkHasJs(c, this.chunkGraph)) {
108
+ continue;
109
+ }
110
+ for (const id of c.ids) {
111
+ initialChunkIds.add(id);
112
+ }
113
+ }
114
+ return webPackWithAlphaTab.webpack.Template.asString([
115
+ `if ( ! ('AudioWorkletGlobalScope' in ${globalObject}) ) { return; }`,
116
+ `const installedChunks = {`,
117
+ webPackWithAlphaTab.webpack.Template.indent(Array.from(initialChunkIds, id => `${JSON.stringify(id)}: 1`).join(',\n')),
118
+ '};',
119
+ '// importScripts chunk loading',
120
+ `const installChunk = ${runtimeTemplate.basicFunction('data', [
121
+ runtimeTemplate.destructureArray(['chunkIds', 'moreModules', 'runtime'], 'data'),
122
+ 'for(const moduleId in moreModules) {',
123
+ webPackWithAlphaTab.webpack.Template.indent([
124
+ `if(${webPackWithAlphaTab.webpack.RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
125
+ webPackWithAlphaTab.webpack.Template.indent(`${webPackWithAlphaTab.webpack.RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`),
126
+ '}'
127
+ ]),
128
+ '}',
129
+ `if(runtime) runtime(${webPackWithAlphaTab.webpack.RuntimeGlobals.require});`,
130
+ 'while(chunkIds.length)',
131
+ webPackWithAlphaTab.webpack.Template.indent('installedChunks[chunkIds.pop()] = 1;'),
132
+ 'parentChunkLoadingFunction(data);'
133
+ ])};`,
134
+ `const chunkLoadingGlobal = ${chunkLoadingGlobalExpr} = ${chunkLoadingGlobalExpr} || [];`,
135
+ 'const parentChunkLoadingFunction = chunkLoadingGlobal.push.bind(chunkLoadingGlobal);',
136
+ 'chunkLoadingGlobal.forEach(installChunk);',
137
+ 'chunkLoadingGlobal.push = installChunk;'
138
+ ]);
198
139
  }
199
- hash.update(this._hashUpdate);
200
- }
201
- serialize(context) {
202
- const { write } = context;
203
- write(this.publicPath);
204
- super.serialize(context);
205
- }
206
- deserialize(context) {
207
- const { read } = context;
208
- this.publicPath = read();
209
- super.deserialize(context);
210
140
  }
141
+ AlphaTabWorkerRuntimeModule.Key = 'AlphaTabWorkerRuntime';
142
+ webPackWithAlphaTab.alphaTab.registerWebWorkerRuntimeModule = (pluginName, compilation) => {
143
+ compilation.hooks.runtimeRequirementInTree
144
+ .for(AlphaTabWorkerRuntimeModule.Key)
145
+ .tap(pluginName, (chunk) => {
146
+ compilation.addRuntimeModule(chunk, new AlphaTabWorkerRuntimeModule());
147
+ });
148
+ compilation.hooks.additionalChunkRuntimeRequirements.tap(pluginName, (chunk, runtimeRequirements) => {
149
+ if (isWorkerRuntime(chunk.runtime)) {
150
+ runtimeRequirements.add(webPackWithAlphaTab.webpack.RuntimeGlobals.moduleFactories);
151
+ runtimeRequirements.add(webPackWithAlphaTab.alphaTab.WebWorkerRuntimeModuleKey);
152
+ }
153
+ });
154
+ };
155
+ webPackWithAlphaTab.alphaTab.WebWorkerRuntimeModuleKey = AlphaTabWorkerRuntimeModule.Key;
211
156
  }
212
- AlphaTabWorkletDependency.Template = class AlphaTabWorkletDependencyTemplate extends webpack.dependencies.ModuleDependency.Template {
213
- apply(dependency, source, templateContext) {
214
- const { chunkGraph, moduleGraph, runtimeRequirements } = templateContext;
215
- const dep = dependency;
216
- const block = moduleGraph.getParentBlock(dependency);
217
- const entrypoint = chunkGraph.getBlockChunkGroup(block);
218
- const workletImportBaseUrl = dep.publicPath
219
- ? JSON.stringify(dep.publicPath)
220
- : webpack.RuntimeGlobals.publicPath;
221
- const chunk = entrypoint.getEntrypointChunk();
222
- // worklet global scope has no 'self', need to inject it for compatibility with chunks
223
- // some plugins like the auto public path need to right location. we pass this on from the main runtime
224
- // some plugins rely on importScripts to be defined.
225
- const workletInlineBootstrap = `
226
- globalThis.self = globalThis.self || globalThis;
227
- globalThis.location = \${JSON.stringify(${webpack.RuntimeGlobals.baseURI})};
228
- globalThis.importScripts = (url) => { throw new Error("importScripts not available, dynamic loading of chunks not supported in this context", url) };
229
- `;
230
- chunkGraph.addChunkRuntimeRequirements(chunk, new Set([
231
- webpack.RuntimeGlobals.moduleFactories,
232
- AlphaTabWorkerRuntimeModule.Key
233
- ]));
234
- runtimeRequirements.add(AlphaTabWorkletStartRuntimeModule.RuntimeGlobalWorkletGetStartupChunks);
235
- source.replace(dep.range[0], dep.range[1] - 1, webpack.Template.asString([
236
- "(/* worklet bootstrap */ async function(__webpack_worklet__) {",
237
- webpack.Template.indent([
238
- `await __webpack_worklet__.addModule(URL.createObjectURL(new Blob([\`${workletInlineBootstrap}\`], { type: "application/javascript; charset=utf-8" })));`,
239
- `for (const fileName of ${AlphaTabWorkletStartRuntimeModule.RuntimeGlobalWorkletGetStartupChunks}(${chunk.id})) {`,
240
- webpack.Template.indent([
241
- `await __webpack_worklet__.addModule(new URL(${workletImportBaseUrl} + fileName, ${webpack.RuntimeGlobals.baseURI}));`
242
- ]),
243
- "}"
244
- ]),
245
- `})(alphaTabWorklet)`
246
- ]));
247
- }
248
- };
249
- makeDependencySerializable(AlphaTabWorkletDependency, 'AlphaTabWorkletDependency');
250
157
 
251
158
  /**@target web */
252
- const AlphaTabWorkletSpecifierTag = Symbol("alphatab worklet specifier tag");
159
+ const AlphaTabWorkletSpecifierTag = Symbol('alphatab worklet specifier tag');
253
160
  const workletIndexMap = new WeakMap();
254
161
  /**
255
162
  * Configures the Audio Worklet aspects within webpack.
@@ -262,12 +169,11 @@ const workletIndexMap = new WeakMap();
262
169
  * @param cachedContextify
263
170
  * @returns
264
171
  */
265
- function configureAudioWorklet(pluginName, options, compiler, compilation, normalModuleFactory, cachedContextify) {
172
+ function configureAudioWorklet(webPackWithAlphaTab, pluginName, options, compiler, compilation, normalModuleFactory, cachedContextify) {
266
173
  if (options.audioWorklets === false) {
267
174
  return;
268
175
  }
269
- compilation.dependencyFactories.set(AlphaTabWorkletDependency, normalModuleFactory);
270
- compilation.dependencyTemplates.set(AlphaTabWorkletDependency, new AlphaTabWorkletDependency.Template());
176
+ webPackWithAlphaTab.alphaTab.registerWorkletDependency(compilation, normalModuleFactory);
271
177
  const handleAlphaTabWorklet = (parser, expr) => {
272
178
  const [arg1] = expr.arguments;
273
179
  const parsedUrl = parseModuleUrl(parser, arg1);
@@ -279,7 +185,7 @@ function configureAudioWorklet(pluginName, options, compiler, compilation, norma
279
185
  return;
280
186
  }
281
187
  const runtime = getWorkerRuntime(parser, compilation, cachedContextify, workletIndexMap);
282
- const block = new webpack.AsyncDependenciesBlock({
188
+ const block = new webPackWithAlphaTab.webpack.AsyncDependenciesBlock({
283
189
  entryOptions: {
284
190
  chunkLoading: false,
285
191
  wasmLoading: false,
@@ -287,17 +193,17 @@ function configureAudioWorklet(pluginName, options, compiler, compilation, norma
287
193
  }
288
194
  });
289
195
  block.loc = expr.loc;
290
- const workletBootstrap = new AlphaTabWorkletDependency(url.string, [expr.range[0], expr.range[1]], compiler.options.output.workerPublicPath);
196
+ const workletBootstrap = webPackWithAlphaTab.alphaTab.createWorkletDependency(url.string, [expr.range[0], expr.range[1]], compiler.options.output.workerPublicPath);
291
197
  workletBootstrap.loc = expr.loc;
292
198
  block.addDependency(workletBootstrap);
293
199
  parser.state.module.addBlock(block);
294
200
  return true;
295
201
  };
296
202
  const parserPlugin = (parser) => {
297
- const pattern = "alphaTabWorklet";
298
- const itemMembers = "addModule";
203
+ const pattern = 'alphaTabWorklet';
204
+ const itemMembers = 'addModule';
299
205
  parser.hooks.preDeclarator.tap(pluginName, (decl) => {
300
- if (decl.id.type === "Identifier" && decl.id.name === pattern) {
206
+ if (decl.id.type === 'Identifier' && decl.id.name === pattern) {
301
207
  parser.tagVariable(decl.id.name, AlphaTabWorkletSpecifierTag);
302
208
  return true;
303
209
  }
@@ -310,7 +216,7 @@ function configureAudioWorklet(pluginName, options, compiler, compilation, norma
310
216
  parser.hooks.callMemberChain
311
217
  .for(AlphaTabWorkletSpecifierTag)
312
218
  .tap(pluginName, (expression, members) => {
313
- if (itemMembers !== members.join(".")) {
219
+ if (itemMembers !== members.join('.')) {
314
220
  return;
315
221
  }
316
222
  return handleAlphaTabWorklet(parser, expression);
@@ -332,13 +238,12 @@ const workerIndexMap = new WeakMap();
332
238
  * @param cachedContextify
333
239
  * @returns
334
240
  */
335
- function configureWebWorker(pluginName, options, compiler, compilation, normalModuleFactory, cachedContextify) {
241
+ function configureWebWorker(webPackWithAlphaTab, pluginName, options, compiler, compilation, normalModuleFactory, cachedContextify) {
336
242
  if (options.audioWorklets === false) {
337
243
  return;
338
244
  }
339
- compilation.dependencyFactories.set(WorkerDependency, normalModuleFactory);
340
- compilation.dependencyTemplates.set(WorkerDependency, new WorkerDependency.Template());
341
- new EnableChunkLoadingPlugin('import-scripts').apply(compiler);
245
+ webPackWithAlphaTab.alphaTab.registerWebWorkerDependency(compilation, normalModuleFactory);
246
+ new webPackWithAlphaTab.webpack.javascript.EnableChunkLoadingPlugin('import-scripts').apply(compiler);
342
247
  const handleAlphaTabWorker = (parser, expr) => {
343
248
  const [arg1, arg2] = expr.arguments;
344
249
  const parsedUrl = parseModuleUrl(parser, arg1);
@@ -350,7 +255,7 @@ function configureWebWorker(pluginName, options, compiler, compilation, normalMo
350
255
  return;
351
256
  }
352
257
  const runtime = getWorkerRuntime(parser, compilation, cachedContextify, workerIndexMap);
353
- const block = new webpack.AsyncDependenciesBlock({
258
+ const block = new webPackWithAlphaTab.webpack.AsyncDependenciesBlock({
354
259
  entryOptions: {
355
260
  chunkLoading: 'import-scripts',
356
261
  wasmLoading: false,
@@ -358,28 +263,330 @@ function configureWebWorker(pluginName, options, compiler, compilation, normalMo
358
263
  }
359
264
  });
360
265
  block.loc = expr.loc;
361
- const workletBootstrap = new WorkerDependency(url.string, range, compiler.options.output.workerPublicPath);
266
+ const workletBootstrap = webPackWithAlphaTab.alphaTab.createWebWorkerDependency(url.string, range, compiler.options.output.workerPublicPath);
362
267
  workletBootstrap.loc = expr.loc;
363
268
  block.addDependency(workletBootstrap);
364
269
  parser.state.module.addBlock(block);
365
- const dep1 = new webpack.dependencies.ConstDependency(`{ type: ${compilation.options.output.module ? '"module"' : "undefined"} }`, arg2.range);
270
+ const dep1 = new webPackWithAlphaTab.webpack.dependencies.ConstDependency(`{ type: ${compilation.options.output.module ? '"module"' : 'undefined'} }`, arg2.range);
366
271
  dep1.loc = expr.loc;
367
272
  parser.state.module.addPresentationalDependency(dep1);
368
273
  parser.walkExpression(expr.callee);
369
274
  return true;
370
275
  };
371
276
  const parserPlugin = (parser) => {
372
- parser.hooks.new.for("alphaTab.Environment.alphaTabWorker").tap(pluginName, (expr) => handleAlphaTabWorker(parser, expr));
277
+ parser.hooks.new
278
+ .for('alphaTab.Environment.alphaTabWorker')
279
+ .tap(pluginName, (expr) => handleAlphaTabWorker(parser, expr));
373
280
  };
374
281
  tapJavaScript(normalModuleFactory, pluginName, parserPlugin);
375
282
  }
376
283
 
377
284
  /**@target web */
285
+ function injectWebWorkerDependency(webPackWithAlphaTab) {
286
+ class AlphaTabWebWorkerDependency extends webPackWithAlphaTab.webpack.dependencies.ModuleDependency {
287
+ constructor(request, range, publicPath) {
288
+ super(request);
289
+ this.range = range;
290
+ this.publicPath = publicPath;
291
+ }
292
+ getReferencedExports() {
293
+ return webPackWithAlphaTab.webpack.Dependency.NO_EXPORTS_REFERENCED;
294
+ }
295
+ get type() {
296
+ return 'alphaTabWorker';
297
+ }
298
+ get category() {
299
+ return 'worker';
300
+ }
301
+ updateHash(hash) {
302
+ if (this._hashUpdate === undefined) {
303
+ this._hashUpdate = JSON.stringify(this.publicPath);
304
+ }
305
+ hash.update(this._hashUpdate);
306
+ }
307
+ serialize(context) {
308
+ const { write } = context;
309
+ write(this.publicPath);
310
+ super.serialize(context);
311
+ }
312
+ deserialize(context) {
313
+ const { read } = context;
314
+ this.publicPath = read();
315
+ super.deserialize(context);
316
+ }
317
+ }
318
+ AlphaTabWebWorkerDependency.Template = class WorkerDependencyTemplate extends (webPackWithAlphaTab.webpack.dependencies.ModuleDependency.Template) {
319
+ apply(dependency, source, templateContext) {
320
+ const { chunkGraph, moduleGraph, runtimeRequirements } = templateContext;
321
+ const dep = dependency;
322
+ const block = moduleGraph.getParentBlock(dependency);
323
+ const entrypoint = chunkGraph.getBlockChunkGroup(block);
324
+ const chunk = entrypoint.getEntrypointChunk();
325
+ // We use the workerPublicPath option if provided, else we fallback to the RuntimeGlobal publicPath
326
+ const workerImportBaseUrl = dep.publicPath ? `"${dep.publicPath}"` : webPackWithAlphaTab.webpack.RuntimeGlobals.publicPath;
327
+ runtimeRequirements.add(webPackWithAlphaTab.webpack.RuntimeGlobals.publicPath);
328
+ runtimeRequirements.add(webPackWithAlphaTab.webpack.RuntimeGlobals.baseURI);
329
+ runtimeRequirements.add(webPackWithAlphaTab.webpack.RuntimeGlobals.getChunkScriptFilename);
330
+ source.replace(dep.range[0], dep.range[1] - 1, `/* worker import */ ${workerImportBaseUrl} + ${webPackWithAlphaTab.webpack.RuntimeGlobals.getChunkScriptFilename}(${JSON.stringify(chunk.id)}), ${webPackWithAlphaTab.webpack.RuntimeGlobals.baseURI}`);
331
+ }
332
+ };
333
+ makeDependencySerializable(webPackWithAlphaTab, AlphaTabWebWorkerDependency, 'AlphaTabWebWorkerDependency');
334
+ webPackWithAlphaTab.alphaTab.createWebWorkerDependency = (request, range, publicPath) => new AlphaTabWebWorkerDependency(request, range, publicPath);
335
+ webPackWithAlphaTab.alphaTab.registerWebWorkerDependency = (compilation, normalModuleFactory) => {
336
+ compilation.dependencyFactories.set(AlphaTabWebWorkerDependency, normalModuleFactory);
337
+ compilation.dependencyTemplates.set(AlphaTabWebWorkerDependency, new AlphaTabWebWorkerDependency.Template());
338
+ };
339
+ }
340
+
341
+ /**@target web */
342
+ function injectWorkletRuntimeModule(webPackWithAlphaTab) {
343
+ class AlphaTabWorkletStartRuntimeModule extends webPackWithAlphaTab.webpack.RuntimeModule {
344
+ constructor() {
345
+ super('alphaTab audio worklet chunk lookup', webPackWithAlphaTab.webpack.RuntimeModule.STAGE_BASIC);
346
+ }
347
+ generate() {
348
+ const compilation = this.compilation;
349
+ const workletChunkLookup = new Map();
350
+ const allChunks = compilation.chunks;
351
+ for (const chunk of allChunks) {
352
+ const isWorkletEntry = isWorkerRuntime(chunk.runtime);
353
+ if (isWorkletEntry) {
354
+ const workletChunks = Array.from(chunk.getAllReferencedChunks()).map(c => {
355
+ // force content chunk to be created
356
+ compilation.hooks.contentHash.call(c);
357
+ return compilation.getPath(webPackWithAlphaTab.webpack.javascript.JavascriptModulesPlugin.getChunkFilenameTemplate(c, compilation.outputOptions), {
358
+ chunk: c,
359
+ contentHashType: 'javascript'
360
+ });
361
+ });
362
+ workletChunkLookup.set(String(chunk.id), workletChunks);
363
+ }
364
+ }
365
+ return webPackWithAlphaTab.webpack.Template.asString([
366
+ `${AlphaTabWorkletStartRuntimeModule.RuntimeGlobalWorkletGetStartupChunks} = (() => {`,
367
+ webPackWithAlphaTab.webpack.Template.indent([
368
+ 'const lookup = new Map(',
369
+ webPackWithAlphaTab.webpack.Template.indent(JSON.stringify(Array.from(workletChunkLookup.entries()))),
370
+ ');',
371
+ 'return (chunkId) => lookup.get(String(chunkId)) ?? [];'
372
+ ]),
373
+ '})();'
374
+ ]);
375
+ }
376
+ }
377
+ AlphaTabWorkletStartRuntimeModule.RuntimeGlobalWorkletGetStartupChunks = '__webpack_require__.wsc';
378
+ webPackWithAlphaTab.alphaTab.RuntimeGlobalWorkletGetStartupChunks =
379
+ AlphaTabWorkletStartRuntimeModule.RuntimeGlobalWorkletGetStartupChunks;
380
+ webPackWithAlphaTab.alphaTab.registerWorkletRuntimeModule = (pluginName, compilation) => {
381
+ compilation.hooks.runtimeRequirementInTree
382
+ .for(AlphaTabWorkletStartRuntimeModule.RuntimeGlobalWorkletGetStartupChunks)
383
+ .tap(pluginName, (chunk) => {
384
+ compilation.addRuntimeModule(chunk, new AlphaTabWorkletStartRuntimeModule());
385
+ });
386
+ };
387
+ }
388
+
389
+ /**@target web */
390
+ function injectWorkletDependency(webPackWithAlphaTab) {
391
+ /**
392
+ * This module dependency injects the relevant code into a worklet bootstrap script
393
+ * to install chunks which have been added to the worklet via addModule before the bootstrap script starts.
394
+ */
395
+ class AlphaTabWorkletDependency extends webPackWithAlphaTab.webpack.dependencies.ModuleDependency {
396
+ constructor(url, range, publicPath) {
397
+ super(url);
398
+ this.range = range;
399
+ this.publicPath = publicPath;
400
+ }
401
+ get type() {
402
+ return 'alphaTabWorklet';
403
+ }
404
+ get category() {
405
+ return 'worker';
406
+ }
407
+ updateHash(hash) {
408
+ if (this._hashUpdate === undefined) {
409
+ this._hashUpdate = JSON.stringify(this.publicPath);
410
+ }
411
+ hash.update(this._hashUpdate);
412
+ }
413
+ serialize(context) {
414
+ const { write } = context;
415
+ write(this.publicPath);
416
+ super.serialize(context);
417
+ }
418
+ deserialize(context) {
419
+ const { read } = context;
420
+ this.publicPath = read();
421
+ super.deserialize(context);
422
+ }
423
+ }
424
+ AlphaTabWorkletDependency.Template = class AlphaTabWorkletDependencyTemplate extends (webPackWithAlphaTab.webpack.dependencies.ModuleDependency.Template) {
425
+ apply(dependency, source, templateContext) {
426
+ const { chunkGraph, moduleGraph, runtimeRequirements } = templateContext;
427
+ const dep = dependency;
428
+ const block = moduleGraph.getParentBlock(dependency);
429
+ const entrypoint = chunkGraph.getBlockChunkGroup(block);
430
+ const workletImportBaseUrl = dep.publicPath
431
+ ? JSON.stringify(dep.publicPath)
432
+ : webPackWithAlphaTab.webpack.RuntimeGlobals.publicPath;
433
+ const chunk = entrypoint.getEntrypointChunk();
434
+ // worklet global scope has no 'self', need to inject it for compatibility with chunks
435
+ // some plugins like the auto public path need to right location. we pass this on from the main runtime
436
+ // some plugins rely on importScripts to be defined.
437
+ const workletInlineBootstrap = `
438
+ globalThis.self = globalThis.self || globalThis;
439
+ globalThis.location = \${JSON.stringify(${webPackWithAlphaTab.webpack.RuntimeGlobals.baseURI})};
440
+ globalThis.importScripts = (url) => { throw new Error("importScripts not available, dynamic loading of chunks not supported in this context", url) };
441
+ `;
442
+ chunkGraph.addChunkRuntimeRequirements(chunk, new Set([webPackWithAlphaTab.webpack.RuntimeGlobals.moduleFactories, webPackWithAlphaTab.alphaTab.WebWorkerRuntimeModuleKey]));
443
+ runtimeRequirements.add(webPackWithAlphaTab.alphaTab.RuntimeGlobalWorkletGetStartupChunks);
444
+ source.replace(dep.range[0], dep.range[1] - 1, webPackWithAlphaTab.webpack.Template.asString([
445
+ '(/* worklet bootstrap */ async function(__webpack_worklet__) {',
446
+ webPackWithAlphaTab.webpack.Template.indent([
447
+ `await __webpack_worklet__.addModule(URL.createObjectURL(new Blob([\`${workletInlineBootstrap}\`], { type: "application/javascript; charset=utf-8" })));`,
448
+ `for (const fileName of ${webPackWithAlphaTab.alphaTab.RuntimeGlobalWorkletGetStartupChunks}(${JSON.stringify(chunk.id)})) {`,
449
+ webPackWithAlphaTab.webpack.Template.indent([
450
+ `await __webpack_worklet__.addModule(new URL(${workletImportBaseUrl} + fileName, ${webPackWithAlphaTab.webpack.RuntimeGlobals.baseURI}));`
451
+ ]),
452
+ '}'
453
+ ]),
454
+ `})(alphaTabWorklet)`
455
+ ]));
456
+ }
457
+ };
458
+ makeDependencySerializable(webPackWithAlphaTab, AlphaTabWorkletDependency, 'AlphaTabWorkletDependency');
459
+ webPackWithAlphaTab.alphaTab.registerWorkletDependency = (compilation, normalModuleFactory) => {
460
+ compilation.dependencyFactories.set(AlphaTabWorkletDependency, normalModuleFactory);
461
+ compilation.dependencyTemplates.set(AlphaTabWorkletDependency, new AlphaTabWorkletDependency.Template());
462
+ };
463
+ webPackWithAlphaTab.alphaTab.createWorkletDependency = (request, range, publicPath) => new AlphaTabWorkletDependency(request, range, publicPath);
464
+ }
465
+
466
+ /**@target web */
467
+ const WINDOWS_ABS_PATH_REGEXP = /^[a-zA-Z]:[\\/]/;
468
+ const WINDOWS_PATH_SEPARATOR_REGEXP = /\\/g;
469
+ const relativePathToRequest = (relativePath) => {
470
+ if (relativePath === '')
471
+ return './.';
472
+ if (relativePath === '..')
473
+ return '../.';
474
+ if (relativePath.startsWith('../'))
475
+ return relativePath;
476
+ return `./${relativePath}`;
477
+ };
478
+ const absoluteToRequest = (context, maybeAbsolutePath) => {
479
+ if (maybeAbsolutePath[0] === '/') {
480
+ if (maybeAbsolutePath.length > 1 && maybeAbsolutePath[maybeAbsolutePath.length - 1] === '/') {
481
+ // this 'path' is actually a regexp generated by dynamic requires.
482
+ // Don't treat it as an absolute path.
483
+ return maybeAbsolutePath;
484
+ }
485
+ const querySplitPos = maybeAbsolutePath.indexOf('?');
486
+ let resource = querySplitPos === -1 ? maybeAbsolutePath : maybeAbsolutePath.slice(0, querySplitPos);
487
+ resource = relativePathToRequest(path__namespace.posix.relative(context, resource));
488
+ return querySplitPos === -1 ? resource : resource + maybeAbsolutePath.slice(querySplitPos);
489
+ }
490
+ if (WINDOWS_ABS_PATH_REGEXP.test(maybeAbsolutePath)) {
491
+ const querySplitPos = maybeAbsolutePath.indexOf('?');
492
+ let resource = querySplitPos === -1 ? maybeAbsolutePath : maybeAbsolutePath.slice(0, querySplitPos);
493
+ resource = path__namespace.win32.relative(context, resource);
494
+ if (!WINDOWS_ABS_PATH_REGEXP.test(resource)) {
495
+ resource = relativePathToRequest(resource.replace(WINDOWS_PATH_SEPARATOR_REGEXP, '/'));
496
+ }
497
+ return querySplitPos === -1 ? resource : resource + maybeAbsolutePath.slice(querySplitPos);
498
+ }
499
+ // not an absolute path
500
+ return maybeAbsolutePath;
501
+ };
502
+ const _contextify = (context, request) => {
503
+ return request
504
+ .split('!')
505
+ .map(r => absoluteToRequest(context, r))
506
+ .join('!');
507
+ };
508
+ const makeCacheableWithContext = (fn) => {
509
+ const cache = new WeakMap();
510
+ const cachedFn = (context, identifier, associatedObjectForCache) => {
511
+ if (!associatedObjectForCache)
512
+ return fn(context, identifier);
513
+ let innerCache = cache.get(associatedObjectForCache);
514
+ if (innerCache === undefined) {
515
+ innerCache = new Map();
516
+ cache.set(associatedObjectForCache, innerCache);
517
+ }
518
+ let cachedResult;
519
+ let innerSubCache = innerCache.get(context);
520
+ if (innerSubCache === undefined) {
521
+ innerCache.set(context, (innerSubCache = new Map()));
522
+ }
523
+ else {
524
+ cachedResult = innerSubCache.get(identifier);
525
+ }
526
+ if (cachedResult !== undefined) {
527
+ return cachedResult;
528
+ }
529
+ else {
530
+ const result = fn(context, identifier);
531
+ innerSubCache.set(identifier, result);
532
+ return result;
533
+ }
534
+ };
535
+ cachedFn.bindContextCache = (context, associatedObjectForCache) => {
536
+ let innerSubCache;
537
+ if (associatedObjectForCache) {
538
+ let innerCache = cache.get(associatedObjectForCache);
539
+ if (innerCache === undefined) {
540
+ innerCache = new Map();
541
+ cache.set(associatedObjectForCache, innerCache);
542
+ }
543
+ innerSubCache = innerCache.get(context);
544
+ if (innerSubCache === undefined) {
545
+ innerCache.set(context, (innerSubCache = new Map()));
546
+ }
547
+ }
548
+ else {
549
+ innerSubCache = new Map();
550
+ }
551
+ const boundFn = (identifier) => {
552
+ const cachedResult = innerSubCache.get(identifier);
553
+ if (cachedResult !== undefined) {
554
+ return cachedResult;
555
+ }
556
+ else {
557
+ const result = fn(context, identifier);
558
+ innerSubCache.set(identifier, result);
559
+ return result;
560
+ }
561
+ };
562
+ return boundFn;
563
+ };
564
+ return cachedFn;
565
+ };
566
+ const contextify = makeCacheableWithContext(_contextify);
378
567
  class AlphaTabWebPackPlugin {
379
568
  constructor(options) {
380
569
  this.options = options ?? {};
381
570
  }
382
571
  apply(compiler) {
572
+ // here we create all plugin related class implementations using
573
+ // the webpack instance provided to this plugin (not as global import)
574
+ // after that we use the helper and factory functions we add to webpack
575
+ const webPackWithAlphaTab = {
576
+ webpack: compiler.webpack,
577
+ alphaTab: {}
578
+ };
579
+ if ('alphaTab' in compiler.webpack.util.serialization.register) { // prevent multi registration
580
+ webPackWithAlphaTab.alphaTab = compiler.webpack.util.serialization.register.alphaTab;
581
+ }
582
+ else {
583
+ compiler.webpack.util.serialization.register.alphaTab = webPackWithAlphaTab.alphaTab;
584
+ injectWebWorkerDependency(webPackWithAlphaTab);
585
+ injectWorkerRuntimeModule(webPackWithAlphaTab);
586
+ injectWorkletDependency(webPackWithAlphaTab);
587
+ injectWorkletRuntimeModule(webPackWithAlphaTab);
588
+ }
589
+ this._webPackWithAlphaTab = webPackWithAlphaTab;
383
590
  this.configureSoundFont(compiler);
384
591
  this.configure(compiler);
385
592
  }
@@ -390,48 +597,41 @@ class AlphaTabWebPackPlugin {
390
597
  // register soundfont as resource
391
598
  compiler.options.module.rules.push({
392
599
  test: /\.sf2/,
393
- type: "asset/resource",
600
+ type: 'asset/resource'
394
601
  });
395
602
  }
396
603
  configure(compiler) {
397
604
  const pluginName = this.constructor.name;
398
- const cachedContextify = identifier.contextify.bindContextCache(compiler.context, compiler.root);
605
+ const cachedContextify = contextify.bindContextCache(compiler.context, compiler.root);
399
606
  compiler.hooks.thisCompilation.tap(pluginName, (compilation, { normalModuleFactory }) => {
400
- compilation.hooks.runtimeRequirementInTree
401
- .for(AlphaTabWorkerRuntimeModule.Key)
402
- .tap(pluginName, (chunk) => {
403
- compilation.addRuntimeModule(chunk, new AlphaTabWorkerRuntimeModule());
404
- });
405
- compilation.hooks.runtimeRequirementInTree
406
- .for(AlphaTabWorkletStartRuntimeModule.RuntimeGlobalWorkletGetStartupChunks)
407
- .tap(pluginName, (chunk) => {
408
- compilation.addRuntimeModule(chunk, new AlphaTabWorkletStartRuntimeModule());
409
- });
410
- configureAudioWorklet(pluginName, this.options, compiler, compilation, normalModuleFactory, cachedContextify);
411
- configureWebWorker(pluginName, this.options, compiler, compilation, normalModuleFactory, cachedContextify);
412
- this.configureAssetCopy(pluginName, compiler, compilation);
607
+ this._webPackWithAlphaTab.alphaTab.registerWebWorkerRuntimeModule(pluginName, compilation);
608
+ this._webPackWithAlphaTab.alphaTab.registerWorkletRuntimeModule(pluginName, compilation);
609
+ configureAudioWorklet(this._webPackWithAlphaTab, pluginName, this.options, compiler, compilation, normalModuleFactory, cachedContextify);
610
+ configureWebWorker(this._webPackWithAlphaTab, pluginName, this.options, compiler, compilation, normalModuleFactory, cachedContextify);
611
+ this.configureAssetCopy(this._webPackWithAlphaTab, pluginName, compiler, compilation);
413
612
  });
414
613
  }
415
- configureAssetCopy(pluginName, compiler, compilation) {
614
+ configureAssetCopy(webPackWithAlphaTab, pluginName, compiler, compilation) {
416
615
  if (this.options.assetOutputDir === false) {
417
616
  return;
418
617
  }
419
618
  const options = this.options;
420
619
  compilation.hooks.processAssets.tapAsync({
421
620
  name: pluginName,
422
- stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
621
+ stage: this._webPackWithAlphaTab.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
423
622
  }, async (_, callback) => {
424
623
  let alphaTabSourceDir = options.alphaTabSourceDir;
425
624
  if (!alphaTabSourceDir) {
426
625
  alphaTabSourceDir = compilation.getPath('node_modules/@coderline/alphatab/dist/');
427
626
  }
428
- if (!alphaTabSourceDir || !fs__namespace.promises.access(path__namespace.join(alphaTabSourceDir, 'alphaTab.mjs'), fs__namespace.constants.F_OK)) {
429
- compilation.errors.push(new webpack.WebpackError('Could not find alphaTab, please ensure it is installed into node_modules or configure alphaTabSourceDir'));
627
+ if (!alphaTabSourceDir ||
628
+ !fs__namespace.promises.access(path__namespace.join(alphaTabSourceDir, 'alphaTab.mjs'), fs__namespace.constants.F_OK)) {
629
+ compilation.errors.push(new this._webPackWithAlphaTab.webpack.WebpackError('Could not find alphaTab, please ensure it is installed into node_modules or configure alphaTabSourceDir'));
430
630
  return;
431
631
  }
432
632
  const outputPath = (options.assetOutputDir ?? compiler.options.output.path);
433
633
  if (!outputPath) {
434
- compilation.errors.push(new webpack.WebpackError('Need output.path configured in application to store asset files.'));
634
+ compilation.errors.push(new this._webPackWithAlphaTab.webpack.WebpackError('Need output.path configured in application to store asset files.'));
435
635
  return;
436
636
  }
437
637
  async function copyFiles(subdir) {
@@ -439,13 +639,15 @@ class AlphaTabWebPackPlugin {
439
639
  compilation.contextDependencies.add(path__namespace.normalize(fullDir));
440
640
  const files = await fs__namespace.promises.readdir(fullDir, { withFileTypes: true });
441
641
  await fs__namespace.promises.mkdir(path__namespace.join(outputPath, subdir), { recursive: true });
442
- await Promise.all(files.filter(f => f.isFile()).map(async (file) => {
642
+ await Promise.all(files
643
+ .filter(f => f.isFile())
644
+ .map(async (file) => {
443
645
  const sourceFilename = path__namespace.join(file.path, file.name);
444
646
  await fs__namespace.promises.copyFile(sourceFilename, path__namespace.join(outputPath, subdir, file.name));
445
647
  const assetFileName = subdir + '/' + file.name;
446
648
  const existingAsset = compilation.getAsset(assetFileName);
447
649
  const data = await fs__namespace.promises.readFile(sourceFilename);
448
- const source = new compiler.webpack.sources.RawSource(data);
650
+ const source = new webPackWithAlphaTab.webpack.sources.RawSource(data);
449
651
  if (existingAsset) {
450
652
  compilation.updateAsset(assetFileName, source, {
451
653
  copied: true,
@@ -460,10 +662,7 @@ class AlphaTabWebPackPlugin {
460
662
  }
461
663
  }));
462
664
  }
463
- await Promise.all([
464
- copyFiles("font"),
465
- copyFiles("soundfont")
466
- ]);
665
+ await Promise.all([copyFiles('font'), copyFiles('soundfont')]);
467
666
  callback();
468
667
  });
469
668
  }