@rushstack/rundown 1.1.10 → 1.1.11

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.
package/LICENSE CHANGED
@@ -1,24 +1,24 @@
1
- @rushstack/rundown
2
-
3
- Copyright (c) Microsoft Corporation. All rights reserved.
4
-
5
- MIT License
6
-
7
- Permission is hereby granted, free of charge, to any person obtaining
8
- a copy of this software and associated documentation files (the
9
- "Software"), to deal in the Software without restriction, including
10
- without limitation the rights to use, copy, modify, merge, publish,
11
- distribute, sublicense, and/or sell copies of the Software, and to
12
- permit persons to whom the Software is furnished to do so, subject to
13
- the following conditions:
14
-
15
- The above copyright notice and this permission notice shall be
16
- included in all copies or substantial portions of the Software.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ @rushstack/rundown
2
+
3
+ Copyright (c) Microsoft Corporation. All rights reserved.
4
+
5
+ MIT License
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining
8
+ a copy of this software and associated documentation files (the
9
+ "Software"), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,230 +1,230 @@
1
- # @rushstack/rundown
2
-
3
- Slow startup times for Node.js commands or services? **Rundown** can invoke a Node.js process and:
4
-
5
- 1. **View imported files:** Intercept all `require()` calls and show which paths were loaded.
6
- 2. **Find culprits:** Show the chain for `require()` calls for each import, explaining why it was imported.
7
- 3. **Detect regressions over time:** Generate a concise "snapshot" report that can be committed to Git. Changes
8
- to this file may indicate potential performance regressions.
9
-
10
-
11
- ## Installation
12
-
13
- You can install this tool globally:
14
-
15
- ```shell
16
- $ npm install --global @rushstack/rundown
17
-
18
- # View command line help
19
- $ rundown --help
20
- ```
21
-
22
- If you will generate rundown snapshots during your build, it is recommended to install via `devDependencies`:
23
-
24
- ```shell
25
- $ cd my-tool
26
- $ npm install @rushstack/rundown --save-dev
27
- ```
28
-
29
-
30
- ## Viewing imported files
31
-
32
- Suppose you maintain a small NPM project that is invoked as follows:
33
-
34
- ```shell
35
- # The folder where your tool is developed
36
- $ cd my-tool
37
-
38
- # When you invoke "my-tool --my-option 123 --verbose" from the shell, let's suppose that it invokes
39
- # this Node.js command:
40
- $ node lib/start.js --my-option 123 --verbose
41
- ```
42
-
43
- And suppose that your tool's startup time is rather slow, because the code calls `require()` to load many different
44
- NPM packages. We can create a report to see all the imports:
45
-
46
- ```shell
47
- # We use "--args" to pass the command-line arguments for "my-tool"
48
- $ rundown inspect --script lib/start.js --args="--my-option 123 --verbose"
49
- ```
50
-
51
- The report may look like this:
52
-
53
- **rundown-inspect.log**
54
- ```
55
- /path/to/my-tool/lib/start.js
56
- /path/to/my-tool/node_modules/at-least-node/index.js
57
- /path/to/my-tool/node_modules/fs-extra/lib/copy-sync/copy-sync.js
58
- /path/to/my-tool/node_modules/fs-extra/lib/copy-sync/index.js
59
- /path/to/my-tool/node_modules/fs-extra/lib/copy/copy.js
60
- /path/to/my-tool/node_modules/fs-extra/lib/copy/index.js
61
- /path/to/my-tool/node_modules/fs-extra/lib/empty/index.js
62
- /path/to/my-tool/node_modules/fs-extra/lib/ensure/file.js
63
- /path/to/my-tool/node_modules/fs-extra/lib/ensure/index.js
64
- /path/to/my-tool/node_modules/fs-extra/lib/ensure/link.js
65
- /path/to/my-tool/node_modules/fs-extra/lib/ensure/symlink-paths.js
66
- /path/to/my-tool/node_modules/fs-extra/lib/ensure/symlink-type.js
67
- /path/to/my-tool/node_modules/fs-extra/lib/ensure/symlink.js
68
- /path/to/my-tool/node_modules/fs-extra/lib/fs/index.js
69
- /path/to/my-tool/node_modules/fs-extra/lib/index.js
70
- /path/to/my-tool/node_modules/fs-extra/lib/json/jsonfile.js
71
- /path/to/my-tool/node_modules/fs-extra/lib/json/output-json-sync.js
72
- /path/to/my-tool/node_modules/fs-extra/lib/json/output-json.js
73
- /path/to/my-tool/node_modules/fs-extra/lib/mkdirs/index.js
74
- /path/to/my-tool/node_modules/fs-extra/lib/mkdirs/make-dir.js
75
- /path/to/my-tool/node_modules/fs-extra/lib/move-sync/index.js
76
- /path/to/my-tool/node_modules/fs-extra/lib/move-sync/move-sync.js
77
- /path/to/my-tool/node_modules/fs-extra/lib/move/index.js
78
- /path/to/my-tool/node_modules/fs-extra/lib/move/move.js
79
- /path/to/my-tool/node_modules/fs-extra/lib/output/index.js
80
- /path/to/my-tool/node_modules/fs-extra/lib/path-exists/index.js
81
- /path/to/my-tool/node_modules/fs-extra/lib/remove/index.js
82
- /path/to/my-tool/node_modules/fs-extra/lib/remove/rimraf.js
83
- /path/to/my-tool/node_modules/fs-extra/lib/util/stat.js
84
- /path/to/my-tool/node_modules/fs-extra/lib/util/utimes.js
85
- /path/to/my-tool/node_modules/graceful-fs/clone.js
86
- /path/to/my-tool/node_modules/graceful-fs/graceful-fs.js
87
- /path/to/my-tool/node_modules/graceful-fs/legacy-streams.js
88
- /path/to/my-tool/node_modules/graceful-fs/polyfills.js
89
- /path/to/my-tool/node_modules/jsonfile/index.js
90
- /path/to/my-tool/node_modules/jsonfile/utils.js
91
- /path/to/my-tool/node_modules/universalify/index.js
92
- ```
93
-
94
- ## Finding callers
95
-
96
- To see how each file is imported, you can add the `--trace-imports` switch.
97
- ```shell
98
- # We use "--args" to pass the command-line arguments for "my-tool"
99
- $ rundown inspect --script lib/start.js --args="--my-option 123 --verbose" --trace-imports
100
- ```
101
-
102
- The report now shows more detail:
103
-
104
- **rundown-inspect.log**
105
- ```
106
- . . .
107
- /path/to/my-tool/node_modules/graceful-fs/legacy-streams.js
108
- imported by /path/to/my-tool/node_modules/graceful-fs/graceful-fs.js
109
- imported by /path/to/my-tool/node_modules/fs-extra/lib/fs/index.js
110
- imported by /path/to/my-tool/node_modules/fs-extra/lib/index.js
111
- imported by /path/to/my-tool/lib/start.js
112
- imported by /rundown/lib/launcher.js
113
-
114
- /path/to/my-tool/node_modules/graceful-fs/polyfills.js
115
- imported by /path/to/my-tool/node_modules/graceful-fs/graceful-fs.js
116
- imported by /path/to/my-tool/node_modules/fs-extra/lib/fs/index.js
117
- imported by /path/to/my-tool/node_modules/fs-extra/lib/index.js
118
- imported by /path/to/my-tool/lib/start.js
119
- imported by rundown/lib/launcher.js
120
- . . .
121
- ```
122
-
123
- ## Fixing problems
124
-
125
- It may be the case that many of these imports are not actually used. You can avoid preloading them
126
- by converting them to lazy imports using the `Import.lazy()` from
127
- [@rushstack/node-core-library](https://www.npmjs.com/package/@rushstack/node-core-library)
128
- or [import-lazy](https://www.npmjs.com/package/import-lazy).
129
-
130
-
131
- ## Generating a snapshot
132
-
133
- To detect future regressions, use the `rundown snapshot` command to write a snapshot file:
134
-
135
- ```shell
136
- # We use "--args" to pass the command-line arguments for "my-tool"
137
- $ rundown snapshot --script lib/start.js --args="--my-option 123 --verbose"
138
-
139
- # This file can be committed to Git to track regressions
140
- $ git add rundown-snapshot.log
141
- ```
142
-
143
- The snapshot file format eliminates spurious diffs, by showing only the names of the imported packages.
144
- For local projects in a monorepo, it will show relative paths. Example output:
145
-
146
- **rundown-snapshot.log**
147
- ```
148
- ../path/to/monorepo-sibling
149
- at-least-node
150
- fs-extra
151
- graceful-fs
152
- jsonfile
153
- universalify
154
- ```
155
-
156
- ## Command-line reference
157
-
158
- ```
159
- usage: rundown [-h] <command> ...
160
-
161
- Detect load time regressions by running an app, tracing require() calls, and
162
- generating a deterministic report
163
-
164
- Positional arguments:
165
- <command>
166
- snapshot Invoke a Node.js script and generate a test snapshot
167
- inspect Invoke a Node.js script and generate detailed diagnostic output
168
-
169
- Optional arguments:
170
- -h, --help Show this help message and exit.
171
-
172
- For detailed help about a specific command, use: rundown <command> -h
173
- ```
174
-
175
- ```
176
- usage: rundown snapshot [-h] -s PATH [-a STRING] [-q] [-i]
177
-
178
- Invoke a Node.js script and generate a test snapshot. This command creates a
179
- concise report that can be added to Git, so that its diff can be used to
180
- detect performance regressions
181
-
182
- Optional arguments:
183
- -h, --help Show this help message and exit.
184
- -s PATH, --script PATH
185
- The path to a .js file that will be the entry point
186
- for the target Node.js process
187
- -a STRING, --args STRING
188
- Specifies command-line arguments to be passed to the
189
- target Node.js process. The value should be a single
190
- text string delimited by spaces. Example: rundown
191
- inspect --scripts ./example.js --args="--flag
192
- --option=123"
193
- -q, --quiet Suppress STDOUT/STDERR for the target Node.js process
194
- -i, --ignore-exit-code
195
- Do not report an error if the target Node.js process
196
- returns a nonzero exit code
197
- ```
198
-
199
- ```
200
- usage: rundown inspect [-h] -s PATH [-a STRING] [-q] [-i] [-t]
201
-
202
- Invoke a Node.js script and generate detailed diagnostic output. This command
203
- is used to inspect performance regressions.
204
-
205
- Optional arguments:
206
- -h, --help Show this help message and exit.
207
- -s PATH, --script PATH
208
- The path to a .js file that will be the entry point
209
- for the target Node.js process
210
- -a STRING, --args STRING
211
- Specifies command-line arguments to be passed to the
212
- target Node.js process. The value should be a single
213
- text string delimited by spaces. Example: rundown
214
- inspect --scripts ./example.js --args="--flag
215
- --option=123"
216
- -q, --quiet Suppress STDOUT/STDERR for the target Node.js process
217
- -i, --ignore-exit-code
218
- Do not report an error if the target Node.js process
219
- returns a nonzero exit code
220
- -t, --trace-imports Reports the call chain for each module path, showing
221
- how it was imported
222
- ```
223
-
224
- ## Links
225
-
226
- - [CHANGELOG.md](
227
- https://github.com/microsoft/rushstack/blob/main/apps/rundown/CHANGELOG.md) - Find
228
- out what's new in the latest version
229
-
230
- Rundown is part of the [Rush Stack](https://rushstack.io/) family of projects.
1
+ # @rushstack/rundown
2
+
3
+ Slow startup times for Node.js commands or services? **Rundown** can invoke a Node.js process and:
4
+
5
+ 1. **View imported files:** Intercept all `require()` calls and show which paths were loaded.
6
+ 2. **Find culprits:** Show the chain for `require()` calls for each import, explaining why it was imported.
7
+ 3. **Detect regressions over time:** Generate a concise "snapshot" report that can be committed to Git. Changes
8
+ to this file may indicate potential performance regressions.
9
+
10
+
11
+ ## Installation
12
+
13
+ You can install this tool globally:
14
+
15
+ ```shell
16
+ $ npm install --global @rushstack/rundown
17
+
18
+ # View command line help
19
+ $ rundown --help
20
+ ```
21
+
22
+ If you will generate rundown snapshots during your build, it is recommended to install via `devDependencies`:
23
+
24
+ ```shell
25
+ $ cd my-tool
26
+ $ npm install @rushstack/rundown --save-dev
27
+ ```
28
+
29
+
30
+ ## Viewing imported files
31
+
32
+ Suppose you maintain a small NPM project that is invoked as follows:
33
+
34
+ ```shell
35
+ # The folder where your tool is developed
36
+ $ cd my-tool
37
+
38
+ # When you invoke "my-tool --my-option 123 --verbose" from the shell, let's suppose that it invokes
39
+ # this Node.js command:
40
+ $ node lib/start.js --my-option 123 --verbose
41
+ ```
42
+
43
+ And suppose that your tool's startup time is rather slow, because the code calls `require()` to load many different
44
+ NPM packages. We can create a report to see all the imports:
45
+
46
+ ```shell
47
+ # We use "--args" to pass the command-line arguments for "my-tool"
48
+ $ rundown inspect --script lib/start.js --args="--my-option 123 --verbose"
49
+ ```
50
+
51
+ The report may look like this:
52
+
53
+ **rundown-inspect.log**
54
+ ```
55
+ /path/to/my-tool/lib/start.js
56
+ /path/to/my-tool/node_modules/at-least-node/index.js
57
+ /path/to/my-tool/node_modules/fs-extra/lib/copy-sync/copy-sync.js
58
+ /path/to/my-tool/node_modules/fs-extra/lib/copy-sync/index.js
59
+ /path/to/my-tool/node_modules/fs-extra/lib/copy/copy.js
60
+ /path/to/my-tool/node_modules/fs-extra/lib/copy/index.js
61
+ /path/to/my-tool/node_modules/fs-extra/lib/empty/index.js
62
+ /path/to/my-tool/node_modules/fs-extra/lib/ensure/file.js
63
+ /path/to/my-tool/node_modules/fs-extra/lib/ensure/index.js
64
+ /path/to/my-tool/node_modules/fs-extra/lib/ensure/link.js
65
+ /path/to/my-tool/node_modules/fs-extra/lib/ensure/symlink-paths.js
66
+ /path/to/my-tool/node_modules/fs-extra/lib/ensure/symlink-type.js
67
+ /path/to/my-tool/node_modules/fs-extra/lib/ensure/symlink.js
68
+ /path/to/my-tool/node_modules/fs-extra/lib/fs/index.js
69
+ /path/to/my-tool/node_modules/fs-extra/lib/index.js
70
+ /path/to/my-tool/node_modules/fs-extra/lib/json/jsonfile.js
71
+ /path/to/my-tool/node_modules/fs-extra/lib/json/output-json-sync.js
72
+ /path/to/my-tool/node_modules/fs-extra/lib/json/output-json.js
73
+ /path/to/my-tool/node_modules/fs-extra/lib/mkdirs/index.js
74
+ /path/to/my-tool/node_modules/fs-extra/lib/mkdirs/make-dir.js
75
+ /path/to/my-tool/node_modules/fs-extra/lib/move-sync/index.js
76
+ /path/to/my-tool/node_modules/fs-extra/lib/move-sync/move-sync.js
77
+ /path/to/my-tool/node_modules/fs-extra/lib/move/index.js
78
+ /path/to/my-tool/node_modules/fs-extra/lib/move/move.js
79
+ /path/to/my-tool/node_modules/fs-extra/lib/output/index.js
80
+ /path/to/my-tool/node_modules/fs-extra/lib/path-exists/index.js
81
+ /path/to/my-tool/node_modules/fs-extra/lib/remove/index.js
82
+ /path/to/my-tool/node_modules/fs-extra/lib/remove/rimraf.js
83
+ /path/to/my-tool/node_modules/fs-extra/lib/util/stat.js
84
+ /path/to/my-tool/node_modules/fs-extra/lib/util/utimes.js
85
+ /path/to/my-tool/node_modules/graceful-fs/clone.js
86
+ /path/to/my-tool/node_modules/graceful-fs/graceful-fs.js
87
+ /path/to/my-tool/node_modules/graceful-fs/legacy-streams.js
88
+ /path/to/my-tool/node_modules/graceful-fs/polyfills.js
89
+ /path/to/my-tool/node_modules/jsonfile/index.js
90
+ /path/to/my-tool/node_modules/jsonfile/utils.js
91
+ /path/to/my-tool/node_modules/universalify/index.js
92
+ ```
93
+
94
+ ## Finding callers
95
+
96
+ To see how each file is imported, you can add the `--trace-imports` switch.
97
+ ```shell
98
+ # We use "--args" to pass the command-line arguments for "my-tool"
99
+ $ rundown inspect --script lib/start.js --args="--my-option 123 --verbose" --trace-imports
100
+ ```
101
+
102
+ The report now shows more detail:
103
+
104
+ **rundown-inspect.log**
105
+ ```
106
+ . . .
107
+ /path/to/my-tool/node_modules/graceful-fs/legacy-streams.js
108
+ imported by /path/to/my-tool/node_modules/graceful-fs/graceful-fs.js
109
+ imported by /path/to/my-tool/node_modules/fs-extra/lib/fs/index.js
110
+ imported by /path/to/my-tool/node_modules/fs-extra/lib/index.js
111
+ imported by /path/to/my-tool/lib/start.js
112
+ imported by /rundown/lib/launcher.js
113
+
114
+ /path/to/my-tool/node_modules/graceful-fs/polyfills.js
115
+ imported by /path/to/my-tool/node_modules/graceful-fs/graceful-fs.js
116
+ imported by /path/to/my-tool/node_modules/fs-extra/lib/fs/index.js
117
+ imported by /path/to/my-tool/node_modules/fs-extra/lib/index.js
118
+ imported by /path/to/my-tool/lib/start.js
119
+ imported by rundown/lib/launcher.js
120
+ . . .
121
+ ```
122
+
123
+ ## Fixing problems
124
+
125
+ It may be the case that many of these imports are not actually used. You can avoid preloading them
126
+ by converting them to lazy imports using the `Import.lazy()` from
127
+ [@rushstack/node-core-library](https://www.npmjs.com/package/@rushstack/node-core-library)
128
+ or [import-lazy](https://www.npmjs.com/package/import-lazy).
129
+
130
+
131
+ ## Generating a snapshot
132
+
133
+ To detect future regressions, use the `rundown snapshot` command to write a snapshot file:
134
+
135
+ ```shell
136
+ # We use "--args" to pass the command-line arguments for "my-tool"
137
+ $ rundown snapshot --script lib/start.js --args="--my-option 123 --verbose"
138
+
139
+ # This file can be committed to Git to track regressions
140
+ $ git add rundown-snapshot.log
141
+ ```
142
+
143
+ The snapshot file format eliminates spurious diffs, by showing only the names of the imported packages.
144
+ For local projects in a monorepo, it will show relative paths. Example output:
145
+
146
+ **rundown-snapshot.log**
147
+ ```
148
+ ../path/to/monorepo-sibling
149
+ at-least-node
150
+ fs-extra
151
+ graceful-fs
152
+ jsonfile
153
+ universalify
154
+ ```
155
+
156
+ ## Command-line reference
157
+
158
+ ```
159
+ usage: rundown [-h] <command> ...
160
+
161
+ Detect load time regressions by running an app, tracing require() calls, and
162
+ generating a deterministic report
163
+
164
+ Positional arguments:
165
+ <command>
166
+ snapshot Invoke a Node.js script and generate a test snapshot
167
+ inspect Invoke a Node.js script and generate detailed diagnostic output
168
+
169
+ Optional arguments:
170
+ -h, --help Show this help message and exit.
171
+
172
+ For detailed help about a specific command, use: rundown <command> -h
173
+ ```
174
+
175
+ ```
176
+ usage: rundown snapshot [-h] -s PATH [-a STRING] [-q] [-i]
177
+
178
+ Invoke a Node.js script and generate a test snapshot. This command creates a
179
+ concise report that can be added to Git, so that its diff can be used to
180
+ detect performance regressions
181
+
182
+ Optional arguments:
183
+ -h, --help Show this help message and exit.
184
+ -s PATH, --script PATH
185
+ The path to a .js file that will be the entry point
186
+ for the target Node.js process
187
+ -a STRING, --args STRING
188
+ Specifies command-line arguments to be passed to the
189
+ target Node.js process. The value should be a single
190
+ text string delimited by spaces. Example: rundown
191
+ inspect --scripts ./example.js --args="--flag
192
+ --option=123"
193
+ -q, --quiet Suppress STDOUT/STDERR for the target Node.js process
194
+ -i, --ignore-exit-code
195
+ Do not report an error if the target Node.js process
196
+ returns a nonzero exit code
197
+ ```
198
+
199
+ ```
200
+ usage: rundown inspect [-h] -s PATH [-a STRING] [-q] [-i] [-t]
201
+
202
+ Invoke a Node.js script and generate detailed diagnostic output. This command
203
+ is used to inspect performance regressions.
204
+
205
+ Optional arguments:
206
+ -h, --help Show this help message and exit.
207
+ -s PATH, --script PATH
208
+ The path to a .js file that will be the entry point
209
+ for the target Node.js process
210
+ -a STRING, --args STRING
211
+ Specifies command-line arguments to be passed to the
212
+ target Node.js process. The value should be a single
213
+ text string delimited by spaces. Example: rundown
214
+ inspect --scripts ./example.js --args="--flag
215
+ --option=123"
216
+ -q, --quiet Suppress STDOUT/STDERR for the target Node.js process
217
+ -i, --ignore-exit-code
218
+ Do not report an error if the target Node.js process
219
+ returns a nonzero exit code
220
+ -t, --trace-imports Reports the call chain for each module path, showing
221
+ how it was imported
222
+ ```
223
+
224
+ ## Links
225
+
226
+ - [CHANGELOG.md](
227
+ https://github.com/microsoft/rushstack/blob/main/apps/rundown/CHANGELOG.md) - Find
228
+ out what's new in the latest version
229
+
230
+ Rundown is part of the [Rush Stack](https://rushstack.io/) family of projects.
package/bin/rundown CHANGED
@@ -1,2 +1,2 @@
1
- #!/usr/bin/env node
2
- require('../lib/start.js');
1
+ #!/usr/bin/env node
2
+ require('../lib/start.js');
@@ -1 +1 @@
1
- {"version":3,"file":"LauncherTypes.js","sourceRoot":"","sources":["../src/LauncherTypes.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nexport const enum LauncherAction {\r\n Snapshot = 'snapshot',\r\n Inspect = 'inspect'\r\n}\r\n\r\nexport interface IIpcTraceRecord {\r\n importedModule: string;\r\n callingModule: string;\r\n}\r\n\r\nexport interface IIpcTrace {\r\n id: 'trace';\r\n records: IIpcTraceRecord[];\r\n}\r\n\r\nexport interface IIpcDone {\r\n id: 'done';\r\n}\r\n\r\nexport type IpcMessage = IIpcTrace | IIpcDone;\r\n"]}
1
+ {"version":3,"file":"LauncherTypes.js","sourceRoot":"","sources":["../src/LauncherTypes.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nexport const enum LauncherAction {\n Snapshot = 'snapshot',\n Inspect = 'inspect'\n}\n\nexport interface IIpcTraceRecord {\n importedModule: string;\n callingModule: string;\n}\n\nexport interface IIpcTrace {\n id: 'trace';\n records: IIpcTraceRecord[];\n}\n\nexport interface IIpcDone {\n id: 'done';\n}\n\nexport type IpcMessage = IIpcTrace | IIpcDone;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Rundown.js","sourceRoot":"","sources":["../src/Rundown.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { FileSystem, PackageJsonLookup, Sort, Text } from '@rushstack/node-core-library';\r\nimport * as child_process from 'child_process';\r\nimport * as path from 'path';\r\nimport stringArgv from 'string-argv';\r\n\r\nimport type { IpcMessage } from './LauncherTypes';\r\n\r\nexport class Rundown {\r\n // Map from required path --> caller path\r\n private _importedModuleMap: Map<string, string> = new Map();\r\n\r\n public async invokeAsync(\r\n scriptPath: string,\r\n args: string | undefined,\r\n quiet: boolean,\r\n ignoreExitCode: boolean\r\n ): Promise<void> {\r\n if (!FileSystem.exists(scriptPath)) {\r\n throw new Error('The specified script path does not exist: ' + scriptPath);\r\n }\r\n const absoluteScriptPath: string = path.resolve(scriptPath);\r\n\r\n const expandedArgs: string[] = args === undefined ? [] : stringArgv(args);\r\n\r\n console.log('Starting process: ' + [absoluteScriptPath, ...expandedArgs].join(' '));\r\n console.log();\r\n\r\n // Example process.argv:\r\n // [\"path/to/launcher.js\", \"path/to/target-script.js\", \"first-target-arg\"]\r\n const nodeArgs: string[] = [path.join(__dirname, 'launcher.js'), absoluteScriptPath, ...expandedArgs];\r\n\r\n await this._spawnLauncherAsync(nodeArgs, quiet, ignoreExitCode);\r\n\r\n if (!quiet) {\r\n console.log();\r\n }\r\n }\r\n\r\n public writeSnapshotReport(): void {\r\n const reportPath: string = 'rundown-snapshot.log';\r\n console.log('Writing report file: ' + reportPath);\r\n\r\n const packageJsonLookup: PackageJsonLookup = new PackageJsonLookup();\r\n const importedPaths: string[] = [...this._importedModuleMap.keys()];\r\n const importedPackageFolders: Set<string> = new Set();\r\n\r\n for (const importedPath of importedPaths) {\r\n const importedPackageFolder: string | undefined =\r\n packageJsonLookup.tryGetPackageFolderFor(importedPath);\r\n if (importedPackageFolder) {\r\n if (/[\\\\/]node_modules[\\\\/]/i.test(importedPackageFolder)) {\r\n importedPackageFolders.add(path.basename(importedPackageFolder));\r\n } else {\r\n const relativePath: string = path.relative(process.cwd(), importedPackageFolder);\r\n importedPackageFolders.add(Text.replaceAll(relativePath, '\\\\', '/'));\r\n }\r\n } else {\r\n // If the importedPath does not belong to an NPM package, then rundown-snapshot.log can ignore it.\r\n // In other words, treat it the same way as the local project's source files.\r\n }\r\n }\r\n\r\n Sort.sortSet(importedPackageFolders);\r\n const data: string = [...importedPackageFolders].join('\\n') + '\\n';\r\n\r\n FileSystem.writeFile(reportPath, data);\r\n }\r\n\r\n public writeInspectReport(traceImports: boolean): void {\r\n const reportPath: string = 'rundown-inspect.log';\r\n console.log('Writing report file: ' + reportPath);\r\n\r\n const importedPaths: string[] = [...this._importedModuleMap.keys()];\r\n importedPaths.sort();\r\n\r\n let data: string = '';\r\n\r\n if (traceImports) {\r\n for (const importedPath of importedPaths) {\r\n data += importedPath + '\\n';\r\n\r\n let current: string = importedPath;\r\n const visited: Set<string> = new Set();\r\n for (;;) {\r\n const callerPath: string | undefined = this._importedModuleMap.get(current);\r\n if (!callerPath) {\r\n break;\r\n }\r\n if (visited.has(callerPath)) {\r\n break;\r\n }\r\n visited.add(callerPath);\r\n data += ' imported by ' + callerPath + '\\n';\r\n current = callerPath;\r\n }\r\n data += '\\n';\r\n }\r\n } else {\r\n data = importedPaths.join('\\n') + '\\n';\r\n }\r\n\r\n FileSystem.writeFile(reportPath, data);\r\n }\r\n\r\n private async _spawnLauncherAsync(\r\n nodeArgs: string[],\r\n quiet: boolean,\r\n ignoreExitCode: boolean\r\n ): Promise<void> {\r\n const childProcess: child_process.ChildProcess = child_process.spawn(process.execPath, nodeArgs, {\r\n stdio: quiet ? ['inherit', 'ignore', 'ignore', 'ipc'] : ['inherit', 'inherit', 'inherit', 'ipc']\r\n });\r\n\r\n let completedNormally: boolean = false;\r\n\r\n childProcess.on('message', (message: IpcMessage): void => {\r\n switch (message.id) {\r\n case 'trace':\r\n for (const record of message.records) {\r\n this._importedModuleMap.set(record.importedModule, record.callingModule);\r\n }\r\n break;\r\n case 'done':\r\n completedNormally = true;\r\n break;\r\n default:\r\n throw new Error('Unknown IPC message: ' + JSON.stringify(message));\r\n }\r\n });\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n childProcess.on('exit', (code: number | null, signal: string | null): void => {\r\n if (code !== 0 && !ignoreExitCode) {\r\n reject(new Error('Child process terminated with exit code ' + code));\r\n } else if (!completedNormally) {\r\n reject(new Error('Child process terminated without completing IPC handshake'));\r\n } else {\r\n resolve();\r\n }\r\n });\r\n });\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"Rundown.js","sourceRoot":"","sources":["../src/Rundown.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { FileSystem, PackageJsonLookup, Sort, Text } from '@rushstack/node-core-library';\nimport * as child_process from 'child_process';\nimport * as path from 'path';\nimport stringArgv from 'string-argv';\n\nimport type { IpcMessage } from './LauncherTypes';\n\nexport class Rundown {\n // Map from required path --> caller path\n private _importedModuleMap: Map<string, string> = new Map();\n\n public async invokeAsync(\n scriptPath: string,\n args: string | undefined,\n quiet: boolean,\n ignoreExitCode: boolean\n ): Promise<void> {\n if (!FileSystem.exists(scriptPath)) {\n throw new Error('The specified script path does not exist: ' + scriptPath);\n }\n const absoluteScriptPath: string = path.resolve(scriptPath);\n\n const expandedArgs: string[] = args === undefined ? [] : stringArgv(args);\n\n console.log('Starting process: ' + [absoluteScriptPath, ...expandedArgs].join(' '));\n console.log();\n\n // Example process.argv:\n // [\"path/to/launcher.js\", \"path/to/target-script.js\", \"first-target-arg\"]\n const nodeArgs: string[] = [path.join(__dirname, 'launcher.js'), absoluteScriptPath, ...expandedArgs];\n\n await this._spawnLauncherAsync(nodeArgs, quiet, ignoreExitCode);\n\n if (!quiet) {\n console.log();\n }\n }\n\n public writeSnapshotReport(): void {\n const reportPath: string = 'rundown-snapshot.log';\n console.log('Writing report file: ' + reportPath);\n\n const packageJsonLookup: PackageJsonLookup = new PackageJsonLookup();\n const importedPaths: string[] = [...this._importedModuleMap.keys()];\n const importedPackageFolders: Set<string> = new Set();\n\n for (const importedPath of importedPaths) {\n const importedPackageFolder: string | undefined =\n packageJsonLookup.tryGetPackageFolderFor(importedPath);\n if (importedPackageFolder) {\n if (/[\\\\/]node_modules[\\\\/]/i.test(importedPackageFolder)) {\n importedPackageFolders.add(path.basename(importedPackageFolder));\n } else {\n const relativePath: string = path.relative(process.cwd(), importedPackageFolder);\n importedPackageFolders.add(Text.replaceAll(relativePath, '\\\\', '/'));\n }\n } else {\n // If the importedPath does not belong to an NPM package, then rundown-snapshot.log can ignore it.\n // In other words, treat it the same way as the local project's source files.\n }\n }\n\n Sort.sortSet(importedPackageFolders);\n const data: string = [...importedPackageFolders].join('\\n') + '\\n';\n\n FileSystem.writeFile(reportPath, data);\n }\n\n public writeInspectReport(traceImports: boolean): void {\n const reportPath: string = 'rundown-inspect.log';\n console.log('Writing report file: ' + reportPath);\n\n const importedPaths: string[] = [...this._importedModuleMap.keys()];\n importedPaths.sort();\n\n let data: string = '';\n\n if (traceImports) {\n for (const importedPath of importedPaths) {\n data += importedPath + '\\n';\n\n let current: string = importedPath;\n const visited: Set<string> = new Set();\n for (;;) {\n const callerPath: string | undefined = this._importedModuleMap.get(current);\n if (!callerPath) {\n break;\n }\n if (visited.has(callerPath)) {\n break;\n }\n visited.add(callerPath);\n data += ' imported by ' + callerPath + '\\n';\n current = callerPath;\n }\n data += '\\n';\n }\n } else {\n data = importedPaths.join('\\n') + '\\n';\n }\n\n FileSystem.writeFile(reportPath, data);\n }\n\n private async _spawnLauncherAsync(\n nodeArgs: string[],\n quiet: boolean,\n ignoreExitCode: boolean\n ): Promise<void> {\n const childProcess: child_process.ChildProcess = child_process.spawn(process.execPath, nodeArgs, {\n stdio: quiet ? ['inherit', 'ignore', 'ignore', 'ipc'] : ['inherit', 'inherit', 'inherit', 'ipc']\n });\n\n let completedNormally: boolean = false;\n\n childProcess.on('message', (message: IpcMessage): void => {\n switch (message.id) {\n case 'trace':\n for (const record of message.records) {\n this._importedModuleMap.set(record.importedModule, record.callingModule);\n }\n break;\n case 'done':\n completedNormally = true;\n break;\n default:\n throw new Error('Unknown IPC message: ' + JSON.stringify(message));\n }\n });\n\n await new Promise<void>((resolve, reject) => {\n childProcess.on('exit', (code: number | null, signal: string | null): void => {\n if (code !== 0 && !ignoreExitCode) {\n reject(new Error('Child process terminated with exit code ' + code));\n } else if (!completedNormally) {\n reject(new Error('Child process terminated without completing IPC handshake'));\n } else {\n resolve();\n }\n });\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"BaseReportAction.js","sourceRoot":"","sources":["../../src/cli/BaseReportAction.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,4FAA4F;AAC5F,2DAA2D;AAE3D,gEAKoC;AAEpC,MAAsB,gBAAiB,SAAQ,mCAAiB;IAM9D,YAAmB,OAAkC;QACnD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC;YAChD,iBAAiB,EAAE,UAAU;YAC7B,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,oFAAoF;YACjG,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC;YAC9C,iBAAiB,EAAE,QAAQ;YAC3B,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,QAAQ;YACtB,WAAW,EACT,yFAAyF;gBACzF,sDAAsD;gBACtD,+EAA+E;SAClF,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,mBAAmB,CAAC;YAC7C,iBAAiB,EAAE,SAAS;YAC5B,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,uDAAuD;SACrE,CAAC,CAAC;QACH,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,mBAAmB,CAAC;YACtD,iBAAiB,EAAE,oBAAoB;YACvC,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,kFAAkF;SAChG,CAAC,CAAC;IACL,CAAC;CACF;AApCD,4CAoCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\n// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport {\r\n CommandLineAction,\r\n type ICommandLineActionOptions,\r\n type CommandLineStringParameter,\r\n type CommandLineFlagParameter\r\n} from '@rushstack/ts-command-line';\r\n\r\nexport abstract class BaseReportAction extends CommandLineAction {\r\n protected readonly scriptParameter: CommandLineStringParameter;\r\n protected readonly argsParameter: CommandLineStringParameter;\r\n protected readonly quietParameter: CommandLineFlagParameter;\r\n protected readonly ignoreExitCodeParameter: CommandLineFlagParameter;\r\n\r\n public constructor(options: ICommandLineActionOptions) {\r\n super(options);\r\n\r\n this.scriptParameter = this.defineStringParameter({\r\n parameterLongName: '--script',\r\n parameterShortName: '-s',\r\n argumentName: 'PATH',\r\n description: 'The path to a .js file that will be the entry point for the target Node.js process',\r\n required: true\r\n });\r\n this.argsParameter = this.defineStringParameter({\r\n parameterLongName: '--args',\r\n parameterShortName: '-a',\r\n argumentName: 'STRING',\r\n description:\r\n 'Specifies command-line arguments to be passed to the target Node.js process. The value' +\r\n ' should be a single text string delimited by spaces.' +\r\n ' Example: rundown inspect --scripts ./example.js --args=\"--flag --option=123\"'\r\n });\r\n this.quietParameter = this.defineFlagParameter({\r\n parameterLongName: '--quiet',\r\n parameterShortName: '-q',\r\n description: 'Suppress STDOUT/STDERR for the target Node.js process'\r\n });\r\n this.ignoreExitCodeParameter = this.defineFlagParameter({\r\n parameterLongName: '--ignore-exit-code',\r\n parameterShortName: '-i',\r\n description: 'Do not report an error if the target Node.js process returns a nonzero exit code'\r\n });\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"BaseReportAction.js","sourceRoot":"","sources":["../../src/cli/BaseReportAction.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,4FAA4F;AAC5F,2DAA2D;AAE3D,gEAKoC;AAEpC,MAAsB,gBAAiB,SAAQ,mCAAiB;IAM9D,YAAmB,OAAkC;QACnD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC;YAChD,iBAAiB,EAAE,UAAU;YAC7B,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,oFAAoF;YACjG,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC;YAC9C,iBAAiB,EAAE,QAAQ;YAC3B,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,QAAQ;YACtB,WAAW,EACT,yFAAyF;gBACzF,sDAAsD;gBACtD,+EAA+E;SAClF,CAAC,CAAC;QACH,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,mBAAmB,CAAC;YAC7C,iBAAiB,EAAE,SAAS;YAC5B,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,uDAAuD;SACrE,CAAC,CAAC;QACH,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,mBAAmB,CAAC;YACtD,iBAAiB,EAAE,oBAAoB;YACvC,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,kFAAkF;SAChG,CAAC,CAAC;IACL,CAAC;CACF;AApCD,4CAoCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport {\n CommandLineAction,\n type ICommandLineActionOptions,\n type CommandLineStringParameter,\n type CommandLineFlagParameter\n} from '@rushstack/ts-command-line';\n\nexport abstract class BaseReportAction extends CommandLineAction {\n protected readonly scriptParameter: CommandLineStringParameter;\n protected readonly argsParameter: CommandLineStringParameter;\n protected readonly quietParameter: CommandLineFlagParameter;\n protected readonly ignoreExitCodeParameter: CommandLineFlagParameter;\n\n public constructor(options: ICommandLineActionOptions) {\n super(options);\n\n this.scriptParameter = this.defineStringParameter({\n parameterLongName: '--script',\n parameterShortName: '-s',\n argumentName: 'PATH',\n description: 'The path to a .js file that will be the entry point for the target Node.js process',\n required: true\n });\n this.argsParameter = this.defineStringParameter({\n parameterLongName: '--args',\n parameterShortName: '-a',\n argumentName: 'STRING',\n description:\n 'Specifies command-line arguments to be passed to the target Node.js process. The value' +\n ' should be a single text string delimited by spaces.' +\n ' Example: rundown inspect --scripts ./example.js --args=\"--flag --option=123\"'\n });\n this.quietParameter = this.defineFlagParameter({\n parameterLongName: '--quiet',\n parameterShortName: '-q',\n description: 'Suppress STDOUT/STDERR for the target Node.js process'\n });\n this.ignoreExitCodeParameter = this.defineFlagParameter({\n parameterLongName: '--ignore-exit-code',\n parameterShortName: '-i',\n description: 'Do not report an error if the target Node.js process returns a nonzero exit code'\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"InspectAction.js","sourceRoot":"","sources":["../../src/cli/InspectAction.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAI3D,yDAAsD;AACtD,wCAAqC;AAErC,MAAa,aAAc,SAAQ,mCAAgB;IAGjD;QACE,KAAK,CAAC;YACJ,UAAU,EAAE,SAAS;YACrB,OAAO,EAAE,iEAAiE;YAC1E,aAAa,EACX,wFAAwF;gBACxF,sCAAsC;SACzC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC;YAC9C,iBAAiB,EAAE,iBAAiB;YACpC,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,0EAA0E;SACxF,CAAC,CAAC;IACL,CAAC;IAES,KAAK,CAAC,SAAS;QACvB,MAAM,OAAO,GAAY,IAAI,iBAAO,EAAE,CAAC;QACvC,MAAM,OAAO,CAAC,WAAW,CACvB,IAAI,CAAC,eAAe,CAAC,KAAM,EAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,EACxB,IAAI,CAAC,cAAc,CAAC,KAAO,EAC3B,IAAI,CAAC,uBAAuB,CAAC,KAAO,CACrC,CAAC;QACF,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,KAAO,CAAC,CAAC;IAC3D,CAAC;CACF;AA7BD,sCA6BC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport type { CommandLineFlagParameter } from '@rushstack/ts-command-line';\r\n\r\nimport { BaseReportAction } from './BaseReportAction';\r\nimport { Rundown } from '../Rundown';\r\n\r\nexport class InspectAction extends BaseReportAction {\r\n private readonly _traceParameter: CommandLineFlagParameter;\r\n\r\n public constructor() {\r\n super({\r\n actionName: 'inspect',\r\n summary: 'Invoke a Node.js script and generate detailed diagnostic output',\r\n documentation:\r\n 'Invoke a Node.js script and generate detailed diagnostic output. This command is used' +\r\n ' to inspect performance regressions.'\r\n });\r\n\r\n this._traceParameter = this.defineFlagParameter({\r\n parameterLongName: '--trace-imports',\r\n parameterShortName: '-t',\r\n description: 'Reports the call chain for each module path, showing how it was imported'\r\n });\r\n }\r\n\r\n protected async onExecute(): Promise<void> {\r\n const rundown: Rundown = new Rundown();\r\n await rundown.invokeAsync(\r\n this.scriptParameter.value!,\r\n this.argsParameter.value,\r\n this.quietParameter.value!!,\r\n this.ignoreExitCodeParameter.value!!\r\n );\r\n rundown.writeInspectReport(this._traceParameter.value!!);\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"InspectAction.js","sourceRoot":"","sources":["../../src/cli/InspectAction.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAI3D,yDAAsD;AACtD,wCAAqC;AAErC,MAAa,aAAc,SAAQ,mCAAgB;IAGjD;QACE,KAAK,CAAC;YACJ,UAAU,EAAE,SAAS;YACrB,OAAO,EAAE,iEAAiE;YAC1E,aAAa,EACX,wFAAwF;gBACxF,sCAAsC;SACzC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC;YAC9C,iBAAiB,EAAE,iBAAiB;YACpC,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,0EAA0E;SACxF,CAAC,CAAC;IACL,CAAC;IAES,KAAK,CAAC,SAAS;QACvB,MAAM,OAAO,GAAY,IAAI,iBAAO,EAAE,CAAC;QACvC,MAAM,OAAO,CAAC,WAAW,CACvB,IAAI,CAAC,eAAe,CAAC,KAAM,EAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,EACxB,IAAI,CAAC,cAAc,CAAC,KAAO,EAC3B,IAAI,CAAC,uBAAuB,CAAC,KAAO,CACrC,CAAC;QACF,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,KAAO,CAAC,CAAC;IAC3D,CAAC;CACF;AA7BD,sCA6BC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { CommandLineFlagParameter } from '@rushstack/ts-command-line';\n\nimport { BaseReportAction } from './BaseReportAction';\nimport { Rundown } from '../Rundown';\n\nexport class InspectAction extends BaseReportAction {\n private readonly _traceParameter: CommandLineFlagParameter;\n\n public constructor() {\n super({\n actionName: 'inspect',\n summary: 'Invoke a Node.js script and generate detailed diagnostic output',\n documentation:\n 'Invoke a Node.js script and generate detailed diagnostic output. This command is used' +\n ' to inspect performance regressions.'\n });\n\n this._traceParameter = this.defineFlagParameter({\n parameterLongName: '--trace-imports',\n parameterShortName: '-t',\n description: 'Reports the call chain for each module path, showing how it was imported'\n });\n }\n\n protected async onExecute(): Promise<void> {\n const rundown: Rundown = new Rundown();\n await rundown.invokeAsync(\n this.scriptParameter.value!,\n this.argsParameter.value,\n this.quietParameter.value!!,\n this.ignoreExitCodeParameter.value!!\n );\n rundown.writeInspectReport(this._traceParameter.value!!);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"RundownCommandLine.js","sourceRoot":"","sources":["../../src/cli/RundownCommandLine.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,gEAA+D;AAE/D,qDAAkD;AAClD,mDAAgD;AAEhD,MAAa,kBAAmB,SAAQ,mCAAiB;IACvD;QACE,KAAK,CAAC;YACJ,YAAY,EAAE,SAAS;YACvB,eAAe,EACb,0EAA0E;gBAC1E,wCAAwC;SAC3C,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,IAAI,+BAAc,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,SAAS,CAAC,IAAI,6BAAa,EAAE,CAAC,CAAC;IACtC,CAAC;CACF;AAZD,gDAYC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { CommandLineParser } from '@rushstack/ts-command-line';\r\n\r\nimport { SnapshotAction } from './SnapshotAction';\r\nimport { InspectAction } from './InspectAction';\r\n\r\nexport class RundownCommandLine extends CommandLineParser {\r\n public constructor() {\r\n super({\r\n toolFilename: 'rundown',\r\n toolDescription:\r\n 'Detect load time regressions by running an app, tracing require() calls,' +\r\n ' and generating a deterministic report'\r\n });\r\n\r\n this.addAction(new SnapshotAction());\r\n this.addAction(new InspectAction());\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"RundownCommandLine.js","sourceRoot":"","sources":["../../src/cli/RundownCommandLine.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,gEAA+D;AAE/D,qDAAkD;AAClD,mDAAgD;AAEhD,MAAa,kBAAmB,SAAQ,mCAAiB;IACvD;QACE,KAAK,CAAC;YACJ,YAAY,EAAE,SAAS;YACvB,eAAe,EACb,0EAA0E;gBAC1E,wCAAwC;SAC3C,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,IAAI,+BAAc,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,SAAS,CAAC,IAAI,6BAAa,EAAE,CAAC,CAAC;IACtC,CAAC;CACF;AAZD,gDAYC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { CommandLineParser } from '@rushstack/ts-command-line';\n\nimport { SnapshotAction } from './SnapshotAction';\nimport { InspectAction } from './InspectAction';\n\nexport class RundownCommandLine extends CommandLineParser {\n public constructor() {\n super({\n toolFilename: 'rundown',\n toolDescription:\n 'Detect load time regressions by running an app, tracing require() calls,' +\n ' and generating a deterministic report'\n });\n\n this.addAction(new SnapshotAction());\n this.addAction(new InspectAction());\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"SnapshotAction.js","sourceRoot":"","sources":["../../src/cli/SnapshotAction.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,yDAAsD;AAEtD,wCAAqC;AAErC,MAAa,cAAe,SAAQ,mCAAgB;IAClD;QACE,KAAK,CAAC;YACJ,UAAU,EAAE,UAAU;YACtB,OAAO,EAAE,sDAAsD;YAC/D,aAAa,EACX,0GAA0G;gBAC1G,+EAA+E;SAClF,CAAC,CAAC;IACL,CAAC;IAES,KAAK,CAAC,SAAS;QACvB,MAAM,OAAO,GAAY,IAAI,iBAAO,EAAE,CAAC;QACvC,MAAM,OAAO,CAAC,WAAW,CACvB,IAAI,CAAC,eAAe,CAAC,KAAM,EAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,EACxB,IAAI,CAAC,cAAc,CAAC,KAAO,EAC3B,IAAI,CAAC,uBAAuB,CAAC,KAAO,CACrC,CAAC;QACF,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAChC,CAAC;CACF;AArBD,wCAqBC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { BaseReportAction } from './BaseReportAction';\r\n\r\nimport { Rundown } from '../Rundown';\r\n\r\nexport class SnapshotAction extends BaseReportAction {\r\n public constructor() {\r\n super({\r\n actionName: 'snapshot',\r\n summary: 'Invoke a Node.js script and generate a test snapshot',\r\n documentation:\r\n 'Invoke a Node.js script and generate a test snapshot. This command creates a concise report that can be' +\r\n ' added to Git, so that its diff can be used to detect performance regressions'\r\n });\r\n }\r\n\r\n protected async onExecute(): Promise<void> {\r\n const rundown: Rundown = new Rundown();\r\n await rundown.invokeAsync(\r\n this.scriptParameter.value!,\r\n this.argsParameter.value,\r\n this.quietParameter.value!!,\r\n this.ignoreExitCodeParameter.value!!\r\n );\r\n rundown.writeSnapshotReport();\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"SnapshotAction.js","sourceRoot":"","sources":["../../src/cli/SnapshotAction.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,yDAAsD;AAEtD,wCAAqC;AAErC,MAAa,cAAe,SAAQ,mCAAgB;IAClD;QACE,KAAK,CAAC;YACJ,UAAU,EAAE,UAAU;YACtB,OAAO,EAAE,sDAAsD;YAC/D,aAAa,EACX,0GAA0G;gBAC1G,+EAA+E;SAClF,CAAC,CAAC;IACL,CAAC;IAES,KAAK,CAAC,SAAS;QACvB,MAAM,OAAO,GAAY,IAAI,iBAAO,EAAE,CAAC;QACvC,MAAM,OAAO,CAAC,WAAW,CACvB,IAAI,CAAC,eAAe,CAAC,KAAM,EAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,EACxB,IAAI,CAAC,cAAc,CAAC,KAAO,EAC3B,IAAI,CAAC,uBAAuB,CAAC,KAAO,CACrC,CAAC;QACF,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAChC,CAAC;CACF;AArBD,wCAqBC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { BaseReportAction } from './BaseReportAction';\n\nimport { Rundown } from '../Rundown';\n\nexport class SnapshotAction extends BaseReportAction {\n public constructor() {\n super({\n actionName: 'snapshot',\n summary: 'Invoke a Node.js script and generate a test snapshot',\n documentation:\n 'Invoke a Node.js script and generate a test snapshot. This command creates a concise report that can be' +\n ' added to Git, so that its diff can be used to detect performance regressions'\n });\n }\n\n protected async onExecute(): Promise<void> {\n const rundown: Rundown = new Rundown();\n await rundown.invokeAsync(\n this.scriptParameter.value!,\n this.argsParameter.value,\n this.quietParameter.value!!,\n this.ignoreExitCodeParameter.value!!\n );\n rundown.writeSnapshotReport();\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"launcher.js","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;AAE3D,oCAAqC;AACrC,sDAA8B;AAK9B,sFAAsF;AACtF,MAAM,cAAc,GAAW,GAAG,CAAC;AAEnC,MAAM,QAAQ;IAAd;QACS,WAAM,0CAA0C;QAChD,wBAAmB,GAAW,EAAE,CAAC;QACjC,eAAU,GAAW,EAAE,CAAC;QACvB,qBAAgB,GAAiB,IAAI,GAAG,EAAE,CAAC;QAC3C,yBAAoB,GAAgB,IAAI,GAAG,EAAE,CAAC;QAC9C,0BAAqB,GAAsB,EAAE,CAAC;IA8GxD,CAAC;IA5GQ,aAAa,CAAC,IAA2B;QAC9C,IAAI,OAAe,CAAC;QACpB,IAAI,aAAuB,CAAC;QAE5B,wBAAwB;QACxB,8FAA8F;QAC9F,CAAC,OAAO,EAAE,AAAD,EAAG,IAAI,CAAC,mBAAmB,EAAE,GAAG,aAAa,CAAC,GAAG,IAAI,CAAC;QAE/D,wBAAwB;QACxB,uEAAuE;QACvE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,GAAG,aAAa,CAAC,CAAC;IAC/D,CAAC;IAED,8DAA8D;IACtD,MAAM,CAAC,eAAe,CAAC,GAAQ,EAAE,GAAQ;QAC/C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YACnC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;SACvB;IACH,CAAC;IAEO,kBAAkB;QACxB,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE;YACzC,MAAM,KAAK,GAAsB,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAC;YACjE,IAAI,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,CAAC;YAEtC,iBAAO,CAAC,IAAK,CAAC;gBACZ,EAAE,EAAE,OAAO;gBACX,OAAO,EAAE,KAAK;aACF,CAAC,CAAC;SACjB;IACH,CAAC;IAED;;OAEG;IACK,MAAM,CAAC,QAAQ,CAAC,YAAoB;QAC1C,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;IAC7E,CAAC;IAEM,WAAW;QAChB,MAAM,WAAW,GAAmB,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC;QAEvE,MAAM,eAAe,GAAiB,IAAI,CAAC,gBAAgB,CAAC,CAAC,cAAc;QAC3E,MAAM,mBAAmB,GAAgB,IAAI,CAAC,oBAAoB,CAAC,CAAC,cAAc;QAClF,MAAM,oBAAoB,GAAsB,IAAI,CAAC,qBAAqB,CAAC,CAAC,cAAc;QAC1F,MAAM,iBAAiB,GAAe,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc;QAExF,SAAS,aAAa,CAAmB,UAAkB;YACzD,4EAA4E;YAC5E,iBAAiB;YACjB,MAAM,iBAAiB,GAAe,IAAI,CAAC;YAE3C,+FAA+F;YAC/F,8DAA8D;YAC9D,MAAM,cAAc,GAAa,WAAmB,CAAC,KAAK,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;YAEzF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE;gBACxC,eAAe,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAEpC,wCAAwC;gBACxC,IAAI,kBAAkB,GAA2B,SAAS,CAAC;gBAC3D,MAAM,QAAQ,GAAiB,iBAAiB,CAAC,QAAQ,IAAI,EAAE,CAAC;gBAChE,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE;oBAC5B,IAAI,KAAK,CAAC,OAAO,KAAK,cAAc,EAAE;wBACpC,kBAAkB,GAAG,KAAK,CAAC;wBAC3B,MAAM;qBACP;iBACF;gBAED,IAAI,kBAAkB,KAAK,SAAS,EAAE;oBACpC,mCAAmC;iBACpC;qBAAM;oBACL,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE;wBAChC,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,UAAU,CAAC,CAAC;qBACvD;oBAED,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE;wBACzD,mBAAmB,CAAC,GAAG,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;wBACrD,oBAAoB,CAAC,IAAI,CAAC;4BACxB,cAAc,EAAE,kBAAkB,CAAC,QAAQ;4BAC3C,aAAa,EAAE,iBAAiB,CAAC,QAAQ;yBAC1C,CAAC,CAAC;wBACH,IAAI,oBAAoB,CAAC,MAAM,IAAI,cAAc,EAAE;4BACjD,iBAAiB,EAAE,CAAC;yBACrB;qBACF;iBACF;aACF;YAED,OAAO,cAAc,CAAC;QACxB,CAAC;QAED,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,GAAG,aAA+B,CAAC;QACrE,QAAQ,CAAC,eAAe,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QAErD,iBAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,iBAAO,CAAC,IAAK,CAAC;gBACZ,EAAE,EAAE,MAAM;aACC,CAAC,CAAC;YAEf,4GAA4G;YAC5G,uGAAuG;YACvG,wGAAwG;YACxG,4DAA4D;YAC5D,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED,IAAI,CAAC,iBAAO,CAAC,IAAI,EAAE;IACjB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;CACxD;AAED,MAAM,QAAQ,GAAa,IAAI,QAAQ,EAAE,CAAC;AAE1C,MAAM,YAAY,GAA0B,CAAC,GAAG,iBAAO,CAAC,IAAI,CAAC,CAAC;AAC9D,iBAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;AACxB,iBAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;AAE3D,QAAQ,CAAC,WAAW,EAAE,CAAC;AAEvB,gBAAgB;AAChB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport moduleApi = require('module');\r\nimport process from 'process';\r\n\r\nimport { LauncherAction } from './LauncherTypes'; // \"import type\" doesn't work with const enums\r\nimport type { IIpcTrace, IIpcDone, IIpcTraceRecord } from './LauncherTypes';\r\n\r\n// The _ipcTraceRecordsBatch will get transmitted when this many items are accumulated\r\nconst IPC_BATCH_SIZE: number = 300;\r\n\r\nclass Launcher {\r\n public action: LauncherAction = LauncherAction.Inspect;\r\n public targetScriptPathArg: string = '';\r\n public reportPath: string = '';\r\n private _importedModules: Set<unknown> = new Set();\r\n private _importedModulePaths: Set<string> = new Set();\r\n private _ipcTraceRecordsBatch: IIpcTraceRecord[] = [];\r\n\r\n public transformArgs(argv: ReadonlyArray<string>): string[] {\r\n let nodeArg: string;\r\n let remainderArgs: string[];\r\n\r\n // Example process.argv:\r\n // [\"path/to/node.exe\", \"path/to/launcher.js\", \"path/to/target-script.js\", \"first-target-arg\"]\r\n [nodeArg, , this.targetScriptPathArg, ...remainderArgs] = argv;\r\n\r\n // Example process.argv:\r\n // [\"path/to/node.exe\", \"path/to/target-script.js\", \"first-target-arg\"]\r\n return [nodeArg, this.targetScriptPathArg, ...remainderArgs];\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n private static _copyProperties(dst: any, src: any): void {\r\n for (const prop of Object.keys(src)) {\r\n dst[prop] = src[prop];\r\n }\r\n }\r\n\r\n private _sendIpcTraceBatch(): void {\r\n if (this._ipcTraceRecordsBatch.length > 0) {\r\n const batch: IIpcTraceRecord[] = [...this._ipcTraceRecordsBatch];\r\n this._ipcTraceRecordsBatch.length = 0;\r\n\r\n process.send!({\r\n id: 'trace',\r\n records: batch\r\n } as IIpcTrace);\r\n }\r\n }\r\n\r\n /**\r\n * Synchronously delay for the specified time interval.\r\n */\r\n private static _delayMs(milliseconds: number): void {\r\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);\r\n }\r\n\r\n public installHook(): void {\r\n const realRequire: NodeJS.Require = moduleApi.Module.prototype.require;\r\n\r\n const importedModules: Set<unknown> = this._importedModules; // for closure\r\n const importedModulePaths: Set<string> = this._importedModulePaths; // for closure\r\n const ipcTraceRecordsBatch: IIpcTraceRecord[] = this._ipcTraceRecordsBatch; // for closure\r\n const sendIpcTraceBatch: () => void = this._sendIpcTraceBatch.bind(this); // for closure\r\n\r\n function hookedRequire(this: NodeModule, moduleName: string): unknown {\r\n // NOTE: The \"this\" pointer is the calling NodeModule, so we rely on closure\r\n // variable here.\r\n const callingModuleInfo: NodeModule = this;\r\n\r\n // Paranoidly use \"arguments\" in case some implementor passes additional undocumented arguments\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const importedModule: unknown = (realRequire as any).apply(callingModuleInfo, arguments);\r\n\r\n if (!importedModules.has(importedModule)) {\r\n importedModules.add(importedModule);\r\n\r\n // Find the info for the imported module\r\n let importedModuleInfo: NodeModule | undefined = undefined;\r\n const children: NodeModule[] = callingModuleInfo.children || [];\r\n for (const child of children) {\r\n if (child.exports === importedModule) {\r\n importedModuleInfo = child;\r\n break;\r\n }\r\n }\r\n\r\n if (importedModuleInfo === undefined) {\r\n // It's a built-in module like \"os\"\r\n } else {\r\n if (!importedModuleInfo.filename) {\r\n throw new Error('Missing filename for ' + moduleName);\r\n }\r\n\r\n if (!importedModulePaths.has(importedModuleInfo.filename)) {\r\n importedModulePaths.add(importedModuleInfo.filename);\r\n ipcTraceRecordsBatch.push({\r\n importedModule: importedModuleInfo.filename,\r\n callingModule: callingModuleInfo.filename\r\n });\r\n if (ipcTraceRecordsBatch.length >= IPC_BATCH_SIZE) {\r\n sendIpcTraceBatch();\r\n }\r\n }\r\n }\r\n }\r\n\r\n return importedModule;\r\n }\r\n\r\n moduleApi.Module.prototype.require = hookedRequire as NodeJS.Require;\r\n Launcher._copyProperties(hookedRequire, realRequire);\r\n\r\n process.on('exit', () => {\r\n this._sendIpcTraceBatch();\r\n process.send!({\r\n id: 'done'\r\n } as IIpcDone);\r\n\r\n // The Node.js \"exit\" event is synchronous, and the process will terminate as soon as this function returns.\r\n // To avoid a race condition, allow some time for IPC messages to be transmitted to the parent process.\r\n // TODO: There should be a way to eliminate this delay by intercepting earlier in the shutdown sequence,\r\n // but it needs to consider every way that Node.js can exit.\r\n Launcher._delayMs(500);\r\n });\r\n }\r\n}\r\n\r\nif (!process.send) {\r\n throw new Error('launcher.js must be invoked via IPC');\r\n}\r\n\r\nconst launcher: Launcher = new Launcher();\r\n\r\nconst originalArgv: ReadonlyArray<string> = [...process.argv];\r\nprocess.argv.length = 0;\r\nprocess.argv.push(...launcher.transformArgs(originalArgv));\r\n\r\nlauncher.installHook();\r\n\r\n// Start the app\r\nrequire(launcher.targetScriptPathArg);\r\n"]}
1
+ {"version":3,"file":"launcher.js","sourceRoot":"","sources":["../src/launcher.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport moduleApi = require('module');\nimport process from 'process';\n\nimport { LauncherAction } from './LauncherTypes'; // \"import type\" doesn't work with const enums\nimport type { IIpcTrace, IIpcDone, IIpcTraceRecord } from './LauncherTypes';\n\n// The _ipcTraceRecordsBatch will get transmitted when this many items are accumulated\nconst IPC_BATCH_SIZE: number = 300;\n\nclass Launcher {\n public action: LauncherAction = LauncherAction.Inspect;\n public targetScriptPathArg: string = '';\n public reportPath: string = '';\n private _importedModules: Set<unknown> = new Set();\n private _importedModulePaths: Set<string> = new Set();\n private _ipcTraceRecordsBatch: IIpcTraceRecord[] = [];\n\n public transformArgs(argv: ReadonlyArray<string>): string[] {\n let nodeArg: string;\n let remainderArgs: string[];\n\n // Example process.argv:\n // [\"path/to/node.exe\", \"path/to/launcher.js\", \"path/to/target-script.js\", \"first-target-arg\"]\n [nodeArg, , this.targetScriptPathArg, ...remainderArgs] = argv;\n\n // Example process.argv:\n // [\"path/to/node.exe\", \"path/to/target-script.js\", \"first-target-arg\"]\n return [nodeArg, this.targetScriptPathArg, ...remainderArgs];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private static _copyProperties(dst: any, src: any): void {\n for (const prop of Object.keys(src)) {\n dst[prop] = src[prop];\n }\n }\n\n private _sendIpcTraceBatch(): void {\n if (this._ipcTraceRecordsBatch.length > 0) {\n const batch: IIpcTraceRecord[] = [...this._ipcTraceRecordsBatch];\n this._ipcTraceRecordsBatch.length = 0;\n\n process.send!({\n id: 'trace',\n records: batch\n } as IIpcTrace);\n }\n }\n\n /**\n * Synchronously delay for the specified time interval.\n */\n private static _delayMs(milliseconds: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);\n }\n\n public installHook(): void {\n const realRequire: NodeJS.Require = moduleApi.Module.prototype.require;\n\n const importedModules: Set<unknown> = this._importedModules; // for closure\n const importedModulePaths: Set<string> = this._importedModulePaths; // for closure\n const ipcTraceRecordsBatch: IIpcTraceRecord[] = this._ipcTraceRecordsBatch; // for closure\n const sendIpcTraceBatch: () => void = this._sendIpcTraceBatch.bind(this); // for closure\n\n function hookedRequire(this: NodeModule, moduleName: string): unknown {\n // NOTE: The \"this\" pointer is the calling NodeModule, so we rely on closure\n // variable here.\n const callingModuleInfo: NodeModule = this;\n\n // Paranoidly use \"arguments\" in case some implementor passes additional undocumented arguments\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const importedModule: unknown = (realRequire as any).apply(callingModuleInfo, arguments);\n\n if (!importedModules.has(importedModule)) {\n importedModules.add(importedModule);\n\n // Find the info for the imported module\n let importedModuleInfo: NodeModule | undefined = undefined;\n const children: NodeModule[] = callingModuleInfo.children || [];\n for (const child of children) {\n if (child.exports === importedModule) {\n importedModuleInfo = child;\n break;\n }\n }\n\n if (importedModuleInfo === undefined) {\n // It's a built-in module like \"os\"\n } else {\n if (!importedModuleInfo.filename) {\n throw new Error('Missing filename for ' + moduleName);\n }\n\n if (!importedModulePaths.has(importedModuleInfo.filename)) {\n importedModulePaths.add(importedModuleInfo.filename);\n ipcTraceRecordsBatch.push({\n importedModule: importedModuleInfo.filename,\n callingModule: callingModuleInfo.filename\n });\n if (ipcTraceRecordsBatch.length >= IPC_BATCH_SIZE) {\n sendIpcTraceBatch();\n }\n }\n }\n }\n\n return importedModule;\n }\n\n moduleApi.Module.prototype.require = hookedRequire as NodeJS.Require;\n Launcher._copyProperties(hookedRequire, realRequire);\n\n process.on('exit', () => {\n this._sendIpcTraceBatch();\n process.send!({\n id: 'done'\n } as IIpcDone);\n\n // The Node.js \"exit\" event is synchronous, and the process will terminate as soon as this function returns.\n // To avoid a race condition, allow some time for IPC messages to be transmitted to the parent process.\n // TODO: There should be a way to eliminate this delay by intercepting earlier in the shutdown sequence,\n // but it needs to consider every way that Node.js can exit.\n Launcher._delayMs(500);\n });\n }\n}\n\nif (!process.send) {\n throw new Error('launcher.js must be invoked via IPC');\n}\n\nconst launcher: Launcher = new Launcher();\n\nconst originalArgv: ReadonlyArray<string> = [...process.argv];\nprocess.argv.length = 0;\nprocess.argv.push(...launcher.transformArgs(originalArgv));\n\nlauncher.installHook();\n\n// Start the app\nrequire(launcher.targetScriptPathArg);\n"]}
package/lib/start.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"start.js","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;AAE3D,oEAAiE;AAEjE,iEAA8D;AAE9D,MAAM,WAAW,GAAW,qCAAiB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC;AAEpF,OAAO,CAAC,GAAG,EAAE,CAAC;AACd,OAAO,CAAC,GAAG,CAAC,WAAW,WAAW,yBAAyB,CAAC,CAAC;AAC7D,OAAO,CAAC,GAAG,EAAE,CAAC;AAEd,MAAM,WAAW,GAAuB,IAAI,uCAAkB,EAAE,CAAC;AACjE,WAAW,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACpC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { PackageJsonLookup } from '@rushstack/node-core-library';\r\n\r\nimport { RundownCommandLine } from './cli/RundownCommandLine';\r\n\r\nconst toolVersion: string = PackageJsonLookup.loadOwnPackageJson(__dirname).version;\r\n\r\nconsole.log();\r\nconsole.log(`Rundown ${toolVersion} - https://rushstack.io`);\r\nconsole.log();\r\n\r\nconst commandLine: RundownCommandLine = new RundownCommandLine();\r\ncommandLine.execute().catch((error) => {\r\n console.error(error);\r\n});\r\n"]}
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;AAE3D,oEAAiE;AAEjE,iEAA8D;AAE9D,MAAM,WAAW,GAAW,qCAAiB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC;AAEpF,OAAO,CAAC,GAAG,EAAE,CAAC;AACd,OAAO,CAAC,GAAG,CAAC,WAAW,WAAW,yBAAyB,CAAC,CAAC;AAC7D,OAAO,CAAC,GAAG,EAAE,CAAC;AAEd,MAAM,WAAW,GAAuB,IAAI,uCAAkB,EAAE,CAAC;AACjE,WAAW,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACpC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { PackageJsonLookup } from '@rushstack/node-core-library';\n\nimport { RundownCommandLine } from './cli/RundownCommandLine';\n\nconst toolVersion: string = PackageJsonLookup.loadOwnPackageJson(__dirname).version;\n\nconsole.log();\nconsole.log(`Rundown ${toolVersion} - https://rushstack.io`);\nconsole.log();\n\nconst commandLine: RundownCommandLine = new RundownCommandLine();\ncommandLine.execute().catch((error) => {\n console.error(error);\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rushstack/rundown",
3
- "version": "1.1.10",
3
+ "version": "1.1.11",
4
4
  "description": "Detect load time regressions by running an app, tracing require() calls, and generating a deterministic report",
5
5
  "repository": {
6
6
  "type": "git",
@@ -19,10 +19,10 @@
19
19
  "dependencies": {
20
20
  "string-argv": "~0.3.1",
21
21
  "@rushstack/node-core-library": "3.61.0",
22
- "@rushstack/ts-command-line": "4.17.0"
22
+ "@rushstack/ts-command-line": "4.17.1"
23
23
  },
24
24
  "devDependencies": {
25
- "@rushstack/heft": "0.63.0",
25
+ "@rushstack/heft": "0.63.1",
26
26
  "local-node-rig": "1.0.0"
27
27
  },
28
28
  "scripts": {