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