@lynxwall/cucumber-tsflow 7.6.0 → 7.7.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.
Files changed (71) hide show
  1. package/README.md +266 -229
  2. package/lib/api/convert-configuration.d.ts +1 -0
  3. package/lib/api/convert-configuration.js +2 -0
  4. package/lib/api/convert-configuration.js.map +1 -1
  5. package/lib/api/load-configuration.js +23 -31
  6. package/lib/api/load-configuration.js.map +1 -1
  7. package/lib/api/load-support.d.ts +11 -2
  8. package/lib/api/load-support.js +31 -6
  9. package/lib/api/load-support.js.map +1 -1
  10. package/lib/api/loader-worker.d.ts +36 -0
  11. package/lib/api/loader-worker.js +74 -0
  12. package/lib/api/loader-worker.js.map +1 -0
  13. package/lib/api/parallel-loader.d.ts +31 -0
  14. package/lib/api/parallel-loader.js +169 -0
  15. package/lib/api/parallel-loader.js.map +1 -0
  16. package/lib/api/run-cucumber.js +42 -12
  17. package/lib/api/run-cucumber.js.map +1 -1
  18. package/lib/api/support.js +3 -0
  19. package/lib/api/support.js.map +1 -1
  20. package/lib/api/wrapper.mjs +1 -0
  21. package/lib/bindings/binding-decorator.d.ts +6 -0
  22. package/lib/bindings/binding-decorator.js +14 -0
  23. package/lib/bindings/binding-decorator.js.map +1 -1
  24. package/lib/bindings/binding-registry.d.ts +31 -1
  25. package/lib/bindings/binding-registry.js +95 -47
  26. package/lib/bindings/binding-registry.js.map +1 -1
  27. package/lib/bindings/step-binding.d.ts +37 -0
  28. package/lib/bindings/step-binding.js +23 -0
  29. package/lib/bindings/step-binding.js.map +1 -1
  30. package/lib/bindings/step-decorators.js.map +1 -1
  31. package/lib/bindings/types.js.map +1 -1
  32. package/lib/cli/argv-parser.d.ts +1 -0
  33. package/lib/cli/argv-parser.js +6 -0
  34. package/lib/cli/argv-parser.js.map +1 -1
  35. package/lib/formatter/{step-definition-snippit-syntax → step-definition-snippet-syntax}/tsflow-snippet-syntax.js.map +1 -1
  36. package/lib/index.d.ts +1 -1
  37. package/lib/index.js +1 -1
  38. package/lib/index.js.map +1 -1
  39. package/lib/runtime/coordinator.d.ts +2 -1
  40. package/lib/runtime/coordinator.js +4 -2
  41. package/lib/runtime/coordinator.js.map +1 -1
  42. package/lib/runtime/make-runtime.d.ts +3 -1
  43. package/lib/runtime/make-runtime.js +5 -4
  44. package/lib/runtime/make-runtime.js.map +1 -1
  45. package/lib/runtime/managed-scenario-context.js +2 -32
  46. package/lib/runtime/managed-scenario-context.js.map +1 -1
  47. package/lib/runtime/parallel/adapter.d.ts +4 -1
  48. package/lib/runtime/parallel/adapter.js +10 -2
  49. package/lib/runtime/parallel/adapter.js.map +1 -1
  50. package/lib/runtime/serial/adapter.d.ts +2 -1
  51. package/lib/runtime/serial/adapter.js +13 -3
  52. package/lib/runtime/serial/adapter.js.map +1 -1
  53. package/lib/runtime/test-case-runner.d.ts +4 -1
  54. package/lib/runtime/test-case-runner.js +4 -5
  55. package/lib/runtime/test-case-runner.js.map +1 -1
  56. package/lib/runtime/types.d.ts +2 -0
  57. package/lib/runtime/types.js.map +1 -1
  58. package/lib/runtime/utils.js +0 -6
  59. package/lib/runtime/utils.js.map +1 -1
  60. package/lib/runtime/worker.d.ts +14 -3
  61. package/lib/runtime/worker.js +91 -12
  62. package/lib/runtime/worker.js.map +1 -1
  63. package/lib/snippet.js +1 -1
  64. package/lib/snippet.js.map +1 -1
  65. package/lib/tsconfig.node.tsbuildinfo +1 -1
  66. package/lib/version.d.ts +1 -1
  67. package/lib/version.js +1 -1
  68. package/lib/version.js.map +1 -1
  69. package/package.json +8 -7
  70. /package/lib/formatter/{step-definition-snippit-syntax → step-definition-snippet-syntax}/tsflow-snippet-syntax.d.ts +0 -0
  71. /package/lib/formatter/{step-definition-snippit-syntax → step-definition-snippet-syntax}/tsflow-snippet-syntax.js +0 -0
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parallelPreload = parallelPreload;
7
+ /**
8
+ * parallel-loader.ts
9
+ *
10
+ * Orchestrates parallel pre-warming of transpiler caches using worker_threads.
11
+ * Each worker loads a subset of support-code files, warming the transpiler's
12
+ * on-disk cache. After all workers finish, the main thread performs the
13
+ * authoritative load (which hits warm caches and runs much faster).
14
+ *
15
+ * The descriptors returned by workers are used for validation — the main
16
+ * thread's BindingRegistry is the canonical source of truth.
17
+ */
18
+ const node_worker_threads_1 = require("node:worker_threads");
19
+ const node_os_1 = require("node:os");
20
+ const node_path_1 = __importDefault(require("node:path"));
21
+ const tsflow_logger_1 = require("../utils/tsflow-logger");
22
+ const logger = (0, tsflow_logger_1.createLogger)('parallel-loader');
23
+ /**
24
+ * Pre-warm transpiler caches by loading support files in parallel worker threads.
25
+ *
26
+ * Each worker receives a subset of files, loads them (which triggers transpilation),
27
+ * and returns serializable binding descriptors. The transpiler cache on disk is now
28
+ * warm for the main thread's subsequent load.
29
+ */
30
+ async function parallelPreload(options) {
31
+ const start = performance.now();
32
+ const threads = resolveThreadCount(options.threadCount);
33
+ logger.checkpoint('Starting parallel preload', {
34
+ threads,
35
+ requirePaths: options.requirePaths.length,
36
+ importPaths: options.importPaths.length
37
+ });
38
+ // Split files across workers — round-robin distribution
39
+ const requireChunks = chunkRoundRobin(options.requirePaths, threads);
40
+ const importChunks = chunkRoundRobin(options.importPaths, threads);
41
+ // Resolve the worker script path (compiled JS in lib/)
42
+ const workerScript = resolveWorkerScript();
43
+ logger.checkpoint('Worker script resolved', { workerScript });
44
+ // Launch workers
45
+ const workerPromises = [];
46
+ for (let i = 0; i < threads; i++) {
47
+ // Only launch a worker if it has files to process
48
+ if (requireChunks[i].length === 0 && importChunks[i].length === 0) {
49
+ continue;
50
+ }
51
+ const request = {
52
+ type: 'LOAD',
53
+ requirePaths: requireChunks[i],
54
+ importPaths: importChunks[i],
55
+ requireModules: options.requireModules,
56
+ loaders: options.loaders,
57
+ experimentalDecorators: options.experimentalDecorators
58
+ };
59
+ workerPromises.push(runWorker(workerScript, request, i));
60
+ }
61
+ // Await all workers
62
+ const results = await Promise.allSettled(workerPromises);
63
+ // Collect results
64
+ const allDescriptors = [];
65
+ const allFiles = new Set();
66
+ let errors = 0;
67
+ for (const result of results) {
68
+ if (result.status === 'fulfilled') {
69
+ const response = result.value;
70
+ if (response.type === 'LOADED') {
71
+ if (response.descriptors) {
72
+ allDescriptors.push(...response.descriptors);
73
+ }
74
+ if (response.loadedFiles) {
75
+ response.loadedFiles.forEach(f => allFiles.add(f));
76
+ }
77
+ }
78
+ else {
79
+ errors++;
80
+ logger.error('Worker reported error', new Error(response.error || 'Unknown worker error'));
81
+ }
82
+ }
83
+ else {
84
+ errors++;
85
+ logger.error('Worker promise rejected', result.reason);
86
+ }
87
+ }
88
+ const durationMs = Math.round(performance.now() - start);
89
+ logger.checkpoint('Parallel preload completed', {
90
+ durationMs,
91
+ descriptorCount: allDescriptors.length,
92
+ fileCount: allFiles.size,
93
+ errors
94
+ });
95
+ if (errors > 0) {
96
+ logger.checkpoint('Some workers failed — main thread will do full load as fallback');
97
+ }
98
+ return {
99
+ descriptors: allDescriptors,
100
+ loadedFiles: Array.from(allFiles),
101
+ durationMs
102
+ };
103
+ }
104
+ /**
105
+ * Run a single loader-worker and return its response.
106
+ */
107
+ function runWorker(workerScript, request, index) {
108
+ return new Promise((resolve, reject) => {
109
+ const worker = new node_worker_threads_1.Worker(workerScript, {
110
+ workerData: request
111
+ });
112
+ let settled = false;
113
+ worker.on('message', (msg) => {
114
+ if (!settled) {
115
+ settled = true;
116
+ logger.checkpoint(`Worker ${index} completed`, { type: msg.type });
117
+ worker.terminate();
118
+ resolve(msg);
119
+ }
120
+ });
121
+ worker.on('error', err => {
122
+ if (!settled) {
123
+ settled = true;
124
+ logger.error(`Worker ${index} error`, err);
125
+ reject(err);
126
+ }
127
+ });
128
+ worker.on('exit', code => {
129
+ if (!settled) {
130
+ settled = true;
131
+ if (code !== 0) {
132
+ reject(new Error(`Worker ${index} exited with code ${code}`));
133
+ }
134
+ }
135
+ });
136
+ });
137
+ }
138
+ /**
139
+ * Resolve the number of threads to use.
140
+ * - true: use availableParallelism() capped at 4
141
+ * - number: use that exact count (min 1)
142
+ */
143
+ function resolveThreadCount(threadCount) {
144
+ if (typeof threadCount === 'number') {
145
+ return Math.max(1, threadCount);
146
+ }
147
+ // Auto-detect: use available parallelism, capped at a reasonable default
148
+ return Math.min((0, node_os_1.availableParallelism)(), 4);
149
+ }
150
+ /**
151
+ * Distribute items round-robin across N buckets.
152
+ */
153
+ function chunkRoundRobin(items, buckets) {
154
+ const chunks = Array.from({ length: buckets }, () => []);
155
+ for (let i = 0; i < items.length; i++) {
156
+ chunks[i % buckets].push(items[i]);
157
+ }
158
+ return chunks;
159
+ }
160
+ /**
161
+ * Resolve the path to the compiled loader-worker script.
162
+ * In development (src), this file is adjacent; in production (lib/), it's compiled.
163
+ */
164
+ function resolveWorkerScript() {
165
+ // Try the compiled lib path first, falling back to __dirname
166
+ const libPath = node_path_1.default.resolve(__dirname, 'loader-worker.js');
167
+ return libPath;
168
+ }
169
+ //# sourceMappingURL=parallel-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel-loader.js","sourceRoot":"","sources":["../../src/api/parallel-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * parallel-loader.ts\r\n *\r\n * Orchestrates parallel pre-warming of transpiler caches using worker_threads.\r\n * Each worker loads a subset of support-code files, warming the transpiler's\r\n * on-disk cache. After all workers finish, the main thread performs the\r\n * authoritative load (which hits warm caches and runs much faster).\r\n *\r\n * The descriptors returned by workers are used for validation — the main\r\n * thread's BindingRegistry is the canonical source of truth.\r\n */\r\nimport { Worker } from 'node:worker_threads';\r\nimport { availableParallelism } from 'node:os';\r\nimport path from 'node:path';\r\nimport type { LoaderWorkerRequest, LoaderWorkerResponse } from './loader-worker';\r\nimport type { SerializableBindingDescriptor } from '../bindings/step-binding';\r\nimport { createLogger } from '../utils/tsflow-logger';\r\n\r\nconst logger = createLogger('parallel-loader');\r\n\r\nexport interface ParallelLoadOptions {\r\n\t/** Absolute require-paths for CJS support files */\r\n\trequirePaths: string[];\r\n\t/** Absolute import-paths for ESM support files */\r\n\timportPaths: string[];\r\n\t/** Modules to require before support code (transpiler hooks) */\r\n\trequireModules: string[];\r\n\t/** ESM loaders to register */\r\n\tloaders: string[];\r\n\t/** Whether experimental decorators are enabled */\r\n\texperimentalDecorators: boolean;\r\n\t/** Number of threads (true = auto, number = explicit) */\r\n\tthreadCount: boolean | number;\r\n}\r\n\r\nexport interface ParallelLoadResult {\r\n\t/** All descriptors collected across workers (for validation) */\r\n\tdescriptors: SerializableBindingDescriptor[];\r\n\t/** Unique source files loaded across all workers */\r\n\tloadedFiles: string[];\r\n\t/** Time spent in parallel phase (ms) */\r\n\tdurationMs: number;\r\n}\r\n\r\n/**\r\n * Pre-warm transpiler caches by loading support files in parallel worker threads.\r\n *\r\n * Each worker receives a subset of files, loads them (which triggers transpilation),\r\n * and returns serializable binding descriptors. The transpiler cache on disk is now\r\n * warm for the main thread's subsequent load.\r\n */\r\nexport async function parallelPreload(options: ParallelLoadOptions): Promise<ParallelLoadResult> {\r\n\tconst start = performance.now();\r\n\r\n\tconst threads = resolveThreadCount(options.threadCount);\r\n\tlogger.checkpoint('Starting parallel preload', {\r\n\t\tthreads,\r\n\t\trequirePaths: options.requirePaths.length,\r\n\t\timportPaths: options.importPaths.length\r\n\t});\r\n\r\n\t// Split files across workers — round-robin distribution\r\n\tconst requireChunks = chunkRoundRobin(options.requirePaths, threads);\r\n\tconst importChunks = chunkRoundRobin(options.importPaths, threads);\r\n\r\n\t// Resolve the worker script path (compiled JS in lib/)\r\n\tconst workerScript = resolveWorkerScript();\r\n\tlogger.checkpoint('Worker script resolved', { workerScript });\r\n\r\n\t// Launch workers\r\n\tconst workerPromises: Promise<LoaderWorkerResponse>[] = [];\r\n\r\n\tfor (let i = 0; i < threads; i++) {\r\n\t\t// Only launch a worker if it has files to process\r\n\t\tif (requireChunks[i].length === 0 && importChunks[i].length === 0) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n\t\tconst request: LoaderWorkerRequest = {\r\n\t\t\ttype: 'LOAD',\r\n\t\t\trequirePaths: requireChunks[i],\r\n\t\t\timportPaths: importChunks[i],\r\n\t\t\trequireModules: options.requireModules,\r\n\t\t\tloaders: options.loaders,\r\n\t\t\texperimentalDecorators: options.experimentalDecorators\r\n\t\t};\r\n\r\n\t\tworkerPromises.push(runWorker(workerScript, request, i));\r\n\t}\r\n\r\n\t// Await all workers\r\n\tconst results = await Promise.allSettled(workerPromises);\r\n\r\n\t// Collect results\r\n\tconst allDescriptors: SerializableBindingDescriptor[] = [];\r\n\tconst allFiles = new Set<string>();\r\n\tlet errors = 0;\r\n\r\n\tfor (const result of results) {\r\n\t\tif (result.status === 'fulfilled') {\r\n\t\t\tconst response = result.value;\r\n\t\t\tif (response.type === 'LOADED') {\r\n\t\t\t\tif (response.descriptors) {\r\n\t\t\t\t\tallDescriptors.push(...response.descriptors);\r\n\t\t\t\t}\r\n\t\t\t\tif (response.loadedFiles) {\r\n\t\t\t\t\tresponse.loadedFiles.forEach(f => allFiles.add(f));\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\terrors++;\r\n\t\t\t\tlogger.error('Worker reported error', new Error(response.error || 'Unknown worker error'));\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\terrors++;\r\n\t\t\tlogger.error('Worker promise rejected', result.reason);\r\n\t\t}\r\n\t}\r\n\r\n\tconst durationMs = Math.round(performance.now() - start);\r\n\tlogger.checkpoint('Parallel preload completed', {\r\n\t\tdurationMs,\r\n\t\tdescriptorCount: allDescriptors.length,\r\n\t\tfileCount: allFiles.size,\r\n\t\terrors\r\n\t});\r\n\r\n\tif (errors > 0) {\r\n\t\tlogger.checkpoint('Some workers failed — main thread will do full load as fallback');\r\n\t}\r\n\r\n\treturn {\r\n\t\tdescriptors: allDescriptors,\r\n\t\tloadedFiles: Array.from(allFiles),\r\n\t\tdurationMs\r\n\t};\r\n}\r\n\r\n/**\r\n * Run a single loader-worker and return its response.\r\n */\r\nfunction runWorker(workerScript: string, request: LoaderWorkerRequest, index: number): Promise<LoaderWorkerResponse> {\r\n\treturn new Promise((resolve, reject) => {\r\n\t\tconst worker = new Worker(workerScript, {\r\n\t\t\tworkerData: request\r\n\t\t});\r\n\r\n\t\tlet settled = false;\r\n\r\n\t\tworker.on('message', (msg: LoaderWorkerResponse) => {\r\n\t\t\tif (!settled) {\r\n\t\t\t\tsettled = true;\r\n\t\t\t\tlogger.checkpoint(`Worker ${index} completed`, { type: msg.type });\r\n\t\t\t\tworker.terminate();\r\n\t\t\t\tresolve(msg);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tworker.on('error', err => {\r\n\t\t\tif (!settled) {\r\n\t\t\t\tsettled = true;\r\n\t\t\t\tlogger.error(`Worker ${index} error`, err);\r\n\t\t\t\treject(err);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tworker.on('exit', code => {\r\n\t\t\tif (!settled) {\r\n\t\t\t\tsettled = true;\r\n\t\t\t\tif (code !== 0) {\r\n\t\t\t\t\treject(new Error(`Worker ${index} exited with code ${code}`));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\t});\r\n}\r\n\r\n/**\r\n * Resolve the number of threads to use.\r\n * - true: use availableParallelism() capped at 4\r\n * - number: use that exact count (min 1)\r\n */\r\nfunction resolveThreadCount(threadCount: boolean | number): number {\r\n\tif (typeof threadCount === 'number') {\r\n\t\treturn Math.max(1, threadCount);\r\n\t}\r\n\t// Auto-detect: use available parallelism, capped at a reasonable default\r\n\treturn Math.min(availableParallelism(), 4);\r\n}\r\n\r\n/**\r\n * Distribute items round-robin across N buckets.\r\n */\r\nfunction chunkRoundRobin<T>(items: T[], buckets: number): T[][] {\r\n\tconst chunks: T[][] = Array.from({ length: buckets }, (): T[] => []);\r\n\tfor (let i = 0; i < items.length; i++) {\r\n\t\tchunks[i % buckets].push(items[i]);\r\n\t}\r\n\treturn chunks;\r\n}\r\n\r\n/**\r\n * Resolve the path to the compiled loader-worker script.\r\n * In development (src), this file is adjacent; in production (lib/), it's compiled.\r\n */\r\nfunction resolveWorkerScript(): string {\r\n\t// Try the compiled lib path first, falling back to __dirname\r\n\tconst libPath = path.resolve(__dirname, 'loader-worker.js');\r\n\treturn libPath;\r\n}\r\n"]}
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runCucumber = runCucumber;
7
7
  const messages_1 = require("@cucumber/messages");
