Skip to content

Commit b784138

Browse files
committed
Ensure all messages to loader are acknowledged
1 parent e9c7c41 commit b784138

File tree

4 files changed

+44
-16
lines changed

4 files changed

+44
-16
lines changed

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,27 @@ module.register('import-in-the-middle/hook.mjs', import.meta.url, {
7474
### Only Intercepting Hooked modules
7575
7676
If you are `Hook`'ing all modules before they are imported, for example in a
77-
module loaded via the Node.js `--import` argument, you can configure the loader
78-
hook to only intercept those specific modules:
77+
module loaded via the Node.js `--import` CLI argument, you can configure the
78+
loader to intercept only modules that were specifically hooked.
7979
8080
`instrument.mjs`
8181
```js
8282
import { register } from 'module'
8383
import { Hook, createAddHookMessageChannel } from 'import-in-the-middle'
8484

85-
const addHookMessagePort = createAddHookMessageChannel()
85+
const { addHookMessagePort, waitForAllMessagesAcknowledged } = createAddHookMessageChannel()
8686

87-
const options = {
88-
data: { addHookMessagePort },
89-
transferList: [addHookMessagePort]
90-
}
87+
const options = { data: { addHookMessagePort }, transferList: [addHookMessagePort] }
9188

9289
register('import-in-the-middle/hook.mjs', import.meta.url, options)
9390

9491
Hook(['fs'], (exported, name, baseDir) => {
9592
// Instrument the fs module
9693
})
94+
95+
// Ensure that the loader has acknowledged all the modules
96+
// before we allow execution to continue
97+
await waitForAllMessagesAcknowledged()
9798
```
9899
`my-app.mjs`
99100
```js

hook.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,15 +263,16 @@ function createHook (meta) {
263263
}
264264

265265
includeModules.push(...modules)
266-
})
266+
data.addHookMessagePort.postMessage('ack')
267+
}).unref()
267268
}
268269
}
269270
}
270271

271272
async function resolve (specifier, context, parentResolve) {
272273
cachedResolve = parentResolve
273274

274-
// See github.com/nodejs/import-in-the-middle/pull/76.
275+
// See https://github.com/nodejs/import-in-the-middle/pull/76.
275276
if (specifier === iitmURL) {
276277
return {
277278
url: specifier,

index.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,39 @@ function callHookFn (hookFn, namespace, name, baseDir) {
3232
}
3333
}
3434

35-
let sendToMessageChannel
35+
let sendModulesToLoader
3636

3737
function createAddHookMessageChannel () {
3838
const { port1, port2 } = new MessageChannel()
39+
let pendingAckCount = 0
40+
let resolveFn
3941

40-
sendToMessageChannel = (modules) => {
42+
sendModulesToLoader = (modules) => {
43+
pendingAckCount++
4144
port1.postMessage(modules)
4245
}
4346

44-
return port2
47+
port1.on('message', () => {
48+
pendingAckCount--
49+
50+
if (resolveFn && pendingAckCount <= 0) {
51+
resolveFn()
52+
}
53+
}).unref()
54+
55+
function waitForAllMessagesAcknowledged () {
56+
const promise = new Promise((resolve) => {
57+
resolveFn = resolve
58+
})
59+
60+
if (pendingAckCount === 0) {
61+
resolveFn()
62+
}
63+
64+
return promise
65+
}
66+
67+
return { addHookMessagePort: port2, waitForAllMessagesAcknowledged }
4568
}
4669

4770
function Hook (modules, options, hookFn) {
@@ -56,8 +79,8 @@ function Hook (modules, options, hookFn) {
5679
}
5780
const internals = options ? options.internals === true : false
5881

59-
if (sendToMessageChannel && Array.isArray(modules)) {
60-
sendToMessageChannel(modules)
82+
if (sendModulesToLoader && Array.isArray(modules)) {
83+
sendModulesToLoader(modules)
6184
}
6285

6386
this._iitmHook = (name, namespace) => {

test/fixtures/import.mjs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { register } from 'module'
22
import { Hook, createAddHookMessageChannel } from '../../index.js'
3-
// We've imported path here to ensure that the hook is still applied later.
3+
// We've imported path here to ensure that the hook is still applied later even
4+
// if the library is used here.
45
import * as path from 'path'
56

6-
const addHookMessagePort = createAddHookMessageChannel()
7+
const { addHookMessagePort, waitForAllMessagesAcknowledged } = createAddHookMessageChannel()
78

89
register('../../hook.mjs', import.meta.url, { data: { addHookMessagePort }, transferList: [addHookMessagePort] })
910

@@ -12,3 +13,5 @@ Hook(['path'], (exports) => {
1213
})
1314

1415
console.assert(path.sep !== '@')
16+
17+
await waitForAllMessagesAcknowledged()

0 commit comments

Comments
 (0)