import-in-the-middle 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/README.md +10 -8
  3. package/fuck.mjs +12 -0
  4. package/hook.mjs +40 -9
  5. package/index.d.ts +68 -7
  6. package/index.js +74 -19
  7. package/lib/register.js +36 -0
  8. package/package.json +7 -3
  9. package/test/README.md +13 -0
  10. package/test/hook/define-property.js +20 -0
  11. package/test/hook/dynamic-import-default.js +29 -0
  12. package/test/hook/dynamic-import-default.mjs +23 -0
  13. package/test/hook/dynamic-import.js +27 -0
  14. package/test/{dynamic-import.mjs → hook/dynamic-import.mjs} +8 -6
  15. package/test/hook/remove.mjs +23 -0
  16. package/test/hook/static-import-default.mjs +26 -0
  17. package/test/hook/static-import-disabled.mjs +15 -0
  18. package/test/hook/static-import-package-internals-enabled.mjs +15 -0
  19. package/test/hook/static-import-package-internals.mjs +15 -0
  20. package/test/hook/static-import-package.mjs +15 -0
  21. package/test/hook/static-import.mjs +24 -0
  22. package/test/{dynamic-import-default.js → low-level/dynamic-import-default.js} +3 -3
  23. package/test/{dynamic-import-default.mjs → low-level/dynamic-import-default.mjs} +3 -3
  24. package/test/{dynamic-import.js → low-level/dynamic-import.js} +7 -5
  25. package/test/{remove.mjs → low-level/remove.mjs} +4 -4
  26. package/test/{static-import-default.mjs → low-level/static-import-default.mjs} +3 -3
  27. package/test/{static-import-disabled.mjs → low-level/static-import-disabled.mjs} +3 -3
  28. package/test/{static-import.mjs → low-level/static-import.mjs} +7 -5
  29. package/test/other/executable +6 -0
  30. package/test/other/import-executable.mjs +11 -0
@@ -1,3 +1,4 @@
1
1
  Component,Origin,License,Copyright
2
+ require,module-details-from-path,MIT,Copyright 2016 Thomas Watson Steen
2
3
  dev,c8,ISC,"Copyright (c) 2017, Contributors"
3
4
  dev,imhotap,MIT,Copyright (c) 2019 Bryan English.
package/README.md CHANGED
@@ -7,23 +7,25 @@ time.
7
7
 
8
8
  ## Usage
9
9
 
10
- See the Typescript definition file for API docs.
10
+ The API for
11
+ `require-in-the-middle` is followed as closely as possible as the default
12
+ export. There are lower-level `addHook` and `removeHook` exports available which
13
+ don't do any filtering of modules, and present the full file URL as a parameter
14
+ to the hook. See the Typescript definition file for detailed API docs.
11
15
 
12
16
  You can modify anything exported from any given ESM or CJS module that's
13
17
  imported in ESM files, regardless of whether they're imported statically or
14
18
  dynamically.
15
19
 
16
20
  ```js
17
- import { addHook } from 'import-in-the-middle'
18
- import { foo } from './module-i-want-to-modify.mjs'
21
+ import Hook from 'import-in-the-middle'
22
+ import { foo } from 'package-i-want-to-modify'
19
23
 
20
24
  console.log(foo) // whatever that module exported
21
25
 
22
- addHook((url, exported) => {
26
+ Hook(['package-i-want-to-modify'], (exported, name, baseDir) => {
23
27
  // `exported` is effectively `import * as exported from ${url}`
24
- if (url.match(/module-i-want-to-modify.mjs$/)) {
25
- exported.foo += 1
26
- }
28
+ exported.foo += 1
27
29
  })
28
30
 
29
31
  console.log(foo) // 1 more than whatever that module exported
@@ -33,7 +35,7 @@ This requires the use of an ESM loader hook, which can be added with the followi
33
35
  command-line option.
34
36
 
35
37
  ```