8
8
  const events_1 = require("events");
9
- const helpers_1 = require("@cucumber/cucumber/lib/cli/helpers");
9
+ const emit_support_code_messages_1 = require("@cucumber/cucumber/lib/api/emit_support_code_messages");
10
10
  const index_1 = require("@cucumber/cucumber/lib/paths/index");
11
11
  const make_runtime_1 = require("../runtime/make-runtime");
12
12
  const formatters_1 = require("@cucumber/cucumber/lib/api/formatters");
@@ -20,6 +20,9 @@ require("polyfill-symbol-metadata");
20
20
  const binding_registry_1 = require("../bindings/binding-registry");
21
21
  const console_1 = require("console");
22
22
  const ansis_1 = __importDefault(require("ansis"));
23
+ const parallel_loader_1 = require("./parallel-loader");
24
+ const tsflow_logger_1 = require("../utils/tsflow-logger");
25
+ const runLogger = (0, tsflow_logger_1.createLogger)('run-cucumber');
23
26
  /**
24
27
  * Execute a Cucumber test run.
25
28
  *
@@ -71,15 +74,42 @@ Running from: ${__dirname}
71
74
  */
72
75
  let supportCodeLibrary = 'originalCoordinates' in options.support
73
76
  ? options.support
74
- : await (0, support_1.getSupportCodeLibrary)({
75
- logger,
76
- cwd,
77
- newId,
78
- requirePaths,
79
- requireModules: supportCoordinates.requireModules,
80
- importPaths,
81
- loaders: supportCoordinates.loaders
82
- });
77
+ : await (async () => {
78
+ // Parallel preload phase: warm transpiler caches in worker threads
79
+ if (options.runtime.parallelLoad) {
80
+ runLogger.checkpoint('Running parallel preload phase');
81
+ consoleLogger.info(ansis_1.default.cyanBright('Pre-warming transpiler caches in parallel...\n'));
82
+ try {
83
+ const result = await (0, parallel_loader_1.parallelPreload)({
84
+ requirePaths,
85
+ importPaths,
86
+ requireModules: supportCoordinates.requireModules,
87
+ loaders: supportCoordinates.loaders,
88
+ experimentalDecorators: options.runtime.experimentalDecorators,
89
+ threadCount: options.runtime.parallelLoad
90
+ });
91
+ runLogger.checkpoint('Parallel preload completed', {
92
+ descriptors: result.descriptors.length,
93
+ files: result.loadedFiles.length,
94
+ durationMs: result.durationMs
95
+ });
96
+ consoleLogger.info(ansis_1.default.cyanBright(`Parallel preload completed in ${result.durationMs}ms ` +
97
+ `(${result.loadedFiles.length} files, ${result.descriptors.length} bindings)\n`));
98
+ }
99
+ catch (err) {
100
+ runLogger.error('Parallel preload failed, falling back to serial load', err);
101
+ }
102
+ }
103
+ return (0, support_1.getSupportCodeLibrary)({
104
+ logger,
105
+ cwd,
106
+ newId,
107
+ requirePaths,
108
+ requireModules: supportCoordinates.requireModules,
109
+ importPaths,
110
+ loaders: supportCoordinates.loaders
111
+ });
112
+ })();
83
113
  // Set support to the updated step and hook definitions
