Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9b16e15

Browse filesBrowse files
vdeturckheimMylesBorins
authored andcommitted
domain: re-implement domain over async_hook
Domain core module has been re-implemented over async_hook. PR-URL: #16222 Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 60423f5 commit 9b16e15
Copy full SHA for 9b16e15

File tree

Expand file treeCollapse file tree

9 files changed

+49
-228
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

9 files changed

+49
-228
lines changed
Open diff view settings
Collapse file

‎lib/domain.js‎

Copy file name to clipboardExpand all lines: lib/domain.js
+44-16Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
const util = require('util');
3030
const EventEmitter = require('events');
31-
const { inherits } = util;
31+
const { createHook } = require('async_hooks');
3232

3333
// communicate with events module, but don't require that
3434
// module to have to load this one, since this module has
@@ -48,13 +48,54 @@ Object.defineProperty(process, 'domain', {
4848
}
4949
});
5050

51+
const pairing = new Map();
52+
const asyncHook = createHook({
53+
init(asyncId, type, triggerAsyncId, resource) {
54+
if (process.domain !== null && process.domain !== undefined) {
55+
// if this operation is created while in a domain, let's mark it
56+
pairing.set(asyncId, process.domain);
57+
resource.domain = process.domain;
58+
if (resource.promise !== undefined &&
59+
resource.promise instanceof Promise) {
60+
// resource.promise instanceof Promise make sure that the
61+
// promise comes from the same context
62+
// see https://github.com/nodejs/node/issues/15673
63+
resource.promise.domain = process.domain;
64+
}
65+
}
66+
},
67+
before(asyncId) {
68+
const current = pairing.get(asyncId);
69+
if (current !== undefined) { // enter domain for this cb
70+
current.enter();
71+
}
72+
},
73+
after(asyncId) {
74+
const current = pairing.get(asyncId);
75+
if (current !== undefined) { // exit domain for this cb
76+
current.exit();
77+
}
78+
},
79+
destroy(asyncId) {
80+
pairing.delete(asyncId); // cleaning up
81+
}
82+
});
83+
5184
// It's possible to enter one domain while already inside
5285
// another one. The stack is each entered domain.
5386
const stack = [];
5487
exports._stack = stack;
88+
process._setupDomainUse(stack);
89+
90+
class Domain extends EventEmitter {
5591

56-
// let the process know we're using domains
57-
const _domain_flag = process._setupDomainUse(_domain, stack);
92+
constructor() {
93+
super();
94+
95+
this.members = [];
96+
asyncHook.enable();
97+
}
98+
}
5899

59100
exports.Domain = Domain;
60101