36
- --loader=/path/to/import-in-the-middle/hook.mjs
38
+ --loader=import-in-the-middle/hook.mjs
37
39
  ```
38
40
 
39
41
  ## Limitations
package/fuck.mjs ADDED
@@ -0,0 +1,12 @@
1
+ import vm from 'vm'
2
+
3
+ const context = vm.createContext()
4
+ console.log(vm)
5
+ const mod = new vm.SourceTextModule(`
6
+ export const bar = 5
7
+ `, { context })
8
+ await mod.link(async () => {
9
+ return new vm.SyntheticModule([], function () {
10
+ }, { context })
11
+ })
12
+ console.log(Reflect.ownKeys(mod.namespace))
package/hook.mjs CHANGED
@@ -2,6 +2,12 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
+ const specifiers = new Map()
6
+
7
+ const EXTENSION_RE = /\.(js|mjs|cjs)$/
8
+
9
+ let entrypoint
10
+
5
11
  export async function resolve (specifier, context, parentResolve) {
6
12
  const { parentURL = '' } = context
7
13
 
@@ -10,11 +16,17 @@ export async function resolve (specifier, context, parentResolve) {
10
16
  }
11
17
  const url = await parentResolve(specifier, context, parentResolve)
12
18
 
13
- if (parentURL === import.meta.url ||
14
- parentURL.startsWith('iitm:')) {
19
+ if (parentURL === '' && !EXTENSION_RE.test(url.url)) {
20
+ entrypoint = url.url
21
+ return { url: url.url, format: 'commonjs' }
22
+ }
23
+
24
+ if (parentURL === import.meta.url || parentURL.startsWith('iitm:')) {
15
25
  return url
16
26
  }
17
27
 
28
+ specifiers.set(url.url, specifier)
29
+
18
30
  return {
19
31
  url: `iitm:${url.url}`
20
32
  }
@@ -26,22 +38,27 @@ export function getFormat (url, context, parentGetFormat) {
26
38
  format: 'module'
27
39
  }
28
40
  }
41
+ if (url === entrypoint) {
42
+ return {
43
+ format: 'commonjs'
44
+ }
45
+ }
29
46
 
30
47
  return parentGetFormat(url, context, parentGetFormat)
31
48
  }
32
49
 
33
- const iitmURL = new URL('index.js', import.meta.url).toString()
50
+ const iitmURL = new URL('lib/register.js', import.meta.url).toString()
34
51
  export async function getSource (url, context, parentGetSource) {
35
52
  if (url.startsWith('iitm:')) {
36
- const realName = url.replace('iitm:', '')
37
- const real = await import(realName)
38
- const names = Object.keys(real)
53
+ const realUrl = url.replace('iitm:', '')
54
+ const realModule = await import(realUrl)
55
+ const exportNames = Object.keys(realModule)
39
56
  return {
40
57
  source: `
41
- import { _register } from '${iitmURL}'
58
+ import { register } from '${iitmURL}'
42
59
  import * as namespace from '${url}'
43
60
  const set = {}
44
- ${names.map((n) => `
61
+ ${exportNames.map((n) => `
45
62
  let $${n} = namespace.${n}
46
63
  export { $${n} as ${n} }
47
64
  set.${n} = (v) => {
@@ -49,10 +66,24 @@ set.${n} = (v) => {
49
66
  return true
50
67
  }
51
68
  `).join('\n')}
52
- _register('${realName}', namespace, set)
69
+ register('${realUrl}', namespace, set, '${specifiers.get(realUrl)}')
53
70
  `
54
71
  }
55
72
  }
56
73
 
57
74
  return parentGetSource(url, context, parentGetSource)
58
75
  }