84
114
  // in the supportCodeLibrary. We also need to initialize originalCoordinates
85
115
  // to support parallel execution.
@@ -111,7 +141,7 @@ Running from: ${__dirname}
111
141
  supportCodeLibrary,
112
142
  pluginManager
113
143
  });
114
- await (0, helpers_1.emitMetaMessage)(eventBroadcaster, env);
144
+ await (0, emit_support_code_messages_1.emitMetaMessage)(eventBroadcaster, env);
115
145
  let filteredPickles = [];
116
146
  let parseErrors = [];
117
147
  if (sourcePaths.length > 0) {
@@ -137,7 +167,7 @@ Running from: ${__dirname}
137
167
  support: supportCodeLibrary
138
168
  };
139
169
  }
140
- (0, helpers_1.emitSupportCodeMessages)({
170
+ (0, emit_support_code_messages_1.emitSupportCodeMessages)({
141
171
  eventBroadcaster,
142
172
  supportCodeLibrary,
143
173
  newId
@@ -1 +1 @@
1
- {"version":3,"file":"run-cucumber.js","sourceRoot":"","sources":["../../src/api/run-cucumber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Envelope, IdGenerator, ParseError } from '@cucumber/messages';\r\nimport { EventEmitter } from 'events';\r\nimport { EventDataCollector } from '@cucumber/cucumber/lib/formatter/helpers/index';\r\nimport { emitMetaMessage, emitSupportCodeMessages } from '@cucumber/cucumber/lib/cli/helpers';\r\nimport { IRunOptions, IRunResult } from '@cucumber/cucumber/lib/api/types';\r\nimport { resolvePaths } from '@cucumber/cucumber/lib/paths/index';\r\nimport { SupportCodeLibrary } from '@cucumber/cucumber/lib/support_code_library_builder/types';\r\nimport { makeRuntime } from '../runtime/make-runtime';\r\nimport { initializeFormatters } from '@cucumber/cucumber/lib/api/formatters';\r\nimport { getSupportCodeLibrary } from './support';\r\nimport { IRunEnvironment, makeEnvironment } from '@cucumber/cucumber/lib/environment/index';\r\nimport { getPicklesAndErrors } from '@cucumber/cucumber/lib/api/gherkin';\r\nimport MessageCollector from '../runtime/message-collector';\r\nimport { version } from '../version';\r\nimport { initializeForRunCucumber } from '@cucumber/cucumber/lib/api/plugins';\r\nimport { IFilterablePickle } from '@cucumber/cucumber/lib/filter/index';\r\nimport 'polyfill-symbol-metadata';\r\nimport { BindingRegistry } from '../bindings/binding-registry';\r\nimport { ITsFlowRunOptionsRuntime } from '../runtime/types';\r\nimport { Console } from 'console';\r\nimport ansis from 'ansis';\r\nimport { supportCodeLibraryBuilder } from '@cucumber/cucumber';\r\n\r\nexport interface ITsFlowRunOptions extends IRunOptions {\r\n\truntime: ITsFlowRunOptionsRuntime;\r\n}\r\n\r\n/**\r\n * Execute a Cucumber test run.\r\n *\r\n * Extended from cucumber.js so that we can use our own implementation\r\n * of makeRuntime\r\n *\r\n * @public\r\n * @param options - Configuration loaded from `loadConfiguration`.\r\n * @param environment - Project environment.\r\n * @param onMessage - Callback fired each time Cucumber emits a message.\r\n */\r\nexport async function runCucumber(\r\n\toptions: ITsFlowRunOptions,\r\n\tenvironment: IRunEnvironment = {},\r\n\tonMessage?: (message: Envelope) => void\r\n): Promise<IRunResult> {\r\n\tconst mergedEnvironment = makeEnvironment(environment);\r\n\tconst { cwd, stdout, stderr, env, logger } = mergedEnvironment;\r\n\r\n\tlogger.debug(`Running cucumber-tsflow ${version}\r\nWorking directory: ${cwd}\r\nRunning from: ${__dirname}\r\n`);\r\n\tconst consoleLogger = new Console(environment.stdout as any, environment.stderr);\r\n\tif (options.runtime.experimentalDecorators) {\r\n\t\tconsoleLogger.info(ansis.yellowBright('Using Experimental Decorators.'));\r\n\t}\r\n\tif (options.runtime.parallel > 0) {\r\n\t\tconsoleLogger.info(\r\n\t\t\tansis.cyanBright(`Running Cucumber-TsFlow in Parallel with ${options.runtime.parallel} worker(s).\\n`)\r\n\t\t);\r\n\t} else {\r\n\t\tconsoleLogger.info(ansis.cyanBright('Running Cucumber-TsFlow in Serial mode.\\n'));\r\n\t}\r\n\r\n\tconst newId = IdGenerator.uuid();\r\n\r\n\tconst supportCoordinates =\r\n\t\t'originalCoordinates' in options.support\r\n\t\t\t? options.support.originalCoordinates\r\n\t\t\t: Object.assign(\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trequireModules: [],\r\n\t\t\t\t\t\trequirePaths: [],\r\n\t\t\t\t\t\tloaders: [],\r\n\t\t\t\t\t\timportPaths: []\r\n\t\t\t\t\t},\r\n\t\t\t\t\toptions.support\r\n\t\t\t\t);\r\n\r\n\tconst pluginManager = await initializeForRunCucumber(\r\n\t\t{\r\n\t\t\t...options,\r\n\t\t\tsupport: supportCoordinates\r\n\t\t},\r\n\t\tmergedEnvironment\r\n\t);\r\n\r\n\tconst resolvedPaths = await resolvePaths(logger, cwd, options.sources, supportCoordinates);\r\n\tpluginManager.emit('paths:resolve', resolvedPaths);\r\n\tconst { sourcePaths, requirePaths, importPaths } = resolvedPaths;\r\n\r\n\t/**\r\n\t * The support code library contains all of the hook and step definitions.\r\n\t * These are loaded into the library when calling getSupportCodeLibrary,\r\n\t * which loads all of the step definitions using require or import.\r\n\t */\r\n\tlet supportCodeLibrary =\r\n\t\t'originalCoordinates' in options.support\r\n\t\t\t? (options.support as SupportCodeLibrary)\r\n\t\t\t: await getSupportCodeLibrary({\r\n\t\t\t\t\tlogger,\r\n\t\t\t\t\tcwd,\r\n\t\t\t\t\tnewId,\r\n\t\t\t\t\trequirePaths,\r\n\t\t\t\t\trequireModules: supportCoordinates.requireModules,\r\n\t\t\t\t\timportPaths,\r\n\t\t\t\t\tloaders: supportCoordinates.loaders\r\n\t\t\t\t});\r\n\r\n\t// Set support to the updated step and hook definitions\r\n\t// in the supportCodeLibrary. We also need to initialize originalCoordinates\r\n\t// to support parallel execution.\r\n\tsupportCodeLibrary = BindingRegistry.instance.updateSupportCodeLibrary(supportCodeLibrary);\r\n\tsupportCodeLibrary = { ...supportCodeLibrary, ...{ originalCoordinates: supportCoordinates } };\r\n\toptions.support = supportCodeLibrary;\r\n\r\n\tconst eventBroadcaster = new EventEmitter();\r\n\tif (onMessage) {\r\n\t\teventBroadcaster.on('envelope', onMessage);\r\n\t}\r\n\teventBroadcaster.on('envelope', value => pluginManager.emit('message', value));\r\n\r\n\t// create a global instance of the message collector and bind it\r\n\t// to the event broadcaster. This is used by cucumber and for tests\r\n\t// that are not running in parallel.\r\n\tglobal.messageCollector = new MessageCollector(eventBroadcaster);\r\n\r\n\t// cast the MessageCollector to an EventDataCollector\r\n\tconst eventDataCollector = global.messageCollector as unknown as EventDataCollector;\r\n\r\n\tlet formatterStreamError = false;\r\n\tconst cleanupFormatters = await initializeFormatters({\r\n\t\tenv,\r\n\t\tcwd,\r\n\t\tstdout,\r\n\t\tstderr,\r\n\t\tlogger,\r\n\t\tonStreamError: () => (formatterStreamError = true),\r\n\t\teventBroadcaster,\r\n\t\teventDataCollector: eventDataCollector,\r\n\t\tconfiguration: options.formats,\r\n\t\tsupportCodeLibrary,\r\n\t\tpluginManager\r\n\t});\r\n\tawait emitMetaMessage(eventBroadcaster, env);\r\n\r\n\tlet filteredPickles: ReadonlyArray<IFilterablePickle> = [];\r\n\tlet parseErrors: ParseError[] = [];\r\n\tif (sourcePaths.length > 0) {\r\n\t\tconst gherkinResult = await getPicklesAndErrors({\r\n\t\t\tnewId,\r\n\t\t\tcwd,\r\n\t\t\tsourcePaths,\r\n\t\t\tcoordinates: options.sources,\r\n\t\t\tonEnvelope: envelope => eventBroadcaster.emit('envelope', envelope)\r\n\t\t});\r\n\t\tfilteredPickles = await pluginManager.transform('pickles:filter', gherkinResult.filterablePickles);\r\n\t\tfilteredPickles = await pluginManager.transform('pickles:order', filteredPickles);\r\n\t\tparseErrors = gherkinResult.parseErrors;\r\n\t}\r\n\tif (parseErrors.length) {\r\n\t\tparseErrors.forEach(parseError => {\r\n\t\t\tlogger.error(`Parse error in \"${parseError.source.uri}\" ${parseError.message}`);\r\n\t\t});\r\n\t\tawait cleanupFormatters();\r\n\t\tawait pluginManager.cleanup();\r\n\t\treturn {\r\n\t\t\tsuccess: false,\r\n\t\t\tsupport: supportCodeLibrary\r\n\t\t};\r\n\t}\r\n\r\n\temitSupportCodeMessages({\r\n\t\teventBroadcaster,\r\n\t\tsupportCodeLibrary,\r\n\t\tnewId\r\n\t});\r\n\r\n\tconst runtime = await makeRuntime({\r\n\t\tenvironment,\r\n\t\tlogger,\r\n\t\teventBroadcaster,\r\n\t\tsourcedPickles: filteredPickles,\r\n\t\tnewId,\r\n\t\tsupportCodeLibrary,\r\n\t\toptions: options.runtime,\r\n\t\tcoordinates: options.sources\r\n\t});\r\n\tconst success = await runtime.run();\r\n\tawait pluginManager.cleanup();\r\n\tawait cleanupFormatters();\r\n\r\n\treturn {\r\n\t\tsuccess: success && !formatterStreamError,\r\n\t\tsupport: supportCodeLibrary\r\n\t};\r\n}\r\n"]}
1
+ {"version":3,"file":"run-cucumber.js","sourceRoot":"","sources":["../../src/api/run-cucumber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Envelope, IdGenerator, ParseError } from '@cucumber/messages';\r\nimport { EventEmitter } from 'events';\r\nimport { EventDataCollector } from '@cucumber/cucumber/lib/formatter/helpers/index';\r\nimport { emitMetaMessage, emitSupportCodeMessages } from '@cucumber/cucumber/lib/api/emit_support_code_messages';\r\nimport { IRunOptions, IRunResult } from '@cucumber/cucumber/lib/api/types';\r\nimport { resolvePaths } from '@cucumber/cucumber/lib/paths/index';\r\nimport { SupportCodeLibrary } from '@cucumber/cucumber/lib/support_code_library_builder/types';\r\nimport { makeRuntime } from '../runtime/make-runtime';\r\nimport { initializeFormatters } from '@cucumber/cucumber/lib/api/formatters';\r\nimport { getSupportCodeLibrary } from './support';\r\nimport { IRunEnvironment, makeEnvironment } from '@cucumber/cucumber/lib/environment/index';\r\nimport { getPicklesAndErrors } from '@cucumber/cucumber/lib/api/gherkin';\r\nimport MessageCollector from '../runtime/message-collector';\r\nimport { version } from '../version';\r\nimport { initializeForRunCucumber } from '@cucumber/cucumber/lib/api/plugins';\r\nimport { IFilterablePickle } from '@cucumber/cucumber/lib/filter/index';\r\nimport 'polyfill-symbol-metadata';\r\nimport { BindingRegistry } from '../bindings/binding-registry';\r\nimport { ITsFlowRunOptionsRuntime } from '../runtime/types';\r\nimport { Console } from 'console';\r\nimport ansis from 'ansis';\r\nimport { parallelPreload } from './parallel-loader';\r\nimport { createLogger } from '../utils/tsflow-logger';\r\n\r\nconst runLogger = createLogger('run-cucumber');\r\n\r\nexport interface ITsFlowRunOptions extends IRunOptions {\r\n\truntime: ITsFlowRunOptionsRuntime;\r\n}\r\n\r\n/**\r\n * Execute a Cucumber test run.\r\n *\r\n * Extended from cucumber.js so that we can use our own implementation\r\n * of makeRuntime\r\n *\r\n * @public\r\n * @param options - Configuration loaded from `loadConfiguration`.\r\n * @param environment - Project environment.\r\n * @param onMessage - Callback fired each time Cucumber emits a message.\r\n */\r\nexport async function runCucumber(\r\n\toptions: ITsFlowRunOptions,\r\n\tenvironment: IRunEnvironment = {},\r\n\tonMessage?: (message: Envelope) => void\r\n): Promise<IRunResult> {\r\n\tconst mergedEnvironment = makeEnvironment(environment);\r\n\tconst { cwd, stdout, stderr, env, logger } = mergedEnvironment;\r\n\r\n\tlogger.debug(`Running cucumber-tsflow ${version}\r\nWorking directory: ${cwd}\r\nRunning from: ${__dirname}\r\n`);\r\n\tconst consoleLogger = new Console(environment.stdout as any, environment.stderr);\r\n\tif (options.runtime.experimentalDecorators) {\r\n\t\tconsoleLogger.info(ansis.yellowBright('Using Experimental Decorators.'));\r\n\t}\r\n\tif (options.runtime.parallel > 0) {\r\n\t\tconsoleLogger.info(\r\n\t\t\tansis.cyanBright(`Running Cucumber-TsFlow in Parallel with ${options.runtime.parallel} worker(s).\\n`)\r\n\t\t);\r\n\t} else {\r\n\t\tconsoleLogger.info(ansis.cyanBright('Running Cucumber-TsFlow in Serial mode.\\n'));\r\n\t}\r\n\r\n\tconst newId = IdGenerator.uuid();\r\n\r\n\tconst supportCoordinates =\r\n\t\t'originalCoordinates' in options.support\r\n\t\t\t? options.support.originalCoordinates\r\n\t\t\t: Object.assign(\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trequireModules: [],\r\n\t\t\t\t\t\trequirePaths: [],\r\n\t\t\t\t\t\tloaders: [],\r\n\t\t\t\t\t\timportPaths: []\r\n\t\t\t\t\t},\r\n\t\t\t\t\toptions.support\r\n\t\t\t\t);\r\n\r\n\tconst pluginManager = await initializeForRunCucumber(\r\n\t\t{\r\n\t\t\t...options,\r\n\t\t\tsupport: supportCoordinates\r\n\t\t},\r\n\t\tmergedEnvironment\r\n\t);\r\n\r\n\tconst resolvedPaths = await resolvePaths(logger, cwd, options.sources, supportCoordinates);\r\n\tpluginManager.emit('paths:resolve', resolvedPaths);\r\n\tconst { sourcePaths, requirePaths, importPaths } = resolvedPaths;\r\n\r\n\t/**\r\n\t * The support code library contains all of the hook and step definitions.\r\n\t * These are loaded into the library when calling getSupportCodeLibrary,\r\n\t * which loads all of the step definitions using require or import.\r\n\t */\r\n\tlet supportCodeLibrary =\r\n\t\t'originalCoordinates' in options.support\r\n\t\t\t? (options.support as SupportCodeLibrary)\r\n\t\t\t: await (async () => {\r\n\t\t\t\t\t// Parallel preload phase: warm transpiler caches in worker threads\r\n\t\t\t\t\tif (options.runtime.parallelLoad) {\r\n\t\t\t\t\t\trunLogger.checkpoint('Running parallel preload phase');\r\n\t\t\t\t\t\tconsoleLogger.info(ansis.cyanBright('Pre-warming transpiler caches in parallel...\\n'));\r\n\t\t\t\t\t\ttry {\r\n\t\t\t\t\t\t\tconst result = await parallelPreload({\r\n\t\t\t\t\t\t\t\trequirePaths,\r\n\t\t\t\t\t\t\t\timportPaths,\r\n\t\t\t\t\t\t\t\trequireModules: supportCoordinates.requireModules,\r\n\t\t\t\t\t\t\t\tloaders: supportCoordinates.loaders,\r\n\t\t\t\t\t\t\t\texperimentalDecorators: options.runtime.experimentalDecorators,\r\n\t\t\t\t\t\t\t\tthreadCount: options.runtime.parallelLoad\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\trunLogger.checkpoint('Parallel preload completed', {\r\n\t\t\t\t\t\t\t\tdescriptors: result.descriptors.length,\r\n\t\t\t\t\t\t\t\tfiles: result.loadedFiles.length,\r\n\t\t\t\t\t\t\t\tdurationMs: result.durationMs\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\tconsoleLogger.info(\r\n\t\t\t\t\t\t\t\tansis.cyanBright(\r\n\t\t\t\t\t\t\t\t\t`Parallel preload completed in ${result.durationMs}ms ` +\r\n\t\t\t\t\t\t\t\t\t\t`(${result.loadedFiles.length} files, ${result.descriptors.length} bindings)\\n`\r\n\t\t\t\t\t\t\t\t)\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t} catch (err: any) {\r\n\t\t\t\t\t\t\trunLogger.error('Parallel preload failed, falling back to serial load', err);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn getSupportCodeLibrary({\r\n\t\t\t\t\t\tlogger,\r\n\t\t\t\t\t\tcwd,\r\n\t\t\t\t\t\tnewId,\r\n\t\t\t\t\t\trequirePaths,\r\n\t\t\t\t\t\trequireModules: supportCoordinates.requireModules,\r\n\t\t\t\t\t\timportPaths,\r\n\t\t\t\t\t\tloaders: supportCoordinates.loaders\r\n\t\t\t\t\t});\r\n\t\t\t\t})();\r\n\r\n\t// Set support to the updated step and hook definitions\r\n\t// in the supportCodeLibrary. We also need to initialize originalCoordinates\r\n\t// to support parallel execution.\r\n\tsupportCodeLibrary = BindingRegistry.instance.updateSupportCodeLibrary(supportCodeLibrary);\r\n\tsupportCodeLibrary = { ...supportCodeLibrary, ...{ originalCoordinates: supportCoordinates } };\r\n\toptions.support = supportCodeLibrary;\r\n\r\n\tconst eventBroadcaster = new EventEmitter();\r\n\tif (onMessage) {\r\n\t\teventBroadcaster.on('envelope', onMessage);\r\n\t}\r\n\teventBroadcaster.on('envelope', value => pluginManager.emit('message', value));\r\n\r\n\t// create a global instance of the message collector and bind it\r\n\t// to the event broadcaster. This is used by cucumber and for tests\r\n\t// that are not running in parallel.\r\n\tglobal.messageCollector = new MessageCollector(eventBroadcaster);\r\n\r\n\t// cast the MessageCollector to an EventDataCollector\r\n\tconst eventDataCollector = global.messageCollector as unknown as EventDataCollector;\r\n\r\n\tlet formatterStreamError = false;\r\n\tconst cleanupFormatters = await initializeFormatters({\r\n\t\tenv,\r\n\t\tcwd,\r\n\t\tstdout,\r\n\t\tstderr,\r\n\t\tlogger,\r\n\t\tonStreamError: () => (formatterStreamError = true),\r\n\t\teventBroadcaster,\r\n\t\teventDataCollector: eventDataCollector,\r\n\t\tconfiguration: options.formats,\r\n\t\tsupportCodeLibrary,\r\n\t\tpluginManager\r\n\t});\r\n\tawait emitMetaMessage(eventBroadcaster, env);\r\n\r\n\tlet filteredPickles: ReadonlyArray<IFilterablePickle> = [];\r\n\tlet parseErrors: ParseError[] = [];\r\n\tif (sourcePaths.length > 0) {\r\n\t\tconst gherkinResult = await getPicklesAndErrors({\r\n\t\t\tnewId,\r\n\t\t\tcwd,\r\n\t\t\tsourcePaths,\r\n\t\t\tcoordinates: options.sources,\r\n\t\t\tonEnvelope: envelope => eventBroadcaster.emit('envelope', envelope)\r\n\t\t});\r\n\t\tfilteredPickles = await pluginManager.transform('pickles:filter', gherkinResult.filterablePickles);\r\n\t\tfilteredPickles = await pluginManager.transform('pickles:order', filteredPickles);\r\n\t\tparseErrors = gherkinResult.parseErrors;\r\n\t}\r\n\tif (parseErrors.length) {\r\n\t\tparseErrors.forEach(parseError => {\r\n\t\t\tlogger.error(`Parse error in \"${parseError.source.uri}\" ${parseError.message}`);\r\n\t\t});\r\n\t\tawait cleanupFormatters();\r\n\t\tawait pluginManager.cleanup();\r\n\t\treturn {\r\n\t\t\tsuccess: false,\r\n\t\t\tsupport: supportCodeLibrary\r\n\t\t};\r\n\t}\r\n\r\n\temitSupportCodeMessages({\r\n\t\teventBroadcaster,\r\n\t\tsupportCodeLibrary,\r\n\t\tnewId\r\n\t});\r\n\r\n\tconst runtime = await makeRuntime({\r\n\t\tenvironment,\r\n\t\tlogger,\r\n\t\teventBroadcaster,\r\n\t\tsourcedPickles: filteredPickles,\r\n\t\tnewId,\r\n\t\tsupportCodeLibrary,\r\n\t\toptions: options.runtime,\r\n\t\tcoordinates: options.sources\r\n\t});\r\n\tconst success = await runtime.run();\r\n\tawait pluginManager.cleanup();\r\n\tawait cleanupFormatters();\r\n\r\n\treturn {\r\n\t\tsuccess: success && !formatterStreamError,\r\n\t\tsupport: supportCodeLibrary\r\n\t};\r\n}\r\n"]}
@@ -8,7 +8,10 @@ const node_module_1 = require("node:module");
8
8
  const node_url_1 = require("node:url");
9
9
  const index_1 = __importDefault(require("@cucumber/cucumber/lib/support_code_library_builder/index"));
10
10
  const try_require_1 = __importDefault(require("@cucumber/cucumber/lib/try_require"));
11
+ const binding_decorator_1 = require("../bindings/binding-decorator");
11
12
  async function getSupportCodeLibrary({ logger, cwd, newId, requireModules, requirePaths, importPaths, loaders }) {
13
+ // Clear the step pattern cache so decorators re-register with the fresh builder
14
+ (0, binding_decorator_1.resetStepPatternRegistrations)();
12
15
  index_1.default.reset(cwd, newId, {
13
16
  requireModules,
14
17
  requirePaths,
@@ -1 +1 @@
1
- {"version":3,"file":"support.js","sourceRoot":"","sources":["../../src/api/support.ts"],"names":[],"mappings":";;;;;AAQA,sDAmDC;AA3DD,6CAAuC;AACvC,uCAAyC;AAGzC,sGAAkG;AAClG,qFAA4D;AAGrD,KAAK,UAAU,qBAAqB,CAAC,EAC3C,MAAM,EACN,GAAG,EACH,KAAK,EACL,cAAc,EACd,YAAY,EACZ,WAAW,EACX,OAAO,EASP;IACA,eAAyB,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE;QAC3C,cAAc;QACd,YAAY;QACZ,WAAW;QACX,OAAO;KACP,CAAC,CAAC;IAEH,0DAA0D;IAC1D,eAAyB,CAAC,mBAAmB,CAAC;QAC7C,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,YAAY;QACpB,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;KAC/C,CAAC,CAAC;IAEH,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACzB,MAAM,CAAC,KAAK,CAAC,oCAAoC,IAAI,GAAG,CAAC,CAAC;QAC1D,IAAA,qBAAU,EAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACvB,MAAM,CAAC,KAAK,CAAC,oCAAoC,IAAI,GAAG,CAAC,CAAC;QAC1D,IAAA,qBAAU,EAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,KAAK,MAAM,SAAS,IAAI,OAAO,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,kCAAkC,SAAS,GAAG,CAAC,CAAC;QAC7D,IAAA,sBAAQ,EAAC,SAAS,EAAE,IAAA,wBAAa,EAAC,IAAI,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,mCAAmC,IAAI,GAAG,CAAC,CAAC;QACzD,MAAM,MAAM,CAAC,IAAA,wBAAa,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,eAAyB,CAAC,QAAQ,EAAE,CAAC;AAC7C,CAAC","sourcesContent":["import { register } from 'node:module';\r\nimport { pathToFileURL } from 'node:url';\r\nimport { IdGenerator } from '@cucumber/messages';\r\nimport { SupportCodeLibrary } from '@cucumber/cucumber/lib/support_code_library_builder/types';\r\nimport supportCodeLibraryBuilder from '@cucumber/cucumber/lib/support_code_library_builder/index';\r\nimport tryRequire from '@cucumber/cucumber/lib/try_require';\r\nimport { ILogger } from '@cucumber/cucumber/lib/environment/index';\r\n\r\nexport async function getSupportCodeLibrary({\r\n\tlogger,\r\n\tcwd,\r\n\tnewId,\r\n\trequireModules,\r\n\trequirePaths,\r\n\timportPaths,\r\n\tloaders\r\n}: {\r\n\tlogger: ILogger;\r\n\tcwd: string;\r\n\tnewId: IdGenerator.NewId;\r\n\trequireModules: string[];\r\n\trequirePaths: string[];\r\n\timportPaths: string[];\r\n\tloaders: string[];\r\n}): Promise<SupportCodeLibrary> {\r\n\tsupportCodeLibraryBuilder.reset(cwd, newId, {\r\n\t\trequireModules,\r\n\t\trequirePaths,\r\n\t\timportPaths,\r\n\t\tloaders\r\n\t});\r\n\r\n\t// Define the boolean type before loading any support code\r\n\tsupportCodeLibraryBuilder.defineParameterType({\r\n\t\tname: 'boolean',\r\n\t\tregexp: /true|false/,\r\n\t\ttransformer: s => (s === 'true' ? true : false)\r\n\t});\r\n\r\n\trequireModules.map(path => {\r\n\t\tlogger.debug(`Attempting to require code from \"${path}\"`);\r\n\t\ttryRequire(path);\r\n\t});\r\n\trequirePaths.map(path => {\r\n\t\tlogger.debug(`Attempting to require code from \"${path}\"`);\r\n\t\ttryRequire(path);\r\n\t});\r\n\r\n\tfor (const specifier of loaders) {\r\n\t\tlogger.debug(`Attempting to register loader \"${specifier}\"`);\r\n\t\tregister(specifier, pathToFileURL('./'));\r\n\t}\r\n\r\n\tfor (const path of importPaths) {\r\n\t\tlogger.debug(`Attempting to import code from \"${path}\"`);\r\n\t\tawait import(pathToFileURL(path).toString());\r\n\t}\r\n\r\n\treturn supportCodeLibraryBuilder.finalize();\r\n}\r\n"]}
1
+ {"version":3,"file":"support.js","sourceRoot":"","sources":["../../src/api/support.ts"],"names":[],"mappings":";;;;;AASA,sDAsDC;AA/DD,6CAAuC;AACvC,uCAAyC;AAGzC,sGAAkG;AAClG,qFAA4D;AAE5D,qEAA8E;AAEvE,KAAK,UAAU,qBAAqB,CAAC,EAC3C,MAAM,EACN,GAAG,EACH,KAAK,EACL,cAAc,EACd,YAAY,EACZ,WAAW,EACX,OAAO,EASP;IACA,gFAAgF;IAChF,IAAA,iDAA6B,GAAE,CAAC;IAEhC,eAAyB,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE;QAC3C,cAAc;QACd,YAAY;QACZ,WAAW;QACX,OAAO;KACP,CAAC,CAAC;IAEH,0DAA0D;IAC1D,eAAyB,CAAC,mBAAmB,CAAC;QAC7C,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,YAAY;QACpB,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;KAC/C,CAAC,CAAC;IAEH,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACzB,MAAM,CAAC,KAAK,CAAC,oCAAoC,IAAI,GAAG,CAAC,CAAC;QAC1D,IAAA,qBAAU,EAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACvB,MAAM,CAAC,KAAK,CAAC,oCAAoC,IAAI,GAAG,CAAC,CAAC;QAC1D,IAAA,qBAAU,EAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,KAAK,MAAM,SAAS,IAAI,OAAO,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,kCAAkC,SAAS,GAAG,CAAC,CAAC;QAC7D,IAAA,sBAAQ,EAAC,SAAS,EAAE,IAAA,wBAAa,EAAC,IAAI,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,mCAAmC,IAAI,GAAG,CAAC,CAAC;QACzD,MAAM,MAAM,CAAC,IAAA,wBAAa,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,eAAyB,CAAC,QAAQ,EAAE,CAAC;AAC7C,CAAC","sourcesContent":["import { register } from 'node:module';\r\nimport { pathToFileURL } from 'node:url';\r\nimport { IdGenerator } from '@cucumber/messages';\r\nimport { SupportCodeLibrary } from '@cucumber/cucumber/lib/support_code_library_builder/types';\r\nimport supportCodeLibraryBuilder from '@cucumber/cucumber/lib/support_code_library_builder/index';\r\nimport tryRequire from '@cucumber/cucumber/lib/try_require';\r\nimport { ILogger } from '@cucumber/cucumber/lib/environment/index';\r\nimport { resetStepPatternRegistrations } from '../bindings/binding-decorator';\r\n\r\nexport async function getSupportCodeLibrary({\r\n\tlogger,\r\n\tcwd,\r\n\tnewId,\r\n\trequireModules,\r\n\trequirePaths,\r\n\timportPaths,\r\n\tloaders\r\n}: {\r\n\tlogger: ILogger;\r\n\tcwd: string;\r\n\tnewId: IdGenerator.NewId;\r\n\trequireModules: string[];\r\n\trequirePaths: string[];\r\n\timportPaths: string[];\r\n\tloaders: string[];\r\n}): Promise<SupportCodeLibrary> {\r\n\t// Clear the step pattern cache so decorators re-register with the fresh builder\r\n\tresetStepPatternRegistrations();\r\n\r\n\tsupportCodeLibraryBuilder.reset(cwd, newId, {\r\n\t\trequireModules,\r\n\t\trequirePaths,\r\n\t\timportPaths,\r\n\t\tloaders\r\n\t});\r\n\r\n\t// Define the boolean type before loading any support code\r\n\tsupportCodeLibraryBuilder.defineParameterType({\r\n\t\tname: 'boolean',\r\n\t\tregexp: /true|false/,\r\n\t\ttransformer: s => (s === 'true' ? true : false)\r\n\t});\r\n\r\n\trequireModules.map(path => {\r\n\t\tlogger.debug(`Attempting to require code from \"${path}\"`);\r\n\t\ttryRequire(path);\r\n\t});\r\n\trequirePaths.map(path => {\r\n\t\tlogger.debug(`Attempting to require code from \"${path}\"`);\r\n\t\ttryRequire(path);\r\n\t});\r\n\r\n\tfor (const specifier of loaders) {\r\n\t\tlogger.debug(`Attempting to register loader \"${specifier}\"`);\r\n\t\tregister(specifier, pathToFileURL('./'));\r\n\t}\r\n\r\n\tfor (const path of importPaths) {\r\n\t\tlogger.debug(`Attempting to import code from \"${path}\"`);\r\n\t\tawait import(pathToFileURL(path).toString());\r\n\t}\r\n\r\n\treturn supportCodeLibraryBuilder.finalize();\r\n}\r\n"]}
@@ -3,5 +3,6 @@ import api from './index.js';
3
3
  export const convertConfiguration = api.convertConfiguration;
4
4
  export const loadConfiguration = api.loadConfiguration;
5
5
  export const loadSupport = api.loadSupport;
6
+ export const reloadSupport = api.reloadSupport;
6
7
  export const loadSources = api.loadSources;
7
8
  export const runCucumber = api.runCucumber;
@@ -1,4 +1,10 @@
1
1
  import { ContextType } from './types';
2
+ /**
3
+ * Clear the step pattern registration cache. Must be called whenever
4
+ * `supportCodeLibraryBuilder.reset()` is used so that decorators
5
+ * re-register definitions with the fresh builder instance.
6
+ */
7
+ export declare function resetStepPatternRegistrations(): void;
2
8
  /**
3
9
  * A class decorator that marks the associated class as a CucumberJS binding.
4
10
  *
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resetStepPatternRegistrations = resetStepPatternRegistrations;
3
4
  exports.binding = binding;
4
5
  const cucumber_1 = require("@cucumber/cucumber");
5
6
  const binding_context_1 = require("./binding-context");
@@ -14,6 +15,14 @@ const step_binding_1 = require("./step-binding");
14
15
  * the point of invocation.
15
16
  */
16
17
  const stepPatternRegistrations = new Map();
18
+ /**
19
+ * Clear the step pattern registration cache. Must be called whenever
20
+ * `supportCodeLibraryBuilder.reset()` is used so that decorators
21
+ * re-register definitions with the fresh builder instance.
22
+ */
23
+ function resetStepPatternRegistrations() {
24
+ stepPatternRegistrations.clear();
25
+ }
17
26
  /**
18
27
  * A class decorator that marks the associated class as a CucumberJS binding.
19
28
  *
@@ -82,6 +91,11 @@ function binding(requiredContextTypes) {
82
91
  * @returns
83
92
  */
84
93
  function addStepBinding(stepBinding) {
94
+ // In loader-worker threads, skip Cucumber registration — we only need
95
+ // the BindingRegistry populated for descriptor extraction.
96
+ if (global.__LOADER_WORKER) {
97
+ return;
98
+ }
85
99
  if (stepBinding.bindingType & step_binding_1.StepBindingFlags.StepDefinitions) {
86
100
  let stepBindingFlags = stepPatternRegistrations.get(stepBinding.stepPattern.toString());
87
101
  if (stepBindingFlags === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"binding-decorator.js","sourceRoot":"","sources":["../../src/bindings/binding-decorator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\r\n\tAfter,\r\n\tAfterStep,\r\n\tAfterAll,\r\n\tBefore,\r\n\tBeforeStep,\r\n\tBeforeAll,\r\n\tGiven,\r\n\tThen,\r\n\tWhen,\r\n\tWorld\r\n} from '@cucumber/cucumber';\r\nimport { getStepBindings, getStepBindingsExp, getCollectedBindings } from './binding-context';\r\nimport { BindingRegistry, DEFAULT_TAG } from './binding-registry';\r\nimport { StepBinding, StepBindingFlags } from './step-binding';\r\nimport { ContextType, StepPattern } from './types';\r\nimport { defineParameterType } from '../index';\r\nimport _ from 'underscore';\r\n\r\ninterface WritableWorld extends World {\r\n\t[key: string]: any;\r\n}\r\n\r\n/**\r\n * A set of step patterns that have been registered with Cucumber.\r\n *\r\n * In order to support scoped (or tagged) step definitions, we must ensure that any step binding is\r\n * only registered with Cucumber once. The binding function for that step pattern then becomes\r\n * responsible for looking up and execuing the step binding based on the context that is in scope at\r\n * the point of invocation.\r\n */\r\nconst stepPatternRegistrations = new Map<StepPattern, StepBindingFlags>();\r\n\r\n/**\r\n * A class decorator that marks the associated class as a CucumberJS binding.\r\n *\r\n * @param requiredContextTypes An optional array of Types that will be created and passed into the created\r\n * object for each scenario.\r\n *\r\n * An instance of the decorated class will be created for each scenario.\r\n */\r\nexport function binding(requiredContextTypes?: ContextType[]): any {\r\n\tif (global.experimentalDecorators) {\r\n\t\treturn <T>(target: { new (...args: any[]): T }) => {\r\n\t\t\tconst bindingRegistry = BindingRegistry.instance;\r\n\t\t\tbindingRegistry.registerContextTypesForClass(target.prototype, requiredContextTypes);\r\n\r\n\t\t\t// the class decorator is called last when decorators on a type are initialized. All other decorators\r\n\t\t\t// are added to DecoratorContext.metadata before this is called.\r\n\t\t\t// This will get all those bindings and then clear metadata for the next type that's loaded.\r\n\t\t\tconst allBindings: StepBinding[] = getStepBindingsExp();\r\n\t\t\tallBindings.forEach(stepBinding => {\r\n\t\t\t\t// For static methods, we need to set the classPrototype to the class itself, not the prototype\r\n\t\t\t\tif (stepBinding.stepIsStatic) {\r\n\t\t\t\t\tstepBinding.classPrototype = target;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tstepBinding.classPrototype = target.prototype;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbindingRegistry.registerStepBinding(stepBinding);\r\n\r\n\t\t\t\t// Register with cucumber\r\n\t\t\t\taddStepBinding(stepBinding);\r\n\t\t\t});\r\n\t\t};\r\n\t} else {\r\n\t\treturn function classDecorator(target: Function, context: ClassDecoratorContext) {\r\n\t\t\tconst bindingRegistry = BindingRegistry.instance;\r\n\t\t\tbindingRegistry.registerContextTypesForClass(target.prototype, requiredContextTypes);\r\n\r\n\t\t\t// the class decorator is called last when decorators on a type are initialized. All other decorators\r\n\t\t\t// are added to DecoratorContext.metadata before this is called.\r\n\t\t\t// This will get all those bindings and then clear metadata for the next type that's loaded.\r\n\t\t\tconst allBindings: StepBinding[] = getStepBindings(context);\r\n\t\t\tallBindings.forEach(stepBinding => {\r\n\t\t\t\t// Set the class prototype and then register the binding with the prototype\r\n\t\t\t\tstepBinding.classPrototype = target.prototype;\r\n\t\t\t\tbindingRegistry.registerStepBinding(stepBinding);\r\n\r\n\t\t\t\t// add the step binding to the binding registry\r\n\t\t\t\taddStepBinding(stepBinding);\r\n\t\t\t});\r\n\r\n\t\t\t// Process pending step bindings after class is decorated\r\n\t\t\tcontext.addInitializer(function () {\r\n\t\t\t\t// Get all the collected bindings\r\n\t\t\t\tconst allBindings = getCollectedBindings();\r\n\r\n\t\t\t\tallBindings.forEach(stepBinding => {\r\n\t\t\t\t\t// Set the class prototype and register\r\n\t\t\t\t\tstepBinding.classPrototype = target.prototype;\r\n\t\t\t\t\tbindingRegistry.registerStepBinding(stepBinding);\r\n\r\n\t\t\t\t\t// Register with cucumber - call the local addStepBinding function\r\n\t\t\t\t\taddStepBinding(stepBinding);\r\n\t\t\t\t});\r\n\t\t\t});\r\n\r\n\t\t\treturn target;\r\n\t\t};\r\n\t}\r\n}\r\n\r\n/**\r\n * Common helper used to add StepBindings to the binding registry\r\n * @param stepBinding\r\n * @returns\r\n */\r\nfunction addStepBinding(stepBinding: StepBinding): void {\r\n\tif (stepBinding.bindingType & StepBindingFlags.StepDefinitions) {\r\n\t\tlet stepBindingFlags = stepPatternRegistrations.get(stepBinding.stepPattern.toString());\r\n\t\tif (stepBindingFlags === undefined) {\r\n\t\t\tstepBindingFlags = StepBindingFlags.none;\r\n\t\t}\r\n\t\tif (stepBindingFlags & stepBinding.bindingType) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tbindStepDefinition(stepBinding);\r\n\t\tstepPatternRegistrations.set(stepBinding.stepPattern.toString(), stepBindingFlags | stepBinding.bindingType);\r\n\t} else if (stepBinding.bindingType & StepBindingFlags.Hooks) {\r\n\t\tbindHook(stepBinding);\r\n\t}\r\n}\r\n\r\n/**\r\n * Binds a step definition to Cucumber.\r\n *\r\n * @param stepBinding The [[StepBinding]] that represents a 'given', 'when', or 'then' step definition.\r\n */\r\nfunction bindStepDefinition(stepBinding: StepBinding): void {\r\n\tconst stepFunction = function (this: WritableWorld): any {\r\n\t\tconst bindingRegistry = BindingRegistry.instance;\r\n\r\n\t\tconst scenarioContext = global.messageCollector.getStepScenarioContext(stepBinding);\r\n\r\n\t\tif (scenarioContext) {\r\n\t\t\tconst matchingStepBindings = bindingRegistry.getStepBindings(\r\n\t\t\t\tstepBinding.stepPattern.toString(),\r\n\t\t\t\tscenarioContext.scenarioInfo.tags\r\n\t\t\t);\r\n\r\n\t\t\tif (matchingStepBindings.length > 1) {\r\n\t\t\t\tlet message = `Ambiguous step definitions for '${matchingStepBindings[0].stepPattern}':\\n`;\r\n\r\n\t\t\t\tmatchingStepBindings.forEach(matchingStepBinding => {\r\n\t\t\t\t\tmessage =\r\n\t\t\t\t\t\tmessage +\r\n\t\t\t\t\t\t`\\t\\t${String(matchingStepBinding.classPropertyKey)} (${matchingStepBinding.callsite.toString()})\\n`;\r\n\t\t\t\t});\r\n\r\n\t\t\t\tthrow new Error(message);\r\n\t\t\t} else if (matchingStepBindings.length === 0) {\r\n\t\t\t\tthrow new Error(\r\n\t\t\t\t\t`Cannot find matched step definition for ${stepBinding.stepPattern.toString()} with tag ${\r\n\t\t\t\t\t\tscenarioContext.scenarioInfo.tags\r\n\t\t\t\t\t} in binding registry`\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tconst contextTypes = bindingRegistry.getContextTypesForClass(matchingStepBindings[0].classPrototype);\r\n\t\t\tconst bindingObject = scenarioContext.getOrActivateBindingClass(\r\n\t\t\t\tmatchingStepBindings[0].classPrototype,\r\n\t\t\t\tcontextTypes,\r\n\t\t\t\tthis\r\n\t\t\t);\r\n\t\t\tbindingObject._worldObj = this;\r\n\r\n\t\t\treturn (bindingObject[matchingStepBindings[0].classPropertyKey] as Function).apply(\r\n\t\t\t\tbindingObject,\r\n\t\t\t\targuments as any\r\n\t\t\t);\r\n\t\t} else {\r\n\t\t\tthrow new Error('Unable to find the Scenario Context for a Step!');\r\n\t\t}\r\n\t};\r\n\r\n\tObject.defineProperty(stepFunction, 'length', {\r\n\t\tvalue: stepBinding.stepArgsLength\r\n\t});\r\n\r\n\t// initialize options used on all step bindings\r\n\tconst options = {\r\n\t\tcucumberKey: stepBinding.cucumberKey,\r\n\t\ttimeout: stepBinding.timeout,\r\n\t\twrapperOptions: stepBinding.wrapperOption\r\n\t};\r\n\t// call appropriate step\r\n\tif (stepBinding.bindingType & StepBindingFlags.given) {\r\n\t\tGiven(stepBinding.stepPattern, options, stepFunction);\r\n\t} else if (stepBinding.bindingType & StepBindingFlags.when) {\r\n\t\tWhen(stepBinding.stepPattern, options, stepFunction);\r\n\t} else if (stepBinding.bindingType & StepBindingFlags.then) {\r\n\t\tThen(stepBinding.stepPattern, options, stepFunction);\r\n\t}\r\n}\r\n\r\n/**\r\n * Binds a hook to Cucumber.\r\n *\r\n * @param stepBinding The [[StepBinding]] that represents a 'before', or 'after', step definition.\r\n */\r\nfunction bindHook(stepBinding: StepBinding): void {\r\n\tconst globalHookFunction = function (this: any): any {\r\n\t\t// Check if it's a static method\r\n\t\tif (stepBinding.stepIsStatic || !stepBinding.classPrototype[stepBinding.classPropertyKey]) {\r\n\t\t\tconst constructor = stepBinding.classPrototype.constructor;\r\n\r\n\t\t\tif (constructor && constructor[stepBinding.classPropertyKey]) {\r\n\t\t\t\treturn constructor[stepBinding.classPropertyKey].apply(constructor);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// For non-static methods\r\n\t\tif (stepBinding.classPrototype[stepBinding.classPropertyKey]) {\r\n\t\t\treturn stepBinding.classPrototype[stepBinding.classPropertyKey].apply(stepBinding.classPrototype);\r\n\t\t}\r\n\r\n\t\tthrow new Error(\r\n\t\t\t`Method ${String(stepBinding.classPropertyKey)} not found on class ${stepBinding.classPrototype?.constructor?.name}`\r\n\t\t);\r\n\t};\r\n\t// Main binding for all other hooks (before, after, beforeStep, afterStep)\r\n\tconst hookFunction = function (this: any, arg: any): any {\r\n\t\tconst scenarioContext = global.messageCollector.getHookScenarioContext(arg);\r\n\t\tif (scenarioContext) {\r\n\t\t\tconst contextTypes = BindingRegistry.instance.getContextTypesForClass(stepBinding.classPrototype);\r\n\t\t\tconst bindingObject = scenarioContext.getOrActivateBindingClass(stepBinding.classPrototype, contextTypes, this);\r\n\t\t\tbindingObject._worldObj = this;\r\n\t\t\treturn (bindingObject[stepBinding.classPropertyKey] as Function).apply(bindingObject, arguments as any);\r\n\t\t} else {\r\n\t\t\tthrow new Error('Unable to find the Scenario Context for Hook!');\r\n\t\t}\r\n\t};\r\n\t// length values need to be added to our binding functions.\r\n\t// These are used in cucumber to determine if the function is\r\n\t// a callback or promise.\r\n\tObject.defineProperty(globalHookFunction, 'length', {\r\n\t\tvalue: stepBinding.stepArgsLength\r\n\t});\r\n\tObject.defineProperty(hookFunction, 'length', {\r\n\t\tvalue: stepBinding.stepArgsLength\r\n\t});\r\n\r\n\tconst tags = stepBinding.tags === DEFAULT_TAG ? undefined : stepBinding.tags;\r\n\r\n\t// This binds the appropriate function above to the associated\r\n\t// cucumber step functions.\r\n\tswitch (stepBinding.bindingType) {\r\n\t\tcase StepBindingFlags.beforeAll: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, timeout: stepBinding.timeout };\r\n\t\t\tBeforeAll(options, globalHookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.before: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, tags: tags, timeout: stepBinding.timeout };\r\n\t\t\tBefore(options, hookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.beforeStep: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, tags: tags, timeout: stepBinding.timeout };\r\n\t\t\tBeforeStep(options, hookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.afterAll: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, timeout: stepBinding.timeout };\r\n\t\t\tAfterAll(options, globalHookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.after: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, tags: tags, timeout: stepBinding.timeout };\r\n\t\t\tAfter(options, hookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.afterStep: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, tags: tags, timeout: stepBinding.timeout };\r\n\t\t\tAfterStep(options, hookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n"]}
1
+ {"version":3,"file":"binding-decorator.js","sourceRoot":"","sources":["../../src/bindings/binding-decorator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\r\n\tAfter,\r\n\tAfterStep,\r\n\tAfterAll,\r\n\tBefore,\r\n\tBeforeStep,\r\n\tBeforeAll,\r\n\tGiven,\r\n\tThen,\r\n\tWhen,\r\n\tWorld\r\n} from '@cucumber/cucumber';\r\nimport { getStepBindings, getStepBindingsExp, getCollectedBindings } from './binding-context';\r\nimport { BindingRegistry, DEFAULT_TAG } from './binding-registry';\r\nimport { StepBinding, StepBindingFlags } from './step-binding';\r\nimport { ContextType, StepPattern } from './types';\r\n\r\ninterface WritableWorld extends World {\r\n\t[key: string]: any;\r\n}\r\n\r\n/**\r\n * A set of step patterns that have been registered with Cucumber.\r\n *\r\n * In order to support scoped (or tagged) step definitions, we must ensure that any step binding is\r\n * only registered with Cucumber once. The binding function for that step pattern then becomes\r\n * responsible for looking up and execuing the step binding based on the context that is in scope at\r\n * the point of invocation.\r\n */\r\nconst stepPatternRegistrations = new Map<StepPattern, StepBindingFlags>();\r\n\r\n/**\r\n * Clear the step pattern registration cache. Must be called whenever\r\n * `supportCodeLibraryBuilder.reset()` is used so that decorators\r\n * re-register definitions with the fresh builder instance.\r\n */\r\nexport function resetStepPatternRegistrations(): void {\r\n\tstepPatternRegistrations.clear();\r\n}\r\n\r\n/**\r\n * A class decorator that marks the associated class as a CucumberJS binding.\r\n *\r\n * @param requiredContextTypes An optional array of Types that will be created and passed into the created\r\n * object for each scenario.\r\n *\r\n * An instance of the decorated class will be created for each scenario.\r\n */\r\nexport function binding(requiredContextTypes?: ContextType[]): any {\r\n\tif (global.experimentalDecorators) {\r\n\t\treturn <T>(target: { new (...args: any[]): T }) => {\r\n\t\t\tconst bindingRegistry = BindingRegistry.instance;\r\n\t\t\tbindingRegistry.registerContextTypesForClass(target.prototype, requiredContextTypes);\r\n\r\n\t\t\t// the class decorator is called last when decorators on a type are initialized. All other decorators\r\n\t\t\t// are added to DecoratorContext.metadata before this is called.\r\n\t\t\t// This will get all those bindings and then clear metadata for the next type that's loaded.\r\n\t\t\tconst allBindings: StepBinding[] = getStepBindingsExp();\r\n\t\t\tallBindings.forEach(stepBinding => {\r\n\t\t\t\t// For static methods, we need to set the classPrototype to the class itself, not the prototype\r\n\t\t\t\tif (stepBinding.stepIsStatic) {\r\n\t\t\t\t\tstepBinding.classPrototype = target;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tstepBinding.classPrototype = target.prototype;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbindingRegistry.registerStepBinding(stepBinding);\r\n\r\n\t\t\t\t// Register with cucumber\r\n\t\t\t\taddStepBinding(stepBinding);\r\n\t\t\t});\r\n\t\t};\r\n\t} else {\r\n\t\treturn function classDecorator(target: Function, context: ClassDecoratorContext) {\r\n\t\t\tconst bindingRegistry = BindingRegistry.instance;\r\n\t\t\tbindingRegistry.registerContextTypesForClass(target.prototype, requiredContextTypes);\r\n\r\n\t\t\t// the class decorator is called last when decorators on a type are initialized. All other decorators\r\n\t\t\t// are added to DecoratorContext.metadata before this is called.\r\n\t\t\t// This will get all those bindings and then clear metadata for the next type that's loaded.\r\n\t\t\tconst allBindings: StepBinding[] = getStepBindings(context);\r\n\t\t\tallBindings.forEach(stepBinding => {\r\n\t\t\t\t// Set the class prototype and then register the binding with the prototype\r\n\t\t\t\tstepBinding.classPrototype = target.prototype;\r\n\t\t\t\tbindingRegistry.registerStepBinding(stepBinding);\r\n\r\n\t\t\t\t// add the step binding to the binding registry\r\n\t\t\t\taddStepBinding(stepBinding);\r\n\t\t\t});\r\n\r\n\t\t\t// Process pending step bindings after class is decorated\r\n\t\t\tcontext.addInitializer(function () {\r\n\t\t\t\t// Get all the collected bindings\r\n\t\t\t\tconst allBindings = getCollectedBindings();\r\n\r\n\t\t\t\tallBindings.forEach(stepBinding => {\r\n\t\t\t\t\t// Set the class prototype and register\r\n\t\t\t\t\tstepBinding.classPrototype = target.prototype;\r\n\t\t\t\t\tbindingRegistry.registerStepBinding(stepBinding);\r\n\r\n\t\t\t\t\t// Register with cucumber - call the local addStepBinding function\r\n\t\t\t\t\taddStepBinding(stepBinding);\r\n\t\t\t\t});\r\n\t\t\t});\r\n\r\n\t\t\treturn target;\r\n\t\t};\r\n\t}\r\n}\r\n\r\n/**\r\n * Common helper used to add StepBindings to the binding registry\r\n * @param stepBinding\r\n * @returns\r\n */\r\nfunction addStepBinding(stepBinding: StepBinding): void {\r\n\t// In loader-worker threads, skip Cucumber registration — we only need\r\n\t// the BindingRegistry populated for descriptor extraction.\r\n\tif (global.__LOADER_WORKER) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (stepBinding.bindingType & StepBindingFlags.StepDefinitions) {\r\n\t\tlet stepBindingFlags = stepPatternRegistrations.get(stepBinding.stepPattern.toString());\r\n\t\tif (stepBindingFlags === undefined) {\r\n\t\t\tstepBindingFlags = StepBindingFlags.none;\r\n\t\t}\r\n\t\tif (stepBindingFlags & stepBinding.bindingType) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tbindStepDefinition(stepBinding);\r\n\t\tstepPatternRegistrations.set(stepBinding.stepPattern.toString(), stepBindingFlags | stepBinding.bindingType);\r\n\t} else if (stepBinding.bindingType & StepBindingFlags.Hooks) {\r\n\t\tbindHook(stepBinding);\r\n\t}\r\n}\r\n\r\n/**\r\n * Binds a step definition to Cucumber.\r\n *\r\n * @param stepBinding The [[StepBinding]] that represents a 'given', 'when', or 'then' step definition.\r\n */\r\nfunction bindStepDefinition(stepBinding: StepBinding): void {\r\n\tconst stepFunction = function (this: WritableWorld): any {\r\n\t\tconst bindingRegistry = BindingRegistry.instance;\r\n\r\n\t\tconst scenarioContext = global.messageCollector.getStepScenarioContext(stepBinding);\r\n\r\n\t\tif (scenarioContext) {\r\n\t\t\tconst matchingStepBindings = bindingRegistry.getStepBindings(\r\n\t\t\t\tstepBinding.stepPattern.toString(),\r\n\t\t\t\tscenarioContext.scenarioInfo.tags\r\n\t\t\t);\r\n\r\n\t\t\tif (matchingStepBindings.length > 1) {\r\n\t\t\t\tlet message = `Ambiguous step definitions for '${matchingStepBindings[0].stepPattern}':\\n`;\r\n\r\n\t\t\t\tmatchingStepBindings.forEach(matchingStepBinding => {\r\n\t\t\t\t\tmessage =\r\n\t\t\t\t\t\tmessage +\r\n\t\t\t\t\t\t`\\t\\t${String(matchingStepBinding.classPropertyKey)} (${matchingStepBinding.callsite.toString()})\\n`;\r\n\t\t\t\t});\r\n\r\n\t\t\t\tthrow new Error(message);\r\n\t\t\t} else if (matchingStepBindings.length === 0) {\r\n\t\t\t\tthrow new Error(\r\n\t\t\t\t\t`Cannot find matched step definition for ${stepBinding.stepPattern.toString()} with tag ${\r\n\t\t\t\t\t\tscenarioContext.scenarioInfo.tags\r\n\t\t\t\t\t} in binding registry`\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tconst contextTypes = bindingRegistry.getContextTypesForClass(matchingStepBindings[0].classPrototype);\r\n\t\t\tconst bindingObject = scenarioContext.getOrActivateBindingClass(\r\n\t\t\t\tmatchingStepBindings[0].classPrototype,\r\n\t\t\t\tcontextTypes,\r\n\t\t\t\tthis\r\n\t\t\t);\r\n\t\t\tbindingObject._worldObj = this;\r\n\r\n\t\t\treturn (bindingObject[matchingStepBindings[0].classPropertyKey] as Function).apply(\r\n\t\t\t\tbindingObject,\r\n\t\t\t\targuments as any\r\n\t\t\t);\r\n\t\t} else {\r\n\t\t\tthrow new Error('Unable to find the Scenario Context for a Step!');\r\n\t\t}\r\n\t};\r\n\r\n\tObject.defineProperty(stepFunction, 'length', {\r\n\t\tvalue: stepBinding.stepArgsLength\r\n\t});\r\n\r\n\t// initialize options used on all step bindings\r\n\tconst options = {\r\n\t\tcucumberKey: stepBinding.cucumberKey,\r\n\t\ttimeout: stepBinding.timeout,\r\n\t\twrapperOptions: stepBinding.wrapperOption\r\n\t};\r\n\t// call appropriate step\r\n\tif (stepBinding.bindingType & StepBindingFlags.given) {\r\n\t\tGiven(stepBinding.stepPattern, options, stepFunction);\r\n\t} else if (stepBinding.bindingType & StepBindingFlags.when) {\r\n\t\tWhen(stepBinding.stepPattern, options, stepFunction);\r\n\t} else if (stepBinding.bindingType & StepBindingFlags.then) {\r\n\t\tThen(stepBinding.stepPattern, options, stepFunction);\r\n\t}\r\n}\r\n\r\n/**\r\n * Binds a hook to Cucumber.\r\n *\r\n * @param stepBinding The [[StepBinding]] that represents a 'before', or 'after', step definition.\r\n */\r\nfunction bindHook(stepBinding: StepBinding): void {\r\n\tconst globalHookFunction = function (this: any): any {\r\n\t\t// Check if it's a static method\r\n\t\tif (stepBinding.stepIsStatic || !stepBinding.classPrototype[stepBinding.classPropertyKey]) {\r\n\t\t\tconst constructor = stepBinding.classPrototype.constructor;\r\n\r\n\t\t\tif (constructor && constructor[stepBinding.classPropertyKey]) {\r\n\t\t\t\treturn constructor[stepBinding.classPropertyKey].apply(constructor);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// For non-static methods\r\n\t\tif (stepBinding.classPrototype[stepBinding.classPropertyKey]) {\r\n\t\t\treturn stepBinding.classPrototype[stepBinding.classPropertyKey].apply(stepBinding.classPrototype);\r\n\t\t}\r\n\r\n\t\tthrow new Error(\r\n\t\t\t`Method ${String(stepBinding.classPropertyKey)} not found on class ${stepBinding.classPrototype?.constructor?.name}`\r\n\t\t);\r\n\t};\r\n\t// Main binding for all other hooks (before, after, beforeStep, afterStep)\r\n\tconst hookFunction = function (this: any, arg: any): any {\r\n\t\tconst scenarioContext = global.messageCollector.getHookScenarioContext(arg);\r\n\t\tif (scenarioContext) {\r\n\t\t\tconst contextTypes = BindingRegistry.instance.getContextTypesForClass(stepBinding.classPrototype);\r\n\t\t\tconst bindingObject = scenarioContext.getOrActivateBindingClass(stepBinding.classPrototype, contextTypes, this);\r\n\t\t\tbindingObject._worldObj = this;\r\n\t\t\treturn (bindingObject[stepBinding.classPropertyKey] as Function).apply(bindingObject, arguments as any);\r\n\t\t} else {\r\n\t\t\tthrow new Error('Unable to find the Scenario Context for Hook!');\r\n\t\t}\r\n\t};\r\n\t// length values need to be added to our binding functions.\r\n\t// These are used in cucumber to determine if the function is\r\n\t// a callback or promise.\r\n\tObject.defineProperty(globalHookFunction, 'length', {\r\n\t\tvalue: stepBinding.stepArgsLength\r\n\t});\r\n\tObject.defineProperty(hookFunction, 'length', {\r\n\t\tvalue: stepBinding.stepArgsLength\r\n\t});\r\n\r\n\tconst tags = stepBinding.tags === DEFAULT_TAG ? undefined : stepBinding.tags;\r\n\r\n\t// This binds the appropriate function above to the associated\r\n\t// cucumber step functions.\r\n\tswitch (stepBinding.bindingType) {\r\n\t\tcase StepBindingFlags.beforeAll: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, timeout: stepBinding.timeout };\r\n\t\t\tBeforeAll(options, globalHookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.before: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, tags: tags, timeout: stepBinding.timeout };\r\n\t\t\tBefore(options, hookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.beforeStep: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, tags: tags, timeout: stepBinding.timeout };\r\n\t\t\tBeforeStep(options, hookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.afterAll: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, timeout: stepBinding.timeout };\r\n\t\t\tAfterAll(options, globalHookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.after: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, tags: tags, timeout: stepBinding.timeout };\r\n\t\t\tAfter(options, hookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase StepBindingFlags.afterStep: {\r\n\t\t\tconst options = { cucumberKey: stepBinding.cucumberKey, tags: tags, timeout: stepBinding.timeout };\r\n\t\t\tAfterStep(options, hookFunction);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n"]}
@@ -1,5 +1,5 @@
1
1
  import { SupportCodeLibrary } from '@cucumber/cucumber/lib/support_code_library_builder/types';
2
- import { StepBinding } from './step-binding';
2
+ import { StepBinding, SerializableBindingDescriptor } from './step-binding';
3
3
  import { ContextType, StepPattern, TagName } from './types';
4
4
  /**
5
5
  * Represents the default step pattern.
@@ -15,6 +15,7 @@ export declare const DEFAULT_TAG = "*";
15
15
  export declare class BindingRegistry {
16
16
  private _stepBindings;
17
17
  private _classBindings;
18
+ private _cucumberKeyIndex;
18
19
  /**
19
20
  * Gets the binding registry singleton.
20
21
  *
@@ -71,6 +72,35 @@ export declare class BindingRegistry {
71
72
  * @returns
72
73
  */
73
74
  updateSupportCodeLibrary: (library: SupportCodeLibrary) => SupportCodeLibrary;
75
+ /**
76
+ * Export all registered step bindings as structured-clone-safe descriptors.
77
+ * Used by loader-workers to send binding metadata back to the main thread.
78
+ *
79
+ * @returns An array of [[SerializableBindingDescriptor]].
80
+ */
81
+ toDescriptors(): SerializableBindingDescriptor[];
82
+ /**
83
+ * Remove all step bindings that originated from a given source file.
84
+ * This supports delta-aware reload — bindings from changed files are purged
85
+ * before re-loading so stale entries don't accumulate.
86
+ *
87
+ * @param filename Absolute path to the source file whose bindings should be removed.
88
+ */
89
+ removeBindingsForFile(filename: string): void;
90
+ /**
91
+ * Check whether a binding with the given cucumberKey is already registered.
92
+ *
93
+ * @param cucumberKey The unique key to check.
94
+ * @returns true if a binding with that key exists.
95
+ */
96
+ hasBindingForKey(cucumberKey: string): boolean;
97
+ /**
98
+ * Collect the unique set of source filenames from all registered bindings.
99
+ * Useful for comparing what was loaded in a worker versus what exists on the main thread.
100
+ *
101
+ * @returns A Set of absolute file paths.
102
+ */
103
+ getDescriptorSourceFiles(): Set<string>;
74
104
  /**
75
105
  * Maps an array of tag names to an array of associated step bindings.
76
106
  *