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