76
+
77
+ // For Node.js 16.12.0 and higher.
78
+ export async function load (url, context, parentLoad) {
79
+ if (url.startsWith('iitm:')) {
80
+ const { source } = await getSource(url, context)
81
+ return {
82
+ source,
83
+ format: 'module'
84
+ }
85
+ }
86
+
87
+ return parentLoad(url, context, parentLoad)
88
+ }
89
+
package/index.d.ts CHANGED
@@ -2,24 +2,85 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
+ /**
6
+ * Property bag representing a module's exports, including the `default` if
7
+ * present.
8
+ */
9
+ export type Namespace = { [key: string]: any }
10
+
5
11
  /**
6
12
  * A hook function to be run against loaded modules.
13
+ * Not to be confused with `HookFunction`, used by the lower-level API.
14
+ * @param {exported} { [string]: any } An object representing the exported
15
+ * items of a module.
16
+ * @param {name} string The name of the module. If it is (or is part of) a
17
+ * package in a node_modules directory, this will be the path of the file
18
+ * starting from the package name.
19
+ * @param {baseDir} string The absolute path of the module, if not provided in
20
+ * `name`.
21
+ * @return any A value that can will be assigned to `exports.default`. This is
22
+ * equivalent to doing that assignment in the body of this function.
23
+ */
24
+ export type HookFn = (exported: Namespace, name: string, baseDir: string|void) => any
25
+
26
+ export type Options = {
27
+ internals?: boolean
28
+ }
29
+
30
+ declare class Hook {
31
+ /**
32
+ * Creates a hook to be run on any already loaded modules and any that will
33
+ * be loaded in the future. It will be run once per loaded module. If
34
+ * statically imported, any variables bound directly to exported items will
35
+ * be re-bound if those items are re-assigned in the hook function.
36
+ * @param {Array<string>} [modules] A list of modules to run this hook on. If
37
+ * omitted, it will run on every import everywhere.
38
+ * @param {Options} [options] An options object. If omitted, the default is
39
+ * `{ internals: false }`. If internals is true, then the hook will operate
40
+ * on internal modules of packages in node_modules. Otherwise it will not,
41
+ * unless they are mentioned specifically in the modules array.
42
+ * @param {HookFunction} hookFn The function to be run on each module.
43
+ */
44
+ constructor (modules: Array<string>, options: Options, hookFn: HookFn)
45
+ constructor (modules: Array<string>, hookFn: HookFn)
46
+ constructor (hookFn: HookFn)
47
+
48
+ /**
49
+ * Disables this hook. It will no longer be run against any subsequently
50
+ * loaded modules.
51
+ */
52
+ unhook(): void
53
+ }
54
+
55
+ export default Hook
56
+
57
+ /**
58
+ * A hook function to be run against loaded modules. To be used with the
59
+ * lower-level APIs `addHook` and `removeHook`.
7
60
  * @param {url} string The absolute path of the module, as a `file:` URL string.
8
- * @param {exported} { [string]: any } An object representing the exported items of a module.
61
+ * @param {exported} { [string]: any } An object representing the exported
62
+ * items of a module.
9
63
  */
10
- export type HookFunction = (url: string, exported: { [string]: any }) => void
64
+ export type HookFunction = (url: string, exported: Namespace) => void
11
65
 
12
66
  /**
13
- * Adds a hook to be run on any already loaded modules and any that will be loaded in the future.
14
- * It will be run once per loaded module. If statically imported, any variables bound directly to
15
- * exported items will be re-bound if those items are re-assigned in the hook.
67
+ * Adds a hook to be run on any already loaded modules and any that will be
68
+ * loaded in the future. It will be run once per loaded module. If statically
69
+ * imported, any variables bound directly to exported items will be re-bound if
70
+ * those items are re-assigned in the hook.
71
+ *
72
+ * This is the lower-level API for hook creation. It will be run on every
73
+ * single imported module, rather than with any filtering.
16
74
  * @param {HookFunction} hookFn The function to be run on each module.
17
75
  */
18
76
  export declare function addHook(hookFn: HookFunction): void
19
77
 
20
78
  /**
21
- * Removes a hook that has been previously added with `addHook`. It will no longer be run against
22
- * any subsequently loaded modules.
79
+ * Removes a hook that has been previously added with `addHook`. It will no
80
+ * longer be run against any subsequently loaded modules.
81
+ *
82
+ * This is the lower-level API for hook removal, and cannot be used with the
83
+ * `Hook` class.
23
84
  * @param {HookFunction} hookFn The function to be removed.
24
85
  */
25
86
  export declare function removeHook(hookFn: HookFunction): void
package/index.js CHANGED
@@ -2,33 +2,88 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
- const importHooks = [] // TODO should this be a Set?
5
+ const path = require('path')
6
+ const parse = require('module-details-from-path')
7
+ const { fileURLToPath } = require('url')
6
8
 
