• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const {
4  validateFunction,
5} = require('internal/validators');
6const {
7  codes: {
8    ERR_NOT_BUILDING_SNAPSHOT,
9    ERR_DUPLICATE_STARTUP_SNAPSHOT_MAIN_FUNCTION,
10  },
11} = require('internal/errors');
12
13const {
14  setSerializeCallback,
15  setDeserializeCallback,
16  setDeserializeMainFunction: _setDeserializeMainFunction,
17} = internalBinding('mksnapshot');
18
19function isBuildingSnapshot() {
20  // For now this is the only way to build a snapshot.
21  return require('internal/options').getOptionValue('--build-snapshot');
22}
23
24function throwIfNotBuildingSnapshot() {
25  if (!isBuildingSnapshot()) {
26    throw new ERR_NOT_BUILDING_SNAPSHOT();
27  }
28}
29
30const deserializeCallbacks = [];
31let deserializeCallbackIsSet = false;
32function runDeserializeCallbacks() {
33  while (deserializeCallbacks.length > 0) {
34    const { 0: callback, 1: data } = deserializeCallbacks.shift();
35    callback(data);
36  }
37}
38
39function addDeserializeCallback(callback, data) {
40  throwIfNotBuildingSnapshot();
41  validateFunction(callback, 'callback');
42  if (!deserializeCallbackIsSet) {
43    // TODO(joyeecheung): when the main function handling is done in JS,
44    // the deserialize callbacks can always be invoked. For now only
45    // store it in C++ when it's actually used to avoid unnecessary
46    // C++ -> JS costs.
47    setDeserializeCallback(runDeserializeCallbacks);
48    deserializeCallbackIsSet = true;
49  }
50  deserializeCallbacks.push([callback, data]);
51}
52
53const serializeCallbacks = [];
54function runSerializeCallbacks() {
55  while (serializeCallbacks.length > 0) {
56    const { 0: callback, 1: data } = serializeCallbacks.shift();
57    callback(data);
58  }
59}
60
61function addSerializeCallback(callback, data) {
62  throwIfNotBuildingSnapshot();
63  validateFunction(callback, 'callback');
64  serializeCallbacks.push([callback, data]);
65}
66
67function initializeCallbacks() {
68  // Only run the serialize callbacks in snapshot building mode, otherwise
69  // they throw.
70  if (isBuildingSnapshot()) {
71    setSerializeCallback(runSerializeCallbacks);
72  }
73}
74
75let deserializeMainIsSet = false;
76function setDeserializeMainFunction(callback, data) {
77  throwIfNotBuildingSnapshot();
78  // TODO(joyeecheung): In lib/internal/bootstrap/node.js, create a default
79  // main function to run the lib/internal/main scripts and make sure that
80  // the main function set in the snapshot building process takes precedence.
81  validateFunction(callback, 'callback');
82  if (deserializeMainIsSet) {
83    throw new ERR_DUPLICATE_STARTUP_SNAPSHOT_MAIN_FUNCTION();
84  }
85  deserializeMainIsSet = true;
86
87  _setDeserializeMainFunction(function deserializeMain() {
88    const {
89      prepareMainThreadExecution,
90      markBootstrapComplete,
91    } = require('internal/process/pre_execution');
92
93    // This should be in sync with run_main_module.js until we make that
94    // a built-in main function.
95    // TODO(joyeecheung): make a copy of argv[0] and insert it as argv[1].
96    prepareMainThreadExecution(false);
97    markBootstrapComplete();
98    callback(data);
99  });
100}
101
102module.exports = {
103  initializeCallbacks,
104  runDeserializeCallbacks,
105  // Exposed to require('v8').startupSnapshot
106  namespace: {
107    addDeserializeCallback,
108    addSerializeCallback,
109    setDeserializeMainFunction,
110    isBuildingSnapshot,
111  },
112};
113