@@ -64,19 +105,8 @@ exports.create = exports.createDomain = function() {
64105

65106
// the active domain is always the one that we're currently in.
66107
exports.active = null;
67-
68-
69-
inherits(Domain, EventEmitter);
70-
71-
function Domain() {
72-
EventEmitter.call(this);
73-
74-
this.members = [];
75-
}
76-
77108
Domain.prototype.members = undefined;
78109

79-
80110
// Called by process._fatalException in case an error was thrown.
81111
Domain.prototype._errorHandler = function _errorHandler(er) {
82112
var caught = false;
@@ -155,7 +185,6 @@ Domain.prototype.enter = function() {
155185
// to push it onto the stack so that we can pop it later.
156186
exports.active = process.domain = this;
157187
stack.push(this);
158-
_domain_flag[0] = stack.length;
159188
};
160189

161190

@@ -166,7 +195,6 @@ Domain.prototype.exit = function() {
166195

167196
// exit all domains until this one.
168197
stack.splice(index);
169-
_domain_flag[0] = stack.length;
170198

171199
exports.active = stack[stack.length - 1];
172200
process.domain = exports.active;
Collapse file

‎lib/internal/process/next_tick.js‎

Copy file name to clipboardExpand all lines: lib/internal/process/next_tick.js
-41Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ function setupNextTick() {
7373
process.nextTick = nextTick;
7474
// Needs to be accessible from beyond this scope.
7575
process._tickCallback = _tickCallback;
76-
process._tickDomainCallback = _tickDomainCallback;
7776

7877
// Set the nextTick() function for internal usage.
7978
exports.nextTick = internalNextTick;
@@ -190,46 +189,6 @@ function setupNextTick() {
190189
} while (tickInfo[kLength] !== 0);
191190
}
192191

193-
function _tickDomainCallback() {
194-
do {
195-
while (tickInfo[kIndex] < tickInfo[kLength]) {
196-
++tickInfo[kIndex];
197-
const tock = nextTickQueue.shift();
198-
const callback = tock.callback;
199-
const domain = tock.domain;
200-
const args = tock.args;
201-
if (domain)
202-
domain.enter();
203-
204-
// CHECK(Number.isSafeInteger(tock[async_id_symbol]))
205-
// CHECK(tock[async_id_symbol] > 0)
206-
// CHECK(Number.isSafeInteger(tock[trigger_async_id_symbol]))
207-
// CHECK(tock[trigger_async_id_symbol] > 0)
208-
209-
emitBefore(tock[async_id_symbol], tock[trigger_async_id_symbol]);
210-
// TODO(trevnorris): See comment in _tickCallback() as to why this
211-
// isn't a good solution.
212-
if (async_hook_fields[kDestroy] > 0)
213-
emitDestroy(tock[async_id_symbol]);
214-
215-
// Using separate callback execution functions allows direct
216-
// callback invocation with small numbers of arguments to avoid the
217-
// performance hit associated with using `fn.apply()`
218-
_combinedTickCallback(args, callback);
219-
220-
emitAfter(tock[async_id_symbol]);
221-
222-
if (kMaxCallbacksPerLoop < tickInfo[kIndex])
223-
tickDone();
224-
if (domain)
225-
domain.exit();
226-
}
227-
tickDone();
228-
_runMicrotasks();
229-
emitPendingUnhandledRejections();
230-
} while (tickInfo[kLength] !== 0);
231-
}
232-
233192
class TickObject {
234193
constructor(callback, args, asyncId, triggerAsyncId) {
235194
this.callback = callback;
Collapse file

‎src/cares_wrap.cc‎

Copy file name to clipboardExpand all lines: src/cares_wrap.cc
-6Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -596,12 +596,6 @@ class QueryWrap : public AsyncWrap {
596596
QueryWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
597597
: AsyncWrap(channel->env(), req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP),
598598
channel_(channel) {
599-
if (env()->in_domain()) {
600-
req_wrap_obj->Set(env()->domain_string(),
601-
env()->domain_array()->Get(env()->context(), 0)
602-
.ToLocalChecked());
603-
}
604-
605599
Wrap(req_wrap_obj, this);
606600

607601
// Make sure the channel object stays alive during the query lifetime.
Collapse file

‎src/env-inl.h‎

Copy file name to clipboardExpand all lines: src/env-inl.h
-26Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -200,22 +200,6 @@ inline bool Environment::AsyncCallbackScope::in_makecallback() const {
200200
return env_->makecallback_cntr_ > 1;
201201
}
202202

203-
inline Environment::DomainFlag::DomainFlag() {
204-
for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0;
205-
}
206-
207-
inline uint32_t* Environment::DomainFlag::fields() {
208-
return fields_;
209-
}
210-
211-
inline int Environment::DomainFlag::fields_count() const {
212-
return kFieldsCount;
213-
}
214-
215-
inline uint32_t Environment::DomainFlag::count() const {
216-
return fields_[kCount];
217-
}
218-
219203
inline Environment::TickInfo::TickInfo() {
220204
for (int i = 0; i < kFieldsCount; ++i)
221205
fields_[i] = 0;
@@ -347,12 +331,6 @@ inline v8::Isolate* Environment::isolate() const {
347331
return isolate_;
348332
}
349333

350-
inline bool Environment::in_domain() const {
351-
// The const_cast is okay, it doesn't violate conceptual const-ness.
352-
return using_domains() &&
353-
const_cast<Environment*>(this)->domain_flag()->count() > 0;
354-
}
355-
356334
inline Environment* Environment::from_immediate_check_handle(
357335
uv_check_t* handle) {
358336
return ContainerOf(&Environment::immediate_check_handle_, handle);
@@ -393,10 +371,6 @@ inline Environment::AsyncHooks* Environment::async_hooks() {
393371
return &async_hooks_;
394372
}
395373

396-
inline Environment::DomainFlag* Environment::domain_flag() {
397-
return &domain_flag_;
398-
}
399-
400374
inline Environment::TickInfo* Environment::tick_info() {
401375
return &tick_info_;
402376
}
Collapse file

‎src/env.h‎

Copy file name to clipboardExpand all lines: src/env.h
-24Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,6 @@ class ModuleWrap;
309309
V(internal_binding_cache_object, v8::Object) \
310310
V(buffer_prototype_object, v8::Object) \
311311
V(context, v8::Context) \
312-
V(domain_array, v8::Array) \
313312
V(domains_stack_array, v8::Array) \
314313
V(http2ping_constructor_template, v8::ObjectTemplate) \
315314
V(http2stream_constructor_template, v8::ObjectTemplate) \
@@ -474,26 +473,6 @@ class Environment {
474473
DISALLOW_COPY_AND_ASSIGN(AsyncCallbackScope);
475474
};
476475

477-
class DomainFlag {
478-
public:
479-
inline uint32_t* fields();
480-
inline int fields_count() const;
481-
inline uint32_t count() const;
482-
483-
private:
484-
friend class Environment; // So we can call the constructor.
485-
inline DomainFlag();
486-
487-
enum Fields {
488-
kCount,
489-
kFieldsCount
490-
};
491-
492-
uint32_t fields_[kFieldsCount];
493-
494-
DISALLOW_COPY_AND_ASSIGN(DomainFlag);
495-
};
496-
497476
class TickInfo {
498477
public:
499478
inline uint32_t* fields();
@@ -562,7 +541,6 @@ class Environment {
562541

563542
inline v8::Isolate* isolate() const;
564543
inline uv_loop_t* event_loop() const;
565-
inline bool in_domain() const;
566544
inline uint32_t watched_providers() const;
567545

568546
static inline Environment* from_immediate_check_handle(uv_check_t* handle);
@@ -579,7 +557,6 @@ class Environment {
579557
inline void FinishHandleCleanup(uv_handle_t* handle);
580558

581559
inline AsyncHooks* async_hooks();
582-
inline DomainFlag* domain_flag();
583560
inline TickInfo* tick_info();
584561
inline uint64_t timer_base() const;
585562

@@ -709,7 +686,6 @@ class Environment {
709686
uv_check_t idle_check_handle_;
710687

711688
AsyncHooks async_hooks_;
712-
DomainFlag domain_flag_;
713689
TickInfo tick_info_;
714690
const uint64_t timer_base_;
715691
bool using_domains_;
Collapse file

‎src/node.cc‎

Copy file name to clipboardExpand all lines: src/node.cc
+5-60Lines changed: 5 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ using v8::Number;
150150
using v8::Object;
151151
using v8::ObjectTemplate;
152152
using v8::Promise;
153-
using v8::PromiseHookType;
154153
using v8::PromiseRejectMessage;
155154
using v8::PropertyCallbackInfo;
156155
using v8::ScriptOrigin;
@@ -1178,7 +1177,6 @@ bool ShouldAbortOnUncaughtException(Isolate* isolate) {
11781177
return isEmittingTopLevelDomainError || !DomainsStackHasErrorHandler(env);
11791178
}
11801179

1181-
11821180
Local<Value> GetDomainProperty(Environment* env, Local<Object> object) {
11831181
Local<Value> domain_v =
11841182
object->GetPrivate(env->context(), env->domain_private_symbol())
@@ -1219,36 +1217,6 @@ void DomainExit(Environment* env, v8::Local<v8::Object> object) {
12191217
}
12201218
}
12211219

1222-
1223-
void DomainPromiseHook(PromiseHookType type,
1224-
Local<Promise> promise,
1225-
Local<Value> parent,
1226-
void* arg) {
1227-
Environment* env = static_cast<Environment*>(arg);
1228-
Local<Context> context = env->context();
1229-
1230-
if (type == PromiseHookType::kInit && env->in_domain()) {
1231-
Local<Value> domain_obj =
1232-
env->domain_array()->Get(context, 0).ToLocalChecked();
1233-
if (promise->CreationContext() == context) {
1234-
promise->Set(context, env->domain_string(), domain_obj).FromJust();
1235-
} else {
1236-
// Do not expose object from another context publicly in promises created
1237-
// in non-main contexts.
1238-
promise->SetPrivate(context, env->domain_private_symbol(), domain_obj)
1239-
.FromJust();
1240-
}
1241-
return;
1242-
}
1243-
1244-
if (type == PromiseHookType::kBefore) {
1245-
DomainEnter(env, promise);
1246-
} else if (type == PromiseHookType::kAfter) {
1247-
DomainExit(env, promise);
1248-
}
1249-
}
1250-
1251-
12521220
void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
12531221
Environment* env = Environment::GetCurrent(args);
12541222

@@ -1259,38 +1227,13 @@ void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
12591227
HandleScope scope(env->isolate());
12601228
Local<Object> process_object = env->process_object();
12611229

1262-
Local<String> tick_callback_function_key = env->tick_domain_cb_string();
1263-
Local<Function> tick_callback_function =
1264-
process_object->Get(tick_callback_function_key).As<Function>();
1265-
1266-
if (!tick_callback_function->IsFunction()) {
1267-
fprintf(stderr, "process._tickDomainCallback assigned to non-function\n");
1268-
ABORT();
1269-
}
1270-
1271-
process_object->Set(env->tick_callback_string(), tick_callback_function);
1272-
env->set_tick_callback_function(tick_callback_function);
1273-
12741230
CHECK(args[0]->IsArray());
1275-
env->set_domain_array(args[0].As<Array>());
1276-
1277-
CHECK(args[1]->IsArray());
1278-
env->set_domains_stack_array(args[1].As<Array>());
1231+
env->set_domains_stack_array(args[0].As<Array>());
12791232

12801233
// Do a little housekeeping.
12811234
env->process_object()->Delete(
12821235
env->context(),
12831236
FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupDomainUse")).FromJust();
1284-
1285-
uint32_t* const fields = env->domain_flag()->fields();
1286-
uint32_t const fields_count = env->domain_flag()->fields_count();
1287-
1288-
Local<ArrayBuffer> array_buffer =
1289-
ArrayBuffer::New(env->isolate(), fields, sizeof(*fields) * fields_count);
1290-
1291-
env->AddPromiseHook(DomainPromiseHook, static_cast<void*>(env));
1292-
1293-
args.GetReturnValue().Set(Uint32Array::New(array_buffer, 0, fields_count));
12941237
}
12951238

12961239

@@ -1414,7 +1357,8 @@ InternalCallbackScope::InternalCallbackScope(Environment* env,
14141357
// If you hit this assertion, you forgot to enter the v8::Context first.
14151358
CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
14161359

1417-
if (env->using_domains() && !object_.IsEmpty()) {
1360+
if (asyncContext.async_id == 0 && env->using_domains() &&
1361+
!object_.IsEmpty()) {
14181362
DomainEnter(env, object_);
14191363
}
14201364

@@ -1447,7 +1391,8 @@ void InternalCallbackScope::Close() {
14471391
AsyncWrap::EmitAfter(env_, async_context_.async_id);
14481392
}
14491393

1450-
if (env_->using_domains() && !object_.IsEmpty()) {
1394+
if (async_context_.async_id == 0 && env_->using_domains() &&
1395+
!object_.IsEmpty()) {
14511396
DomainExit(env_, object_);
14521397
}
14531398

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.