7
- const setters = new WeakMap()
9
+ const {
10
+ importHooks,
11
+ specifiers,
12
+ toHook
13
+ } = require('./lib/register')
8
14
 
9
- const toHook = []
10
-
11
- const proxyHandler = {
12
- set(target, name, value) {
13
- return setters.get(target)[name](value)
14
- }
15
- }
16
-
17
- exports._register = function _register(name, namespace, set) {
18
- setters.set(namespace, set)
19
- const proxy = new Proxy(namespace, proxyHandler)
20
- importHooks.forEach(hook => hook(name, proxy))
21
- toHook.push([name, proxy])
22
- }
23
-
24
- exports.addHook = function addHook(hook) {
15
+ function addHook(hook) {
25
16
  importHooks.push(hook)
26
17
  toHook.forEach(([name, namespace]) => hook(name, namespace))
27
18
  }
28
19
 
29
- exports.removeHook = function removeHook(hook) {
20
+ function removeHook(hook) {
30
21
  const index = importHooks.indexOf(hook)
31
22
  if (index > -1) {
32
23
  importHooks.splice(index, 1)
33
24
  }
34
25
  }
26
+
27
+ function callHookFn(hookFn, namespace, name, baseDir) {
28
+ const newDefault = hookFn(namespace, name, baseDir)
29
+ if (newDefault && newDefault !== namespace) {
30
+ namespace.default = newDefault
31
+ }
32
+ }
33
+
34
+ function Hook(modules, options, hookFn) {
35
+ if ((this instanceof Hook) === false) return new Hook(modules, options, hookFn)
36
+ if (typeof modules === 'function') {
37
+ hookFn = modules
38
+ modules = null
39
+ options = null
40
+ } else if (typeof options === 'function') {
41
+ hookFn = options
42
+ options = null
43
+ }
44
+ const internals = options ? options.internals === true : false
45
+
46
+ this._iitmHook = (name, namespace) => {
47
+ const filename = name
48
+ const isBuiltin = name.startsWith('node:')
49
+ let baseDir
50
+
51
+ if (isBuiltin) {
52
+ name = name.replace(/^node:/, '')
53
+ } else {
54
+ name = name.replace(/^file:\/\//, '')
55
+ const details = parse(name)
56
+ if (details) {
57
+ name = details.name
58
+ baseDir = details.basedir
59
+ }
60
+ }
61
+
62
+ if (modules) {
63
+ for (const moduleName of modules) {
64
+ if (moduleName === name) {
65
+ if (baseDir) {
66
+ if (internals) {
67
+ name = name + path.sep + path.relative(baseDir, fileURLToPath(filename))
68
+ } else {
69
+ if (!baseDir.endsWith(specifiers.get(filename))) continue
70
+ }
71
+ }
72
+ callHookFn(hookFn, namespace, name, baseDir)
73
+ }
74
+ }
75
+ } else {
76
+ callHookFn(hookFn, namespace, name, baseDir)
77
+ }
78
+ }
79
+
80
+ addHook(this._iitmHook)
81
+ }
82
+
83
+ Hook.prototype.unhook = function () {
84
+ removeHook(this._iitmHook)
85
+ }
86
+
87
+ module.exports = Hook
88
+ module.exports.addHook = addHook
89
+ module.exports.removeHook = removeHook
@@ -0,0 +1,36 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+
6
+ const importHooks = [] // TODO should this be a Set?
7
+ const setters = new WeakMap()
8
+ const specifiers = new Map()
9
+ const toHook = []
10
+
11
+ const proxyHandler = {
12
+ set(target, name, value) {
13
+ return setters.get(target)[name](value)
14
+ },
15
+
16
+ defineProperty(target, property, descriptor) {
17
+ if ((!('value' in descriptor))) {
18
+ throw new Error('Getters/setters are not supported for exports property descriptors.')
19
+ }
20
+
21
+ return setters.get(target)[property](descriptor.value)
22
+ }
23
+ }
24
+
25
+ function register(name, namespace, set, specifier) {
26
+ specifiers.set(name, specifier)
27
+ setters.set(namespace, set)
28
+ const proxy = new Proxy(namespace, proxyHandler)
29
+ importHooks.forEach(hook => hook(name, proxy))
30
+ toHook.push([name, proxy])
31
+ }
32
+
33
+ exports.register = register
34
+ exports.importHooks = importHooks
35
+ exports.specifiers = specifiers
36
+ exports.toHook = toHook
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "import-in-the-middle",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "Intercept imports in Node.js",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "c8 --check-coverage --lines 100 imhotap --runner test/runtest --files test/*.*js"
7
+ "test": "c8 --check-coverage --lines 90 imhotap --runner test/runtest --files test/{hook,low-level,other}/*",
8
+ "coverage": "c8 --reporter html imhotap --runner test/runtest --files test/{hook,low-level,other}/* && echo '\nNow open coverage/index.html\n'"
8
9
  },
9
10
  "repository": {
10
11
  "type": "git",
@@ -26,6 +27,9 @@
26
27
  "homepage": "https://github.com/DataDog/import-in-the-middle#readme",
27
28
  "devDependencies": {
28
29
  "c8": "^7.8.0",
29
- "imhotap": "^1.1.0"
30
+ "imhotap": "^2.0.0"
31
+ },
32
+ "dependencies": {
33
+ "module-details-from-path": "^1.0.3"
30
34
  }
31
35
  }
package/test/README.md ADDED
@@ -0,0 +1,13 @@
1
+ These tests are organized as follows:
2
+
3
+ * Located in the `hook` directory if they use the `Hook` class.
4
+ * Located in the `low-level` directory if they use the "low-level" API,
5
+ `addHook` and `removeHook`.
6
+
7
+ The tests should be run with the `runtest` command found in this directory. If
8
+ the command exits with a non-zero code, then it's a test failure.
9
+
10
+ Running of all the tests can be done with `npm test`.
11
+
12
+ Coverage must be 100% according to `c8`. If you don't have 100% coverage, you
13
+ can run `npm run coverage` to get coverage data in HTML form.
@@ -0,0 +1,20 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+ const Hook = require('../../index.js')
6
+ const { rejects } = require('assert')
7
+
8
+ Hook((exports, name) => {
9
+ if (name === 'os') {
10
+ Object.defineProperty(exports, 'freemem', {
11
+ get: () => () => 47
12
+ })
13
+ }
14
+ })
15
+
16
+ ;(async () => {
17
+ rejects(async () => {
18
+ await import('os')
19
+ })
20
+ })()
@@ -0,0 +1,29 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+ const Hook = require('../../index.js')
6
+ const { strictEqual } = require('assert')
7
+
8
+ Hook((exports, name) => {
9
+ if (name.match(/something.js/)) {
10
+ const orig = exports.default
11
+ exports.default = function bar() {
12
+ return orig() + 15
13
+ }
14
+ }
15
+ if (name.match(/something.mjs/)) {
16
+ const orig = exports.default
17
+ return function bar() {
18
+ return orig() + 15
19
+ }
20
+ }
21
+ })
22
+
23
+ ;(async () => {
24
+ const { default: barMjs } = await import('../fixtures/something.mjs')
25
+ const { default: barJs } = await import('../fixtures/something.js')
26
+
27
+ strictEqual(barMjs(), 57)
28
+ strictEqual(barJs(), 57)
29
+ })()
@@ -0,0 +1,23 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+ import Hook from '../../index.js'
6
+ import { strictEqual } from 'assert'
7
+
8
+ Hook((exports, name) => {
9
+ if (name.match(/something\.m?js/)) {
10
+ const orig = exports.default
11
+ exports.default = function bar() {
12
+ return orig() + 15
13
+ }
14
+ }
15
+ })
16
+
17
+ ;(async () => {
18
+ const { default: barMjs } = await import('../fixtures/something.mjs')
19
+ const { default: barJs } = await import('../fixtures/something.js')
20
+
21
+ strictEqual(barMjs(), 57)
22
+ strictEqual(barJs(), 57)
23
+ })()
@@ -0,0 +1,27 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+ const Hook = require('../../index.js')
6
+ const { strictEqual } = require('assert')
7
+
8
+ Hook((exports, name) => {
9
+ if (name.match(/something\.m?js/)) {
10
+ exports.foo += 15
11
+ }
12
+ if (name === 'os') {
13
+ Object.defineProperty(exports, 'freemem', {
14
+ value: () => 47
15
+ })
16
+ }
17
+ })
18
+
19
+ ;(async () => {
20
+ const { foo: fooMjs } = await import('../fixtures/something.mjs')
21
+ const { foo: fooJs } = await import('../fixtures/something.js')
22
+ const { freemem } = await import('os')
23
+
24
+ strictEqual(fooMjs, 57)
25
+ strictEqual(fooJs, 57)
26
+ strictEqual(freemem(), 47)
27
+ })()
@@ -2,21 +2,23 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
- import { addHook } from '../index.js'
5
+ import Hook from '../../index.js'
6
6
  import { strictEqual } from 'assert'
7
7
 
8
- addHook((name, exports) => {
8
+ Hook((exports, name) => {
9
9
  if (name.match(/something\.m?js/)) {
10
10
  exports.foo += 15
11
11
  }
12
- if (name.match('os')) {
13
- exports.freemem = () => 47
12
+ if (name === 'os') {
13
+ Object.defineProperty(exports, 'freemem', {
14
+ value: () => 47
15
+ })
14
16
  }
15
17
  })
16
18
 
17
19
  ;(async () => {
18
- const { foo: fooMjs } = await import('./fixtures/something.mjs')
19
- const { foo: fooJs } = await import('./fixtures/something.js')
20
+ const { foo: fooMjs } = await import('../fixtures/something.mjs')
21
+ const { foo: fooJs } = await import('../fixtures/something.js')
20
22
  const { freemem } = await import('os')
21
23
 
22
24
  strictEqual(fooMjs, 57)
@@ -0,0 +1,23 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+ import Hook from '../../index.js'
6
+ import { strictEqual } from 'assert'
7
+
8
+ const hook = new Hook((exports, name) => {
9
+ if (name.match(/something\.m?js/)) {
10
+ exports.foo += 15
11
+ }
12
+ })
13
+
14
+ ;(async () => {
15
+ const { foo: fooMjs } = await import('../fixtures/something.mjs')
16
+
17
+ hook.unhook()
18
+
19
+ const { foo: fooJs } = await import('../fixtures/something.js')
20
+
21
+ strictEqual(fooMjs, 57)
22
+ strictEqual(fooJs, 42)
23
+ })()
@@ -0,0 +1,26 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+ import Hook from '../../index.js'
6
+ import barMjs from '../fixtures/something.mjs'
7
+ import barJs from '../fixtures/something.js'
8
+ import { strictEqual } from 'assert'
9
+
10
+ Hook((exports, name) => {
11
+ if (name.match(/something.mjs/)) {
12
+ const orig = exports.default
13
+ exports.default = function bar() {
14
+ return orig() + 15
15
+ }
16
+ }
17
+ if (name.match(/something.js/)) {
18
+ const orig = exports.default
19
+ return function bar() {
20
+ return orig() + 15
21
+ }
22
+ }
23
+ })
24
+
25
+ strictEqual(barMjs(), 57)
26
+ strictEqual(barJs(), 57)
@@ -0,0 +1,15 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+ import Hook from '../../index.js'
6
+ import { foo as fooMjs } from '../fixtures/something.mjs'
7
+ import { foo as fooJs } from '../fixtures/something.js'
8
+ import { strictEqual, fail } from 'assert'
9
+
10
+ Hook(() => {
11
+ fail('should not have been called at all')
12
+ })
13
+
14
+ strictEqual(fooMjs, 42)
15
+ strictEqual(fooJs, 42)
@@ -0,0 +1,15 @@
1
+ import Hook from '../../index.js'
2
+ import { Report } from 'c8/index.js'
3
+ import path from 'path'
4
+ import { fileURLToPath } from 'url'
5
+ import { strictEqual } from 'assert'
6
+
7
+ const c8Dir = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'node_modules', 'c8')
8
+
9
+ Hook(['c8'], { internals: true }, (exports, name, baseDir) => {
10
+ strictEqual(name, 'c8/index.js')
11
+ strictEqual(baseDir, c8Dir)
12
+ exports.Report = () => 42
13
+ })
14
+
15
+ strictEqual(Report({}), 42)
@@ -0,0 +1,15 @@
1
+ import Hook from '../../index.js'
2
+ import { Report } from 'c8/index.js'
3
+ import path from 'path'
4
+ import { fileURLToPath } from 'url'
5
+ import { strictEqual, notStrictEqual } from 'assert'
6
+
7
+ const c8Dir = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'node_modules', 'c8')
8
+
9
+ Hook(['c8'], (exports, name, baseDir) => {
10
+ strictEqual(name, 'c8')
11
+ strictEqual(baseDir, c8Dir)
12
+ exports.Report = () => 42
13
+ })
14
+
15
+ notStrictEqual(Report({}), 42)
@@ -0,0 +1,15 @@
1
+ import Hook from '../../index.js'
2
+ import { Report } from 'c8'
3
+ import path from 'path'
4
+ import { fileURLToPath } from 'url'
5
+ import { strictEqual } from 'assert'
6
+
7
+ const c8Dir = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'node_modules', 'c8')
8
+
9
+ Hook(['c8'], (exports, name, baseDir) => {
10
+ strictEqual(name, 'c8')
11
+ strictEqual(baseDir, c8Dir)
12
+ exports.Report = () => 42
13
+ })
14
+
15
+ strictEqual(Report({}), 42)
@@ -0,0 +1,24 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+ import Hook from '../../index.js'
6
+ import { foo as fooMjs } from '../fixtures/something.mjs'
7
+ import { foo as fooJs } from '../fixtures/something.js'
8
+ import { freemem } from 'os'
9
+ import { strictEqual } from 'assert'
10
+
11
+ Hook((exports, name) => {
12
+ if (name.match(/something\.m?js/)) {
13
+ exports.foo += 15
14
+ }
15
+ if (name === 'os') {
16
+ Object.defineProperty(exports, 'freemem', {
17
+ value: () => 47
18
+ })
19
+ }
20
+ })
21
+
22
+ strictEqual(fooMjs, 57)
23
+ strictEqual(fooJs, 57)
24
+ strictEqual(freemem(), 47)
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
- const { addHook } = require('../index.js')
5
+ const { addHook } = require('../../index.js')
6
6
  const { strictEqual } = require('assert')
7
7
 
8
8
  addHook((name, exports) => {
@@ -15,8 +15,8 @@ addHook((name, exports) => {
15
15
  })
16
16
 
17
17
  ;(async () => {
18
- const { default: barMjs } = await import('./fixtures/something.mjs')
19
- const { default: barJs } = await import('./fixtures/something.js')
18
+ const { default: barMjs } = await import('../fixtures/something.mjs')
19
+ const { default: barJs } = await import('../fixtures/something.js')
20
20
 
21
21
  strictEqual(barMjs(), 57)
22
22
  strictEqual(barJs(), 57)
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
- import { addHook } from '../index.js'
5
+ import { addHook } from '../../index.js'
6
6
  import { strictEqual } from 'assert'
7
7
 
8
8
  addHook((name, exports) => {
@@ -15,8 +15,8 @@ addHook((name, exports) => {
15
15
  })
16
16
 
17
17
  ;(async () => {
18
- const { default: barMjs } = await import('./fixtures/something.mjs')
19
- const { default: barJs } = await import('./fixtures/something.js')
18
+ const { default: barMjs } = await import('../fixtures/something.mjs')
19
+ const { default: barJs } = await import('../fixtures/something.js')
20
20
 
21
21
  strictEqual(barMjs(), 57)
22
22
  strictEqual(barJs(), 57)
@@ -2,21 +2,23 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
- const { addHook } = require('../index.js')
5
+ const { addHook } = require('../../index.js')
6
6
  const { strictEqual } = require('assert')
7
7
 
8
8
  addHook((name, exports) => {
9
9
  if (name.match(/something\.m?js/)) {
10
10
  exports.foo += 15
11
11
  }
12
- if (name.match('os')) {
13
- exports.freemem = () => 47
12
+ if (name === 'node:os') {
13
+ Object.defineProperty(exports, 'freemem', {
14
+ value: () => 47
15
+ })
14
16
  }
15
17
  })
16
18
 
17
19
  ;(async () => {
18
- const { foo: fooMjs } = await import('./fixtures/something.mjs')
19
- const { foo: fooJs } = await import('./fixtures/something.js')
20
+ const { foo: fooMjs } = await import('../fixtures/something.mjs')
21
+ const { foo: fooJs } = await import('../fixtures/something.js')
20
22
  const { freemem } = await import('os')
21
23
 
22
24
  strictEqual(fooMjs, 57)
@@ -2,8 +2,8 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
- import { addHook, removeHook } from '../index.js'
6
- import { strictEqual, ok } from 'assert'
5
+ import { addHook, removeHook } from '../../index.js'
6
+ import { strictEqual } from 'assert'
7
7
 
8
8
  const hook = (name, exports) => {
9
9
  if (name.match(/something\.m?js/)) {
@@ -14,11 +14,11 @@ const hook = (name, exports) => {
14
14
  addHook(hook)
15
15
 
16
16
  ;(async () => {
17
- const { foo: fooMjs } = await import('./fixtures/something.mjs')
17
+ const { foo: fooMjs } = await import('../fixtures/something.mjs')
18
18
 
19
19
  removeHook(hook)
20
20
 
21
- const { foo: fooJs } = await import('./fixtures/something.js')
21
+ const { foo: fooJs } = await import('../fixtures/something.js')
22
22
 
23
23
  strictEqual(fooMjs, 57)
24
24
  strictEqual(fooJs, 42)
@@ -2,9 +2,9 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
- import { addHook } from '../index.js'
6
- import barMjs from './fixtures/something.mjs'
7
- import barJs from './fixtures/something.js'
5
+ import { addHook } from '../../index.js'
6
+ import barMjs from '../fixtures/something.mjs'
7
+ import barJs from '../fixtures/something.js'
8
8
  import { strictEqual } from 'assert'
9
9
 
10
10
  addHook((name, exports) => {
@@ -2,9 +2,9 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
- import { addHook } from '../index.js'
6
- import { foo as fooMjs } from './fixtures/something.mjs'
7
- import { foo as fooJs } from './fixtures/something.js'
5
+ import { addHook } from '../../index.js'
6
+ import { foo as fooMjs } from '../fixtures/something.mjs'
7
+ import { foo as fooJs } from '../fixtures/something.js'
8
8
  import { strictEqual, fail } from 'assert'
9
9
 
10
10
  addHook(() => {
@@ -2,9 +2,9 @@
2
2
  //
3
3
  // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
4
 
5
- import { addHook } from '../index.js'
6
- import { foo as fooMjs } from './fixtures/something.mjs'
7
- import { foo as fooJs } from './fixtures/something.js'
5
+ import { addHook } from '../../index.js'
6
+ import { foo as fooMjs } from '../fixtures/something.mjs'
7
+ import { foo as fooJs } from '../fixtures/something.js'
8
8
  import { freemem } from 'os'
9
9
  import { strictEqual } from 'assert'
10
10
 
@@ -12,8 +12,10 @@ addHook((name, exports) => {
12
12
  if (name.match(/something\.m?js/)) {
13
13
  exports.foo += 15
14
14
  }
15
- if (name.match('os')) {
16
- exports.freemem = () => 47
15
+ if (name === 'node:os') {
16
+ Object.defineProperty(exports, 'freemem', {
17
+ value: () => 47
18
+ })
17
19
  }
18
20
  })
19
21
 
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
3
+ //
4
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
5
+
6
+ // This script doesn't actually have to do anything.
@@ -0,0 +1,11 @@
1
+ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License.
2
+ //
3
+ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
4
+
5
+ import { rejects } from 'assert'
6
+ (async () => {
7
+ await rejects(() => import('./executable'), {
8
+ name: 'TypeError',
9
+ code: 'ERR_UNKNOWN_FILE_EXTENSION'
10
+ })
11
+ })()