| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 733af61 commit 8abcc76
13 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,13 +14,9 @@ | |||
| 14 | 14 | ||
| 15 | 15 | // This file is compiled as if it's wrapped in a function with arguments | |
| 16 | 16 | // passed by node::LoadEnvironment() | |
| 17 | - /* global process, bootstrappers, loaderExports, triggerFatalException */ | ||
| 17 | + /* global process, loaderExports, triggerFatalException */ | ||
| 18 | 18 | /* global isMainThread */ | |
| 19 | 19 | ||
| 20 | - const { | ||
| 21 | - _setupNextTick, | ||
| 22 | - _setupPromises | ||
| 23 | - } = bootstrappers; | ||
| 24 | 20 | const { internalBinding, NativeModule } = loaderExports; | |
| 25 | 21 | ||
| 26 | 22 | const exceptionHandlerState = { captureFn: null }; | |
@@ -105,8 +101,18 @@ function startup() { | |||
| 105 | 101 | } | |
| 106 | 102 | ||
| 107 | 103 | NativeModule.require('internal/process/warning').setup(); | |
| 108 | - NativeModule.require('internal/process/next_tick').setup(_setupNextTick, | ||
| 109 | - _setupPromises); | ||
| 104 | + const { | ||
| 105 | + nextTick, | ||
| 106 | + runNextTicks | ||
| 107 | + } = NativeModule.require('internal/process/next_tick').setup(); | ||
| 108 | + | ||
| 109 | + process.nextTick = nextTick; | ||
| 110 | + // Used to emulate a tick manually in the JS land. | ||
| 111 | + // A better name for this function would be `runNextTicks` but | ||
| 112 | + // it has been exposed to the process object so we keep this legacy name | ||
| 113 | + // TODO(joyeecheung): either remove it or make it public | ||
| 114 | + process._tickCallback = runNextTicks; | ||
| 115 | + | ||
| 110 | 116 | const credentials = internalBinding('credentials'); | |
| 111 | 117 | if (credentials.implementsPosixCredentials) { | |
| 112 | 118 | process.getuid = credentials.getuid; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,128 +1,138 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | - exports.setup = setupNextTick; | ||
| 4 | - | ||
| 5 | - function setupNextTick(_setupNextTick, _setupPromises) { | ||
| 6 | - const { | ||
| 7 | - getDefaultTriggerAsyncId, | ||
| 8 | - newAsyncId, | ||
| 9 | - initHooksExist, | ||
| 10 | - destroyHooksExist, | ||
| 11 | - emitInit, | ||
| 12 | - emitBefore, | ||
| 13 | - emitAfter, | ||
| 14 | - emitDestroy, | ||
| 15 | - symbols: { async_id_symbol, trigger_async_id_symbol } | ||
| 16 | - } = require('internal/async_hooks'); | ||
| 17 | - const emitPromiseRejectionWarnings = | ||
| 18 | - require('internal/process/promises').setup(_setupPromises); | ||
| 19 | - const { ERR_INVALID_CALLBACK } = require('internal/errors').codes; | ||
| 20 | - const FixedQueue = require('internal/fixed_queue'); | ||
| 21 | - | ||
| 22 | - // tickInfo is used so that the C++ code in src/node.cc can | ||
| 23 | - // have easy access to our nextTick state, and avoid unnecessary | ||
| 24 | - // calls into JS land. | ||
| 25 | - // runMicrotasks is used to run V8's micro task queue. | ||
| 26 | - const [ | ||
| 27 | - tickInfo, | ||
| 28 | - runMicrotasks | ||
| 29 | - ] = _setupNextTick(internalTickCallback); | ||
| 30 | - | ||
| 31 | - // *Must* match Environment::TickInfo::Fields in src/env.h. | ||
| 32 | - const kHasScheduled = 0; | ||
| 33 | - const kHasPromiseRejections = 1; | ||
| 34 | - | ||
| 35 | - const queue = new FixedQueue(); | ||
| 36 | - | ||
| 37 | - process.nextTick = nextTick; | ||
| 38 | - // Needs to be accessible from beyond this scope. | ||
| 39 | - process._tickCallback = _tickCallback; | ||
| 40 | - | ||
| 41 | - function _tickCallback() { | ||
| 42 | - if (tickInfo[kHasScheduled] === 0 && tickInfo[kHasPromiseRejections] === 0) | ||
| 43 | - runMicrotasks(); | ||
| 44 | - if (tickInfo[kHasScheduled] === 0 && tickInfo[kHasPromiseRejections] === 0) | ||
| 45 | - return; | ||
| 46 | - | ||
| 47 | - internalTickCallback(); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - function internalTickCallback() { | ||
| 51 | - let tock; | ||
| 52 | - do { | ||
| 53 | - while (tock = queue.shift()) { | ||
| 54 | - const asyncId = tock[async_id_symbol]; | ||
| 55 | - emitBefore(asyncId, tock[trigger_async_id_symbol]); | ||
| 56 | - // emitDestroy() places the async_id_symbol into an asynchronous queue | ||
| 57 | - // that calls the destroy callback in the future. It's called before | ||
| 58 | - // calling tock.callback so destroy will be called even if the callback | ||
| 59 | - // throws an exception that is handled by 'uncaughtException' or a | ||
| 60 | - // domain. | ||
| 61 | - // TODO(trevnorris): This is a bit of a hack. It relies on the fact | ||
| 62 | - // that nextTick() doesn't allow the event loop to proceed, but if | ||
| 63 | - // any async hooks are enabled during the callback's execution then | ||
| 64 | - // this tock's after hook will be called, but not its destroy hook. | ||
| 65 | - if (destroyHooksExist()) | ||
| 66 | - emitDestroy(asyncId); | ||
| 67 | - | ||
| 68 | - const callback = tock.callback; | ||
| 69 | - if (tock.args === undefined) | ||
| 70 | - callback(); | ||
| 71 | - else | ||
| 72 | - Reflect.apply(callback, undefined, tock.args); | ||
| 73 | - | ||
| 74 | - emitAfter(asyncId); | ||
| 75 | - } | ||
| 76 | - tickInfo[kHasScheduled] = 0; | ||
| 77 | - runMicrotasks(); | ||
| 78 | - } while (!queue.isEmpty() || emitPromiseRejectionWarnings()); | ||
| 79 | - tickInfo[kHasPromiseRejections] = 0; | ||
| 80 | - } | ||
| 3 | + const { | ||
| 4 | + // For easy access to the nextTick state in the C++ land, | ||
| 5 | + // and to avoid unnecessary calls into JS land. | ||
| 6 | + tickInfo, | ||
| 7 | + // Used to run V8's micro task queue. | ||
| 8 | + runMicrotasks, | ||
| 9 | + setTickCallback, | ||
| 10 | + initializePromiseRejectCallback | ||
| 11 | + } = internalBinding('task_queue'); | ||
| 12 | + | ||
| 13 | + const { | ||
| 14 | + promiseRejectHandler, | ||
| 15 | + emitPromiseRejectionWarnings | ||
| 16 | + } = require('internal/process/promises'); | ||
| 17 | + | ||
| 18 | + const { | ||
| 19 | + getDefaultTriggerAsyncId, | ||
| 20 | + newAsyncId, | ||
| 21 | + initHooksExist, | ||
| 22 | + destroyHooksExist, | ||
| 23 | + emitInit, | ||
| 24 | + emitBefore, | ||
| 25 | + emitAfter, | ||
| 26 | + emitDestroy, | ||
| 27 | + symbols: { async_id_symbol, trigger_async_id_symbol } | ||
| 28 | + } = require('internal/async_hooks'); | ||
| 29 | + const { ERR_INVALID_CALLBACK } = require('internal/errors').codes; | ||
| 30 | + const FixedQueue = require('internal/fixed_queue'); | ||
| 31 | + | ||
| 32 | + // *Must* match Environment::TickInfo::Fields in src/env.h. | ||
| 33 | + const kHasScheduled = 0; | ||
| 34 | + const kHasPromiseRejections = 1; | ||
| 35 | + | ||
| 36 | + const queue = new FixedQueue(); | ||
| 37 | + | ||
| 38 | + function runNextTicks() { | ||
| 39 | + if (tickInfo[kHasScheduled] === 0 && tickInfo[kHasPromiseRejections] === 0) | ||
| 40 | + runMicrotasks(); | ||
| 41 | + if (tickInfo[kHasScheduled] === 0 && tickInfo[kHasPromiseRejections] === 0) | ||
| 42 | + return; | ||
| 43 | + | ||
| 44 | + internalTickCallback(); | ||
| 45 | + } | ||
| 81 | 46 | ||
| 82 | - class TickObject { | ||
| 83 | - constructor(callback, args, triggerAsyncId) { | ||
| 84 | - // This must be set to null first to avoid function tracking | ||
| 85 | - // on the hidden class, revisit in V8 versions after 6.2 | ||
| 86 | - this.callback = null; | ||
| 87 | - this.callback = callback; | ||
| 88 | - this.args = args; | ||
| 89 | - | ||
| 90 | - const asyncId = newAsyncId(); | ||
| 91 | - this[async_id_symbol] = asyncId; | ||
| 92 | - this[trigger_async_id_symbol] = triggerAsyncId; | ||
| 93 | - | ||
| 94 | - if (initHooksExist()) { | ||
| 95 | - emitInit(asyncId, | ||
| 96 | - 'TickObject', | ||
| 97 | - triggerAsyncId, | ||
| 98 | - this); | ||
| 99 | - } | ||
| 47 | + function internalTickCallback() { | ||
| 48 | + let tock; | ||
| 49 | + do { | ||
| 50 | + while (tock = queue.shift()) { | ||
| 51 | + const asyncId = tock[async_id_symbol]; | ||
| 52 | + emitBefore(asyncId, tock[trigger_async_id_symbol]); | ||
| 53 | + // emitDestroy() places the async_id_symbol into an asynchronous queue | ||
| 54 | + // that calls the destroy callback in the future. It's called before | ||
| 55 | + // calling tock.callback so destroy will be called even if the callback | ||
| 56 | + // throws an exception that is handled by 'uncaughtException' or a | ||
| 57 | + // domain. | ||
| 58 | + // TODO(trevnorris): This is a bit of a hack. It relies on the fact | ||
| 59 | + // that nextTick() doesn't allow the event loop to proceed, but if | ||
| 60 | + // any async hooks are enabled during the callback's execution then | ||
| 61 | + // this tock's after hook will be called, but not its destroy hook. | ||
| 62 | + if (destroyHooksExist()) | ||
| 63 | + emitDestroy(asyncId); | ||
| 64 | + | ||
| 65 | + const callback = tock.callback; | ||
| 66 | + if (tock.args === undefined) | ||
| 67 | + callback(); | ||
| 68 | + else | ||
| 69 | + Reflect.apply(callback, undefined, tock.args); | ||
| 70 | + | ||
| 71 | + emitAfter(asyncId); | ||
| 100 | 72 | } | |
| 101 | - } | ||
| 73 | + tickInfo[kHasScheduled] = 0; | ||
| 74 | + runMicrotasks(); | ||
| 75 | + } while (!queue.isEmpty() || emitPromiseRejectionWarnings()); | ||
| 76 | + tickInfo[kHasPromiseRejections] = 0; | ||
| 77 | + } | ||
| 102 | 78 | ||
| 103 | - // `nextTick()` will not enqueue any callback when the process is about to | ||
| 104 | - // exit since the callback would not have a chance to be executed. | ||
| 105 | - function nextTick(callback) { | ||
| 106 | - if (typeof callback !== 'function') | ||
| 107 | - throw new ERR_INVALID_CALLBACK(); | ||
| 108 | - | ||
| 109 | - if (process._exiting) | ||
| 110 | - return; | ||
| 111 | - | ||
| 112 | - var args; | ||
| 113 | - switch (arguments.length) { | ||
| 114 | - case 1: break; | ||
| 115 | - case 2: args = [arguments[1]]; break; | ||
| 116 | - case 3: args = [arguments[1], arguments[2]]; break; | ||
| 117 | - case 4: args = [arguments[1], arguments[2], arguments[3]]; break; | ||
| 118 | - default: | ||
| 119 | - args = new Array(arguments.length - 1); | ||
| 120 | - for (var i = 1; i < arguments.length; i++) | ||
| 121 | - args[i - 1] = arguments[i]; | ||
| 79 | + class TickObject { | ||
| 80 | + constructor(callback, args, triggerAsyncId) { | ||
| 81 | + // This must be set to null first to avoid function tracking | ||
| 82 | + // on the hidden class, revisit in V8 versions after 6.2 | ||
| 83 | + this.callback = null; | ||
| 84 | + this.callback = callback; | ||
| 85 | + this.args = args; | ||
| 86 | + | ||
| 87 | + const asyncId = newAsyncId(); | ||
| 88 | + this[async_id_symbol] = asyncId; | ||
| 89 | + this[trigger_async_id_symbol] = triggerAsyncId; | ||
| 90 | + | ||
| 91 | + if (initHooksExist()) { | ||
| 92 | + emitInit(asyncId, | ||
| 93 | + 'TickObject', | ||
| 94 | + triggerAsyncId, | ||
| 95 | + this); | ||
| 122 | 96 | } | |
| 97 | + } | ||
| 98 | + } | ||
| 123 | 99 | ||
| 124 | - if (queue.isEmpty()) | ||
| 125 | - tickInfo[kHasScheduled] = 1; | ||
| 126 | - queue.push(new TickObject(callback, args, getDefaultTriggerAsyncId())); | ||
| 100 | + // `nextTick()` will not enqueue any callback when the process is about to | ||
| 101 | + // exit since the callback would not have a chance to be executed. | ||
| 102 | + function nextTick(callback) { | ||
| 103 | + if (typeof callback !== 'function') | ||
| 104 | + throw new ERR_INVALID_CALLBACK(); | ||
| 105 | + | ||
| 106 | + if (process._exiting) | ||
| 107 | + return; | ||
| 108 | + | ||
| 109 | + var args; | ||
| 110 | + switch (arguments.length) { | ||
| 111 | + case 1: break; | ||
| 112 | + case 2: args = [arguments[1]]; break; | ||
| 113 | + case 3: args = [arguments[1], arguments[2]]; break; | ||
| 114 | + case 4: args = [arguments[1], arguments[2], arguments[3]]; break; | ||
| 115 | + default: | ||
| 116 | + args = new Array(arguments.length - 1); | ||
| 117 | + for (var i = 1; i < arguments.length; i++) | ||
| 118 | + args[i - 1] = arguments[i]; | ||
| 127 | 119 | } | |
| 120 | + | ||
| 121 | + if (queue.isEmpty()) | ||
| 122 | + tickInfo[kHasScheduled] = 1; | ||
| 123 | + queue.push(new TickObject(callback, args, getDefaultTriggerAsyncId())); | ||
| 128 | 124 | } | |
| 125 | + | ||
| 126 | + // TODO(joyeecheung): make this a factory class so that node.js can | ||
| 127 | + // control the side effects caused by the initializers. | ||
| 128 | + exports.setup = function() { | ||
| 129 | + // Initializes the per-isolate promise rejection callback which | ||
| 130 | + // will call the handler being passed into this function. | ||
| 131 | + initializePromiseRejectCallback(promiseRejectHandler); | ||
| 132 | + // Sets the callback to be run in every tick. | ||
| 133 | + setTickCallback(internalTickCallback); | ||
| 134 | + return { | ||
| 135 | + nextTick, | ||
| 136 | + runNextTicks | ||
| 137 | + }; | ||
| 138 | + }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,21 +1,16 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | 3 | const { safeToString } = internalBinding('util'); | |
| 4 | + const { | ||
| 5 | + promiseRejectEvents | ||
| 6 | + } = internalBinding('task_queue'); | ||
| 4 | 7 | ||
| 5 | 8 | const maybeUnhandledPromises = new WeakMap(); | |
| 6 | 9 | const pendingUnhandledRejections = []; | |
| 7 | 10 | const asyncHandledRejections = []; | |
| 8 | - const promiseRejectEvents = {}; | ||
| 9 | 11 | let lastPromiseId = 0; | |
| 10 | 12 | ||
| 11 | - exports.setup = setupPromises; | ||
| 12 | - | ||
| 13 | - function setupPromises(_setupPromises) { | ||
| 14 | - _setupPromises(handler, promiseRejectEvents); | ||
| 15 | - return emitPromiseRejectionWarnings; | ||
| 16 | - } | ||
| 17 | - | ||
| 18 | - function handler(type, promise, reason) { | ||
| 13 | + function promiseRejectHandler(type, promise, reason) { | ||
| 19 | 14 | switch (type) { | |
| 20 | 15 | case promiseRejectEvents.kPromiseRejectWithNoHandler: | |
| 21 | 16 | return unhandledRejection(promise, reason); | |
@@ -124,3 +119,8 @@ function emitPromiseRejectionWarnings() { | |||
| 124 | 119 | } | |
| 125 | 120 | return maybeScheduledTicks || pendingUnhandledRejections.length !== 0; | |
| 126 | 121 | } | |
| 122 | + | ||
| 123 | + module.exports = { | ||
| 124 | + promiseRejectHandler, | ||
| 125 | + emitPromiseRejectionWarnings | ||
| 126 | + }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -327,7 +327,6 @@ | |||
| 327 | 327 | ||
| 328 | 328 | 'sources': [ | |
| 329 | 329 | 'src/async_wrap.cc', | |
| 330 | - 'src/bootstrapper.cc', | ||
| 331 | 330 | 'src/callback_scope.cc', | |
| 332 | 331 | 'src/cares_wrap.cc', | |
| 333 | 332 | 'src/connect_wrap.cc', | |
@@ -374,6 +373,7 @@ | |||
| 374 | 373 | 'src/node_serdes.cc', | |
| 375 | 374 | 'src/node_stat_watcher.cc', | |
| 376 | 375 | 'src/node_symbols.cc', | |
| 376 | + 'src/node_task_queue.cc', | ||
| 377 | 377 | 'src/node_trace_events.cc', | |
| 378 | 378 | 'src/node_types.cc', | |
| 379 | 379 | 'src/node_url.cc', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -362,7 +362,7 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2; | |||
| 362 | 362 | V(performance_entry_template, v8::Function) \ | |
| 363 | 363 | V(pipe_constructor_template, v8::FunctionTemplate) \ | |
| 364 | 364 | V(process_object, v8::Object) \ | |
| 365 | - V(promise_handler_function, v8::Function) \ | ||
| 365 | + V(promise_reject_callback, v8::Function) \ | ||
| 366 | 366 | V(promise_wrap_template, v8::ObjectTemplate) \ | |
| 367 | 367 | V(sab_lifetimepartner_constructor_template, v8::FunctionTemplate) \ | |
| 368 | 368 | V(script_context_constructor_template, v8::FunctionTemplate) \ | |
@@ -377,7 +377,7 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2; | |||
| 377 | 377 | V(tty_constructor_template, v8::FunctionTemplate) \ | |
| 378 | 378 | V(udp_constructor_function, v8::Function) \ | |
| 379 | 379 | V(url_constructor_function, v8::Function) \ | |
| 380 | - V(write_wrap_template, v8::ObjectTemplate) \ | ||
| 380 | + V(write_wrap_template, v8::ObjectTemplate) | ||
| 381 | 381 | ||
| 382 | 382 | class Environment; | |
| 383 | 383 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1163,20 +1163,14 @@ void LoadEnvironment(Environment* env) { | |||
| 1163 | 1163 | return; | |
| 1164 | 1164 | } | |
| 1165 | 1165 | ||
| 1166 | - // Bootstrap Node.js | ||
| 1167 | - Local<Object> bootstrapper = Object::New(env->isolate()); | ||
| 1168 | - SetupBootstrapObject(env, bootstrapper); | ||
| 1169 | - | ||
| 1170 | 1166 | // process, bootstrappers, loaderExports, triggerFatalException | |
| 1171 | 1167 | std::vector<Local<String>> node_params = { | |
| 1172 | 1168 | env->process_string(), | |
| 1173 | - FIXED_ONE_BYTE_STRING(isolate, "bootstrappers"), | ||
| 1174 | 1169 | FIXED_ONE_BYTE_STRING(isolate, "loaderExports"), | |
| 1175 | 1170 | FIXED_ONE_BYTE_STRING(isolate, "triggerFatalException"), | |
| 1176 | 1171 | FIXED_ONE_BYTE_STRING(isolate, "isMainThread")}; | |
| 1177 | 1172 | std::vector<Local<Value>> node_args = { | |
| 1178 | 1173 | process, | |
| 1179 | - bootstrapper, | ||
| 1180 | 1174 | loader_exports.ToLocalChecked(), | |
| 1181 | 1175 | env->NewFunctionTemplate(FatalException) | |
| 1182 | 1176 | ->GetFunction(context) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -52,6 +52,7 @@ | |||
| 52 | 52 | V(stream_wrap) \ | |
| 53 | 53 | V(string_decoder) \ | |
| 54 | 54 | V(symbols) \ | |
| 55 | + V(task_queue) \ | ||
| 55 | 56 | V(tcp_wrap) \ | |
| 56 | 57 | V(timers) \ | |
| 57 | 58 | V(trace_events) \ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments