| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a5ce44d commit e5278b7
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -104,6 +104,7 @@ const before_symbol = Symbol('before'); | |||
| 104 | 104 | const after_symbol = Symbol('after'); | |
| 105 | 105 | const destroy_symbol = Symbol('destroy'); | |
| 106 | 106 | const promise_resolve_symbol = Symbol('promiseResolve'); | |
| 107 | + const async_local_storage_context_symbol = Symbol('kAsyncLocalStorageContext'); | ||
| 107 | 108 | const emitBeforeNative = emitHookFactory(before_symbol, 'emitBeforeNative'); | |
| 108 | 109 | const emitAfterNative = emitHookFactory(after_symbol, 'emitAfterNative'); | |
| 109 | 110 | const emitDestroyNative = emitHookFactory(destroy_symbol, 'emitDestroyNative'); | |
@@ -594,7 +595,8 @@ module.exports = { | |||
| 594 | 595 | symbols: { | |
| 595 | 596 | async_id_symbol, trigger_async_id_symbol, | |
| 596 | 597 | init_symbol, before_symbol, after_symbol, destroy_symbol, | |
| 597 | - promise_resolve_symbol, owner_symbol, | ||
| 598 | + promise_resolve_symbol, async_local_storage_context_symbol, | ||
| 599 | + owner_symbol, | ||
| 598 | 600 | }, | |
| 599 | 601 | constants: { | |
| 600 | 602 | kInit, kBefore, kAfter, kDestroy, kTotals, kPromiseResolve, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,6 +12,11 @@ const { | |||
| 12 | 12 | const { | |
| 13 | 13 | validateObject, | |
| 14 | 14 | } = require('internal/validators'); | |
| 15 | + const { | ||
| 16 | + symbols: { | ||
| 17 | + async_local_storage_context_symbol, | ||
| 18 | + }, | ||
| 19 | + } = require('internal/async_hooks'); | ||
| 15 | 20 | ||
| 16 | 21 | const { | |
| 17 | 22 | AsyncResource, | |
@@ -20,6 +25,11 @@ const { | |||
| 20 | 25 | } = require('async_hooks'); | |
| 21 | 26 | ||
| 22 | 27 | const storageList = []; | |
| 28 | + | ||
| 29 | + function getOrCreateResourceStore(resource) { | ||
| 30 | + return resource[async_local_storage_context_symbol] ??= { __proto__: null }; | ||
| 31 | + } | ||
| 32 | + | ||
| 23 | 33 | const storageHook = createHook({ | |
| 24 | 34 | init(asyncId, type, triggerAsyncId, resource) { | |
| 25 | 35 | const currentResource = executionAsyncResource(); | |
@@ -88,16 +98,18 @@ class AsyncLocalStorage { | |||
| 88 | 98 | ||
| 89 | 99 | // Propagate the context from a parent resource to a child one | |
| 90 | 100 | _propagate(resource, triggerResource, type) { | |
| 91 | - const store = triggerResource[this.kResourceStore]; | ||
| 101 | + const store = triggerResource[async_local_storage_context_symbol]?.[this.kResourceStore]; | ||
| 92 | 102 | if (this.enabled) { | |
| 93 | - resource[this.kResourceStore] = store; | ||
| 103 | + const resourceStore = getOrCreateResourceStore(resource); | ||
| 104 | + resourceStore[this.kResourceStore] = store; | ||
| 94 | 105 | } | |
| 95 | 106 | } | |
| 96 | 107 | ||
| 97 | 108 | enterWith(store) { | |
| 98 | 109 | this._enable(); | |
| 99 | 110 | const resource = executionAsyncResource(); | |
| 100 | - resource[this.kResourceStore] = store; | ||
| 111 | + const resourceStore = getOrCreateResourceStore(resource); | ||
| 112 | + resourceStore[this.kResourceStore] = store; | ||
| 101 | 113 | } | |
| 102 | 114 | ||
| 103 | 115 | run(store, callback, ...args) { | |
@@ -109,14 +121,15 @@ class AsyncLocalStorage { | |||
| 109 | 121 | this._enable(); | |
| 110 | 122 | ||
| 111 | 123 | const resource = executionAsyncResource(); | |
| 112 | - const oldStore = resource[this.kResourceStore]; | ||
| 124 | + const resourceStore = getOrCreateResourceStore(resource); | ||
| 125 | + const oldStore = resourceStore[this.kResourceStore]; | ||
| 113 | 126 | ||
| 114 | - resource[this.kResourceStore] = store; | ||
| 127 | + resourceStore[this.kResourceStore] = store; | ||
| 115 | 128 | ||
| 116 | 129 | try { | |
| 117 | 130 | return ReflectApply(callback, null, args); | |
| 118 | 131 | } finally { | |
| 119 | - resource[this.kResourceStore] = oldStore; | ||
| 132 | + resourceStore[this.kResourceStore] = oldStore; | ||
| 120 | 133 | } | |
| 121 | 134 | } | |
| 122 | 135 | ||
@@ -135,10 +148,11 @@ class AsyncLocalStorage { | |||
| 135 | 148 | getStore() { | |
| 136 | 149 | if (this.enabled) { | |
| 137 | 150 | const resource = executionAsyncResource(); | |
| 138 | - if (!(this.kResourceStore in resource)) { | ||
| 151 | + const resourceStore = resource[async_local_storage_context_symbol]; | ||
| 152 | + if (resourceStore === undefined || !(this.kResourceStore in resourceStore)) { | ||
| 139 | 153 | return this.#defaultValue; | |
| 140 | 154 | } | |
| 141 | - return resource[this.kResourceStore]; | ||
| 155 | + return resourceStore[this.kResourceStore]; | ||
| 142 | 156 | } | |
| 143 | 157 | return this.#defaultValue; | |
| 144 | 158 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -87,6 +87,9 @@ const { | |||
| 87 | 87 | immediateInfo, | |
| 88 | 88 | timeoutInfo, | |
| 89 | 89 | } = binding; | |
| 90 | + const { | ||
| 91 | + enqueueMicrotask, | ||
| 92 | + } = internalBinding('task_queue'); | ||
| 90 | 93 | ||
| 91 | 94 | const { | |
| 92 | 95 | getDefaultTriggerAsyncId, | |
@@ -97,6 +100,9 @@ const { | |||
| 97 | 100 | emitBefore, | |
| 98 | 101 | emitAfter, | |
| 99 | 102 | emitDestroy, | |
| 103 | + symbols: { | ||
| 104 | + async_local_storage_context_symbol, | ||
| 105 | + }, | ||
| 100 | 106 | } = require('internal/async_hooks'); | |
| 101 | 107 | ||
| 102 | 108 | // Symbols for storing async id state. | |
@@ -125,6 +131,39 @@ const AsyncContextFrame = require('internal/async_context_frame'); | |||
| 125 | 131 | ||
| 126 | 132 | const async_context_frame = Symbol('kAsyncContextFrame'); | |
| 127 | 133 | ||
| 134 | + function removeStoresFromResource(resource) { | ||
| 135 | + if (AsyncContextFrame.enabled) { | ||
| 136 | + if (resource[async_context_frame] !== undefined) { | ||
| 137 | + resource[async_context_frame] = undefined; | ||
| 138 | + } | ||
| 139 | + } else if (resource[async_local_storage_context_symbol] !== undefined) { | ||
| 140 | + resource[async_local_storage_context_symbol] = undefined; | ||
| 141 | + } | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + function cleanTimer(timer) { | ||
| 145 | + removeStoresFromResource(timer); | ||
| 146 | + timer._onTimeout = undefined; | ||
| 147 | + timer._timerArgs = undefined; | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + function cleanImmediate(immediate) { | ||
| 151 | + removeStoresFromResource(immediate); | ||
| 152 | + immediate._onImmediate = undefined; | ||
| 153 | + immediate._argv = undefined; | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + function enqueueRemoveStoresFromResource(resource) { | ||
| 157 | + enqueueMicrotask(() => removeStoresFromResource(resource)); | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + function enqueueRemoveStoresIfNotReinserted(resource) { | ||
| 161 | + enqueueMicrotask(() => { | ||
| 162 | + if (!resource._idleNext && !resource._idlePrev) | ||
| 163 | + removeStoresFromResource(resource); | ||
| 164 | + }); | ||
| 165 | + } | ||
| 166 | + | ||
| 128 | 167 | // *Must* match Environment::ImmediateInfo::Fields in src/env.h. | |
| 129 | 168 | const kCount = 0; | |
| 130 | 169 | const kRefCount = 1; | |
@@ -528,14 +567,22 @@ function getTimerCallbacks(runNextTicks) { | |||
| 528 | 567 | const asyncId = immediate[async_id_symbol]; | |
| 529 | 568 | emitBefore(asyncId, immediate[trigger_async_id_symbol], immediate); | |
| 530 | 569 | ||
| 570 | + let threw = true; | ||
| 531 | 571 | try { | |
| 532 | 572 | const argv = immediate._argv; | |
| 533 | 573 | if (!argv) | |
| 534 | 574 | immediate._onImmediate(); | |
| 535 | 575 | else | |
| 536 | 576 | immediate._onImmediate(...argv); | |
| 577 | + threw = false; | ||
| 537 | 578 | } finally { | |
| 538 | - immediate._onImmediate = null; | ||
| 579 | + if (threw) { | ||
| 580 | + immediate._onImmediate = undefined; | ||
| 581 | + immediate._argv = undefined; | ||
| 582 | + enqueueRemoveStoresFromResource(immediate); | ||
| 583 | + } else { | ||
| 584 | + cleanImmediate(immediate); | ||
| 585 | + } | ||
| 539 | 586 | ||
| 540 | 587 | emitDestroy(asyncId); | |
| 541 | 588 | ||
@@ -607,6 +654,8 @@ function getTimerCallbacks(runNextTicks) { | |||
| 607 | 654 | if (!timer._destroyed) { | |
| 608 | 655 | timer._destroyed = true; | |
| 609 | 656 | ||
| 657 | + cleanTimer(timer); | ||
| 658 | + | ||
| 610 | 659 | if (timer[kHasPrimitive]) | |
| 611 | 660 | delete knownTimersById[asyncId]; | |
| 612 | 661 | ||
@@ -629,26 +678,42 @@ function getTimerCallbacks(runNextTicks) { | |||
| 629 | 678 | start = binding.getLibuvNow(); | |
| 630 | 679 | } | |
| 631 | 680 | ||
| 681 | + let threw = true; | ||
| 632 | 682 | try { | |
| 633 | 683 | const args = timer._timerArgs; | |
| 634 | 684 | if (args === undefined) | |
| 635 | 685 | timer._onTimeout(); | |
| 636 | 686 | else | |
| 637 | 687 | ReflectApply(timer._onTimeout, timer, args); | |
| 688 | + threw = false; | ||
| 638 | 689 | } finally { | |
| 639 | 690 | if (timer._repeat && timer._idleTimeout !== -1) { | |
| 640 | 691 | timer._idleTimeout = timer._repeat; | |
| 641 | 692 | insert(timer, timer._idleTimeout, start); | |
| 642 | - } else if (!timer._idleNext && !timer._idlePrev && !timer._destroyed) { | ||
| 643 | - timer._destroyed = true; | ||
| 644 | - | ||
| 645 | - if (timer[kHasPrimitive]) | ||
| 646 | - delete knownTimersById[asyncId]; | ||
| 647 | - | ||
| 648 | - if (timer[kRefed]) | ||
| 649 | - timeoutInfo[0]--; | ||
| 650 | - | ||
| 651 | - emitDestroy(asyncId); | ||
| 693 | + } else if (!timer._idleNext && !timer._idlePrev) { | ||
| 694 | + if (timer._destroyed) { | ||
| 695 | + timer._onTimeout = undefined; | ||
| 696 | + timer._timerArgs = undefined; | ||
| 697 | + if (threw) | ||
| 698 | + enqueueRemoveStoresIfNotReinserted(timer); | ||
| 699 | + else | ||
| 700 | + removeStoresFromResource(timer); | ||
| 701 | + } else { | ||
| 702 | + if (threw) | ||
| 703 | + enqueueRemoveStoresIfNotReinserted(timer); | ||
| 704 | + else | ||
| 705 | + removeStoresFromResource(timer); | ||
| 706 | + | ||
| 707 | + timer._destroyed = true; | ||
| 708 | + | ||
| 709 | + if (timer[kHasPrimitive]) | ||
| 710 | + delete knownTimersById[asyncId]; | ||
| 711 | + | ||
| 712 | + if (timer[kRefed]) | ||
| 713 | + timeoutInfo[0]--; | ||
| 714 | + | ||
| 715 | + emitDestroy(asyncId); | ||
| 716 | + } | ||
| 652 | 717 | } | |
| 653 | 718 | } | |
| 654 | 719 | ||
@@ -728,8 +793,11 @@ module.exports = { | |||
| 728 | 793 | kTimeout: Symbol('timeout'), // For hiding Timeouts on other internals. | |
| 729 | 794 | async_id_symbol, | |
| 730 | 795 | trigger_async_id_symbol, | |
| 796 | + async_context_frame, | ||
| 731 | 797 | Timeout, | |
| 732 | 798 | Immediate, | |
| 799 | + cleanImmediate, | ||
| 800 | + cleanTimer, | ||
| 733 | 801 | kRefed, | |
| 734 | 802 | kHasPrimitive, | |
| 735 | 803 | initAsyncResource, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -38,6 +38,8 @@ const { | |||
| 38 | 38 | async_id_symbol, | |
| 39 | 39 | Timeout, | |
| 40 | 40 | Immediate, | |
| 41 | + cleanTimer, | ||
| 42 | + cleanImmediate, | ||
| 41 | 43 | decRefCount, | |
| 42 | 44 | immediateInfoFields: { | |
| 43 | 45 | kCount, | |
@@ -69,9 +71,12 @@ const { | |||
| 69 | 71 | ||
| 70 | 72 | // Remove a timer. Cancels the timeout and resets the relevant timer properties. | |
| 71 | 73 | function unenroll(item) { | |
| 72 | - if (item._destroyed) | ||
| 74 | + if (item._destroyed) { | ||
| 75 | + cleanTimer(item); | ||
| 73 | 76 | return; | |
| 77 | + } | ||
| 74 | 78 | ||
| 79 | + const wasEnrolled = item._idleNext !== null || item._idlePrev !== null; | ||
| 75 | 80 | item._destroyed = true; | |
| 76 | 81 | ||
| 77 | 82 | if (item[kHasPrimitive]) | |
@@ -99,6 +104,9 @@ function unenroll(item) { | |||
| 99 | 104 | decRefCount(); | |
| 100 | 105 | } | |
| 101 | 106 | ||
| 107 | + if (wasEnrolled) | ||
| 108 | + cleanTimer(item); | ||
| 109 | + | ||
| 102 | 110 | // If active is called later, then we want to make sure not to insert again | |
| 103 | 111 | item._idleTimeout = -1; | |
| 104 | 112 | } | |
@@ -238,7 +246,7 @@ function clearImmediate(immediate) { | |||
| 238 | 246 | ||
| 239 | 247 | emitDestroy(immediate[async_id_symbol]); | |
| 240 | 248 | ||
| 241 | - immediate._onImmediate = null; | ||
| 249 | + cleanImmediate(immediate); | ||
| 242 | 250 | ||
| 243 | 251 | immediateQueue.remove(immediate); | |
| 244 | 252 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments