1'use strict';
2
3const {
4  Error,
5  ObjectDefineProperty,
6  ObjectGetOwnPropertyDescriptor,
7  ObjectSetPrototypeOf,
8  SafeArrayIterator,
9  SafeSet,
10} = primordials;
11
12const binding = internalBinding('mksnapshot');
13const { BuiltinModule: { normalizeRequirableId } } = require('internal/bootstrap/realm');
14const {
15  compileSerializeMain,
16} = binding;
17
18const {
19  getOptionValue,
20} = require('internal/options');
21
22const {
23  readFileSync,
24} = require('fs');
25
26const supportedModules = new SafeSet(new SafeArrayIterator([
27  // '_http_agent',
28  // '_http_client',
29  // '_http_common',
30  // '_http_incoming',
31  // '_http_outgoing',
32  // '_http_server',
33  '_stream_duplex',
34  '_stream_passthrough',
35  '_stream_readable',
36  '_stream_transform',
37  '_stream_wrap',
38  '_stream_writable',
39  // '_tls_common',
40  // '_tls_wrap',
41  'assert',
42  'assert/strict',
43  // 'async_hooks',
44  'buffer',
45  // 'child_process',
46  // 'cluster',
47  'console',
48  'constants',
49  'crypto',
50  // 'dgram',
51  // 'diagnostics_channel',
52  'dns',
53  // 'dns/promises',
54  // 'domain',
55  'events',
56  'fs',
57  'fs/promises',
58  // 'http',
59  // 'http2',
60  // 'https',
61  // 'inspector',
62  // 'module',
63  // 'net',
64  'os',
65  'path',
66  'path/posix',
67  'path/win32',
68  // 'perf_hooks',
69  'process',
70  'punycode',
71  'querystring',
72  // 'readline',
73  // 'repl',
74  'stream',
75  'stream/promises',
76  'string_decoder',
77  'sys',
78  'timers',
79  'timers/promises',
80  // 'tls',
81  // 'trace_events',
82  // 'tty',
83  'url',
84  'util',
85  'util/types',
86  'v8',
87  // 'vm',
88  // 'worker_threads',
89  'zlib',
90]));
91
92const warnedModules = new SafeSet();
93function supportedInUserSnapshot(id) {
94  return supportedModules.has(id);
95}
96
97function requireForUserSnapshot(id) {
98  const normalizedId = normalizeRequirableId(id);
99  if (!normalizedId) {
100    // eslint-disable-next-line no-restricted-syntax
101    const err = new Error(
102      `Cannot find module '${id}'. `,
103    );
104    err.code = 'MODULE_NOT_FOUND';
105    throw err;
106  }
107  if (!supportedInUserSnapshot(normalizedId)) {
108    if (!warnedModules.has(normalizedId)) {
109      process.emitWarning(
110        `built-in module ${id} is not yet supported in user snapshots`);
111      warnedModules.add(normalizedId);
112    }
113  }
114
115  return require(normalizedId);
116}
117
118function main() {
119  const {
120    prepareMainThreadExecution,
121  } = require('internal/process/pre_execution');
122
123  prepareMainThreadExecution(true, false);
124
125  const file = process.argv[1];
126  const path = require('path');
127  const filename = path.resolve(file);
128  const dirname = path.dirname(filename);
129  const source = readFileSync(file, 'utf-8');
130  const serializeMainFunction = compileSerializeMain(filename, source);
131
132  const {
133    initializeCallbacks,
134    namespace: {
135      addSerializeCallback,
136      addDeserializeCallback,
137    },
138  } = require('internal/v8/startup_snapshot');
139  initializeCallbacks();
140
141  let stackTraceLimitDesc;
142  addDeserializeCallback(() => {
143    if (stackTraceLimitDesc !== undefined) {
144      ObjectDefineProperty(Error, 'stackTraceLimit', stackTraceLimitDesc);
145    }
146  });
147
148  if (getOptionValue('--inspect-brk')) {
149    internalBinding('inspector').callAndPauseOnStart(
150      serializeMainFunction, undefined,
151      requireForUserSnapshot, filename, dirname);
152  } else {
153    serializeMainFunction(requireForUserSnapshot, filename, dirname);
154  }
155
156  addSerializeCallback(() => {
157    stackTraceLimitDesc = ObjectGetOwnPropertyDescriptor(Error, 'stackTraceLimit');
158
159    if (stackTraceLimitDesc !== undefined) {
160      // We want to use null-prototype objects to not rely on globally mutable
161      // %Object.prototype%.
162      ObjectSetPrototypeOf(stackTraceLimitDesc, null);
163      process._rawDebug('Deleting Error.stackTraceLimit from the snapshot. ' +
164                        'It will be re-installed after deserialization');
165      delete Error.stackTraceLimit;
166    }
167  });
168}
169
170main();
171