dd-trace 5.35.0 → 5.37.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 (125) hide show
  1. package/LICENSE-3rdparty.csv +2 -1
  2. package/index.d.ts +8 -7
  3. package/loader-hook.mjs +0 -4
  4. package/package.json +15 -14
  5. package/packages/datadog-core/index.js +1 -1
  6. package/packages/datadog-core/src/storage.js +76 -31
  7. package/packages/datadog-instrumentations/src/cucumber.js +54 -1
  8. package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
  9. package/packages/datadog-instrumentations/src/helpers/register.js +2 -2
  10. package/packages/datadog-instrumentations/src/jest.js +105 -11
  11. package/packages/datadog-instrumentations/src/mocha/main.js +46 -4
  12. package/packages/datadog-instrumentations/src/mocha/utils.js +35 -2
  13. package/packages/datadog-instrumentations/src/mocha/worker.js +7 -0
  14. package/packages/datadog-instrumentations/src/mysql2.js +3 -3
  15. package/packages/datadog-instrumentations/src/openai.js +8 -0
  16. package/packages/datadog-instrumentations/src/playwright.js +70 -22
  17. package/packages/datadog-instrumentations/src/vitest.js +60 -6
  18. package/packages/datadog-plugin-aerospike/src/index.js +1 -1
  19. package/packages/datadog-plugin-apollo/src/gateway/fetch.js +1 -1
  20. package/packages/datadog-plugin-apollo/src/gateway/index.js +1 -1
  21. package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -1
  22. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -3
  23. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -4
  24. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -2
  25. package/packages/datadog-plugin-azure-functions/src/index.js +1 -1
  26. package/packages/datadog-plugin-couchbase/src/index.js +2 -2
  27. package/packages/datadog-plugin-cucumber/src/index.js +31 -14
  28. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +72 -7
  29. package/packages/datadog-plugin-cypress/src/support.js +36 -29
  30. package/packages/datadog-plugin-dd-trace-api/src/index.js +1 -3
  31. package/packages/datadog-plugin-graphql/src/utils.js +8 -1
  32. package/packages/datadog-plugin-grpc/src/client.js +1 -1
  33. package/packages/datadog-plugin-grpc/src/server.js +1 -1
  34. package/packages/datadog-plugin-hapi/src/index.js +1 -1
  35. package/packages/datadog-plugin-http/src/client.js +1 -1
  36. package/packages/datadog-plugin-http/src/server.js +1 -1
  37. package/packages/datadog-plugin-http2/src/client.js +3 -3
  38. package/packages/datadog-plugin-http2/src/server.js +1 -1
  39. package/packages/datadog-plugin-jest/src/index.js +17 -12
  40. package/packages/datadog-plugin-langchain/src/tracing.js +1 -1
  41. package/packages/datadog-plugin-mariadb/src/index.js +3 -3
  42. package/packages/datadog-plugin-mocha/src/index.js +35 -16
  43. package/packages/datadog-plugin-mongodb-core/src/index.js +28 -2
  44. package/packages/datadog-plugin-next/src/index.js +4 -4
  45. package/packages/datadog-plugin-openai/src/tracing.js +2 -3
  46. package/packages/datadog-plugin-playwright/src/index.js +35 -9
  47. package/packages/datadog-plugin-rhea/src/consumer.js +1 -1
  48. package/packages/datadog-plugin-router/src/index.js +2 -2
  49. package/packages/datadog-plugin-selenium/src/index.js +1 -1
  50. package/packages/datadog-plugin-vitest/src/index.js +36 -12
  51. package/packages/dd-trace/src/appsec/graphql.js +6 -6
  52. package/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +3 -7
  53. package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +15 -1
  54. package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +17 -30
  55. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +2 -2
  56. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +7 -11
  57. package/packages/dd-trace/src/appsec/iast/analyzers/stored-injection-analyzer.js +11 -0
  58. package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +2 -6
  59. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +24 -4
  60. package/packages/dd-trace/src/appsec/iast/context/context-plugin.js +2 -2
  61. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +2 -2
  62. package/packages/dd-trace/src/appsec/iast/index.js +4 -2
  63. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +187 -0
  64. package/packages/dd-trace/src/appsec/iast/security-controls/parser.js +96 -0
  65. package/packages/dd-trace/src/appsec/iast/taint-tracking/constants.js +6 -0
  66. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -2
  67. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +8 -8
  68. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +1 -1
  69. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +65 -0
  70. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +14 -5
  71. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +80 -2
  72. package/packages/dd-trace/src/appsec/iast/taint-tracking/secure-marks-generator.js +1 -1
  73. package/packages/dd-trace/src/appsec/iast/taint-tracking/secure-marks.js +28 -0
  74. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
  75. package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +5 -0
  76. package/packages/dd-trace/src/appsec/iast/utils.js +24 -0
  77. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +8 -13
  78. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -0
  79. package/packages/dd-trace/src/appsec/index.js +4 -4
  80. package/packages/dd-trace/src/appsec/rasp/command_injection.js +5 -5
  81. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +5 -5
  82. package/packages/dd-trace/src/appsec/rasp/lfi.js +3 -3
  83. package/packages/dd-trace/src/appsec/rasp/sql_injection.js +4 -4
  84. package/packages/dd-trace/src/appsec/rasp/ssrf.js +3 -3
  85. package/packages/dd-trace/src/appsec/reporter.js +3 -3
  86. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
  87. package/packages/dd-trace/src/appsec/waf/index.js +1 -1
  88. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +2 -0
  89. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +31 -56
  90. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +20 -2
  91. package/packages/dd-trace/src/ci-visibility/quarantined-tests/get-quarantined-tests.js +62 -0
  92. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +5 -2
  93. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +3 -3
  94. package/packages/dd-trace/src/config.js +18 -3
  95. package/packages/dd-trace/src/data_streams_context.js +2 -2
  96. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +14 -7
  97. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +50 -0
  98. package/packages/dd-trace/src/debugger/devtools_client/state.js +38 -10
  99. package/packages/dd-trace/src/exporters/common/agents.js +1 -1
  100. package/packages/dd-trace/src/exporters/common/request.js +3 -3
  101. package/packages/dd-trace/src/iitm.js +2 -2
  102. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +1 -1
  103. package/packages/dd-trace/src/llmobs/tagger.js +12 -2
  104. package/packages/dd-trace/src/log/writer.js +3 -3
  105. package/packages/dd-trace/src/noop/span.js +1 -1
  106. package/packages/dd-trace/src/opentracing/propagation/text_map.js +5 -4
  107. package/packages/dd-trace/src/opentracing/span.js +3 -3
  108. package/packages/dd-trace/src/plugin_manager.js +3 -1
  109. package/packages/dd-trace/src/plugins/apollo.js +1 -1
  110. package/packages/dd-trace/src/plugins/ci_plugin.js +51 -4
  111. package/packages/dd-trace/src/plugins/database.js +14 -4
  112. package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
  113. package/packages/dd-trace/src/plugins/plugin.js +8 -8
  114. package/packages/dd-trace/src/plugins/tracing.js +3 -3
  115. package/packages/dd-trace/src/plugins/util/git.js +3 -3
  116. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -3
  117. package/packages/dd-trace/src/plugins/util/test.js +10 -4
  118. package/packages/dd-trace/src/profiling/exporters/agent.js +3 -3
  119. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
  120. package/packages/dd-trace/src/proxy.js +5 -1
  121. package/packages/dd-trace/src/ritm.js +2 -1
  122. package/packages/dd-trace/src/scope.js +5 -5
  123. package/packages/dd-trace/src/spanleak.js +0 -1
  124. package/packages/dd-trace/src/tracer.js +0 -14
  125. package/packages/memwatch/package.json +0 -9
@@ -27,7 +27,7 @@ require,protobufjs,BSD-3-Clause,Copyright 2016 Daniel Wirtz
27
27
  require,tlhunter-sorted-set,MIT,Copyright (c) 2023 Datadog Inc.
28
28
  require,retry,MIT,Copyright 2011 Tim Koschützki Felix Geisendörfer
29
29
  require,rfdc,MIT,Copyright 2019 David Mark Clements
30
- require,semver,ISC,Copyright Isaac Z. Schlueter and Contributors
30
+ require,semifies,Apache license 2.0,Copyright Authors
31
31
  require,shell-quote,mit,Copyright (c) 2013 James Halliday
32
32
  require,source-map,BSD-3-Clause,Copyright (c) 2009-2011, Mozilla Foundation and contributors
33
33
  require,ttl-set,MIT,Copyright (c) 2024 Thomas Watson
@@ -68,6 +68,7 @@ dev,nock,MIT,Copyright 2017 Pedro Teixeira and other contributors
68
68
  dev,nyc,ISC,Copyright 2015 Contributors
69
69
  dev,proxyquire,MIT,Copyright 2013 Thorsten Lorenz
70
70
  dev,rimraf,ISC,Copyright Isaac Z. Schlueter and Contributors
71
+ dev,semver,ISC,Copyright Isaac Z. Schlueter and Contributors
71
72
  dev,sinon,BSD-3-Clause,Copyright 2010-2017 Christian Johansen
72
73
  dev,sinon-chai,WTFPL and BSD-2-Clause,Copyright 2004 Sam Hocevar 2012–2017 Domenic Denicola
73
74
  dev,tap,ISC,Copyright 2011-2022 Isaac Z. Schlueter and Contributors
package/index.d.ts CHANGED
@@ -85,10 +85,6 @@ interface Tracer extends opentracing.Tracer {
85
85
  * span will finish when that callback is called.
86
86
  * * The function doesn't accept a callback and doesn't return a promise, in
87
87
  * which case the span will finish at the end of the function execution.
88
- *
89
- * If the `orphanable` option is set to false, the function will not be traced
90
- * unless there is already an active span or `childOf` option. Note that this
91
- * option is deprecated and has been removed in version 4.0.
92
88
  */
93
89
  trace<T> (name: string, fn: (span: tracer.Span) => T): T;
94
90
  trace<T> (name: string, fn: (span: tracer.Span, done: (error?: Error) => void) => T): T;
@@ -659,13 +655,13 @@ declare namespace tracer {
659
655
  * * 'anonymous': will hash user IDs and user logins before collecting them
660
656
  * * 'anon': alias for 'anonymous'
661
657
  * * 'safe': deprecated alias for 'anonymous'
662
- *
658
+ *
663
659
  * * 'identification': will collect user IDs and logins without redaction
664
660
  * * 'ident': alias for 'identification'
665
661
  * * 'extended': deprecated alias for 'identification'
666
- *
662
+ *
667
663
  * * 'disabled': will not collect user IDs and logins
668
- *
664
+ *
669
665
  * Unknown values will be considered as 'disabled'
670
666
  * @default 'identification'
671
667
  */
@@ -2230,6 +2226,11 @@ declare namespace tracer {
2230
2226
  */
2231
2227
  redactionValuePattern?: string,
2232
2228
 
2229
+ /**
2230
+ * Allows to enable security controls.
2231
+ */
2232
+ securityControlsConfiguration?: string,
2233
+
2233
2234
  /**
2234
2235
  * Specifies the verbosity of the sent telemetry. Default 'INFORMATION'
2235
2236
  */
package/loader-hook.mjs CHANGED
@@ -1,5 +1 @@
1
- // TODO(bengl): Not sure why `import/export` fails on this line, but it's just
2
- // a passthrough to another module so it should be fine. Disabling for now.
3
-
4
- // eslint-disable-next-line import/export
5
1
  export * from 'import-in-the-middle/hook.mjs'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.35.0",
3
+ "version": "5.37.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -12,8 +12,8 @@
12
12
  "bench:e2e:ci-visibility": "node benchmark/e2e-ci/benchmark-run.js",
13
13
  "type:doc": "cd docs && yarn && yarn build",
14
14
  "type:test": "cd docs && yarn && yarn test",
15
- "lint": "node scripts/check_licenses.js && eslint . && yarn audit",
16
- "lint-fix": "node scripts/check_licenses.js && eslint . --fix && yarn audit",
15
+ "lint": "node scripts/check_licenses.js && eslint . --max-warnings 0 && yarn audit",
16
+ "lint:fix": "node scripts/check_licenses.js && eslint . --max-warnings 0 --fix && yarn audit",
17
17
  "release:proposal": "node scripts/release/proposal",
18
18
  "services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
19
19
  "test": "SERVICES=* yarn services && mocha --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
@@ -83,8 +83,8 @@
83
83
  "dependencies": {
84
84
  "@datadog/libdatadog": "^0.4.0",
85
85
  "@datadog/native-appsec": "8.4.0",
86
- "@datadog/native-iast-rewriter": "2.6.1",
87
- "@datadog/native-iast-taint-tracking": "3.2.0",
86
+ "@datadog/native-iast-rewriter": "2.8.0",
87
+ "@datadog/native-iast-taint-tracking": "3.3.0",
88
88
  "@datadog/native-metrics": "^3.1.0",
89
89
  "@datadog/pprof": "5.5.1",
90
90
  "@datadog/sketches-js": "^2.1.0",
@@ -108,7 +108,7 @@
108
108
  "protobufjs": "^7.2.5",
109
109
  "retry": "^0.13.1",
110
110
  "rfdc": "^1.3.1",
111
- "semver": "^7.5.4",
111
+ "semifies": "^1.0.0",
112
112
  "shell-quote": "^1.8.1",
113
113
  "source-map": "^0.7.4",
114
114
  "tlhunter-sorted-set": "^0.1.0",
@@ -116,10 +116,10 @@
116
116
  },
117
117
  "devDependencies": {
118
118
  "@apollo/server": "^4.11.0",
119
- "@eslint/eslintrc": "^3.1.0",
120
- "@eslint/js": "^9.11.1",
119
+ "@eslint/eslintrc": "^3.2.0",
120
+ "@eslint/js": "^9.19.0",
121
121
  "@msgpack/msgpack": "^3.0.0-beta3",
122
- "@stylistic/eslint-plugin-js": "^2.8.0",
122
+ "@stylistic/eslint-plugin-js": "^3.0.1",
123
123
  "@types/node": "^16.0.0",
124
124
  "autocannon": "^4.5.2",
125
125
  "aws-sdk": "^2.1446.0",
@@ -132,12 +132,12 @@
132
132
  "cli-table3": "^0.6.3",
133
133
  "dotenv": "16.3.1",
134
134
  "esbuild": "0.16.12",
135
- "eslint": "^8.57.0",
135
+ "eslint": "^9.19.0",
136
136
  "eslint-config-standard": "^17.1.0",
137
- "eslint-plugin-import": "^2.29.1",
138
- "eslint-plugin-mocha": "^10.4.3",
139
- "eslint-plugin-n": "^16.6.2",
140
- "eslint-plugin-promise": "^6.4.0",
137
+ "eslint-plugin-import": "^2.31.0",
138
+ "eslint-plugin-mocha": "^10.5.0",
139
+ "eslint-plugin-n": "^17.15.1",
140
+ "eslint-plugin-promise": "^7.2.1",
141
141
  "express": "^4.21.2",
142
142
  "get-port": "^3.2.0",
143
143
  "glob": "^7.1.6",
@@ -152,6 +152,7 @@
152
152
  "nyc": "^15.1.0",
153
153
  "proxyquire": "^1.8.0",
154
154
  "rimraf": "^3.0.0",
155
+ "semver": "^7.5.4",
155
156
  "sinon": "^16.1.3",
156
157
  "sinon-chai": "^3.7.0",
157
158
  "tap": "^16.3.7",
@@ -1,5 +1,5 @@
1
1
  'use strict'
2
2
 
3
- const storage = require('./src/storage')
3
+ const { storage } = require('./src/storage')
4
4
 
5
5
  module.exports = { storage }
@@ -2,66 +2,111 @@
2
2
 
3
3
  const { AsyncLocalStorage } = require('async_hooks')
4
4
 
5
- class DatadogStorage {
6
- constructor () {
7
- this._storage = new AsyncLocalStorage()
8
- }
9
-
10
- disable () {
11
- this._storage.disable()
12
- }
13
-
5
+ /**
6
+ * This is exactly the same as AsyncLocalStorage, with the exception that it
7
+ * uses a WeakMap to store the store object. This is because ALS stores the
8
+ * store object as a property of the resource object, which causes all sorts
9
+ * of problems with logging and memory. We substitute the `store` object with
10
+ * a "handle" object, which is used as a key in a WeakMap, where the values
11
+ * are the real store objects.
12
+ *
13
+ * @template T
14
+ */
15
+ class DatadogStorage extends AsyncLocalStorage {
16
+ /**
17
+ *
18
+ * @param store {DatadogStorage}
19
+ */
14
20
  enterWith (store) {
15
21
  const handle = {}
16
22
  stores.set(handle, store)
17
- this._storage.enterWith(handle)
18
- }
19
-
20
- exit (callback, ...args) {
21
- this._storage.exit(callback, ...args)
23
+ super.enterWith(handle)
22
24
  }
23
25
 
24
- // TODO: Refactor the Scope class to use a span-only store and remove this.
26
+ /**
27
+ * This is method is a passthrough to the real `getStore()`, so that, when we
28
+ * need it, we can use the handle rather than our mapped store.
29
+ *
30
+ * It's only here because stores are currently used for a bunch of things,
31
+ * and we don't want to hold on to all of them in spans
32
+ * (see opentracing/span.js). Using a namespaced storage for spans would
33
+ * solve this.
34
+ *
35
+ * TODO: Refactor the Scope class to use a span-only store and remove this.
36
+ *
37
+ * @returns {{}}
38
+ */
25
39
  getHandle () {
26
- return this._storage.getStore()
40
+ return super.getStore()
27
41
  }
28
42
 
43
+ /**
44
+ * Here, we replicate the behavior of the original `getStore()` method by
45
+ * passing in the handle, which we retrieve by calling it on super. Handles
46
+ * retrieved through `getHandle()` can also be passed in to be used as the
47
+ * key. This is useful if you've stashed a handle somewhere and want to
48
+ * retrieve the store with it.
49
+ *
50
+ * @param handle {{}}
51
+ * @returns {T | undefined}
52
+ */
29
53
  getStore (handle) {
30
54
  if (!handle) {
31
- handle = this._storage.getStore()
55
+ handle = super.getStore()
32
56
  }
33
57
 
34
58
  return stores.get(handle)
35
59
  }
36
60
 
61
+ /**
62
+ * Here, we replicate the behavior of the original `run()` method. We ensure
63
+ * that our `enterWith()` is called internally, so that the handle to the
64
+ * store is set. As an optimization, we use super for getStore and enterWith
65
+ * when dealing with the parent store, so that we don't have to access the
66
+ * WeakMap.
67
+ * @template R
68
+ * @template TArgs extends any[]
69
+ * @param store {DatadogStorage}
70
+ * @param fn {() => R}
71
+ * @param args {TArgs}
72
+ * @returns {void}
73
+ */
37
74
  run (store, fn, ...args) {
38
- const prior = this._storage.getStore()
75
+ const prior = super.getStore()
39
76
  this.enterWith(store)
40
77
  try {
41
78
  return Reflect.apply(fn, null, args)
42
79
  } finally {
43
- this._storage.enterWith(prior)
80
+ super.enterWith(prior)
44
81
  }
45
82
  }
46
83
  }
47
84
 
85
+ /**
86
+ * This is the map from handles to real stores, used in the class above.
87
+ * @template T
88
+ * @type {WeakMap<WeakKey, T>}
89
+ */
90
+ const stores = new WeakMap()
91
+
92
+ /**
93
+ * For convenience, we use the `storage` function as a registry of namespaces
94
+ * corresponding to DatadogStorage instances. This lets us have separate
95
+ * storages for separate purposes.
96
+ * @type {Map<string, DatadogStorage>}
97
+ */
48
98
  const storages = Object.create(null)
49
- const legacyStorage = new DatadogStorage()
50
99
 
51
- const storage = function (namespace) {
100
+ /**
101
+ *
102
+ * @param namespace {string} the namespace to use
103
+ * @returns {DatadogStorage}
104
+ */
105
+ function storage (namespace) {
52
106
  if (!storages[namespace]) {
53
107
  storages[namespace] = new DatadogStorage()
54
108
  }
55
109
  return storages[namespace]
56
110
  }
57
111
 
58
- storage.disable = legacyStorage.disable.bind(legacyStorage)
59
- storage.enterWith = legacyStorage.enterWith.bind(legacyStorage)
60
- storage.exit = legacyStorage.exit.bind(legacyStorage)
61
- storage.getHandle = legacyStorage.getHandle.bind(legacyStorage)
62
- storage.getStore = legacyStorage.getStore.bind(legacyStorage)
63
- storage.run = legacyStorage.run.bind(legacyStorage)
64
-
65
- const stores = new WeakMap()
66
-
67
- module.exports = storage
112
+ module.exports = { storage }
@@ -22,6 +22,7 @@ const knownTestsCh = channel('ci:cucumber:known-tests')
22
22
  const skippableSuitesCh = channel('ci:cucumber:test-suite:skippable')
23
23
  const sessionStartCh = channel('ci:cucumber:session:start')
24
24
  const sessionFinishCh = channel('ci:cucumber:session:finish')
25
+ const quarantinedTestsCh = channel('ci:cucumber:quarantined-tests')
25
26
 
26
27
  const workerReportTraceCh = channel('ci:cucumber:worker-report:trace')
27
28
 
@@ -71,6 +72,8 @@ let earlyFlakeDetectionFaultyThreshold = 0
71
72
  let isEarlyFlakeDetectionFaulty = false
72
73
  let isFlakyTestRetriesEnabled = false
73
74
  let isKnownTestsEnabled = false
75
+ let isQuarantinedTestsEnabled = false
76
+ let quarantinedTests = {}
74
77
  let numTestRetries = 0
75
78
  let knownTests = []
76
79
  let skippedSuites = []
@@ -117,6 +120,17 @@ function isNewTest (testSuite, testName) {
117
120
  return !testsForSuite.includes(testName)
118
121
  }
119
122
 
123
+ function isQuarantinedTest (testSuite, testName) {
124
+ return quarantinedTests
125
+ ?.cucumber
126
+ ?.suites
127
+ ?.[testSuite]
128
+ ?.tests
129
+ ?.[testName]
130
+ ?.properties
131
+ ?.quarantined
132
+ }
133
+
120
134
  function getTestStatusFromRetries (testStatuses) {
121
135
  if (testStatuses.every(status => status === 'fail')) {
122
136
  return 'fail'
@@ -293,12 +307,17 @@ function wrapRun (pl, isLatestVersion) {
293
307
  }
294
308
  let isNew = false
295
309
  let isEfdRetry = false
310
+ let isQuarantined = false
296
311
  if (isKnownTestsEnabled && status !== 'skip') {
297
312
  const numRetries = numRetriesByPickleId.get(this.pickle.id)
298
313
 
299
314
  isNew = numRetries !== undefined
300
315
  isEfdRetry = numRetries > 0
301
316
  }
317
+ if (isQuarantinedTestsEnabled) {
318
+ const testSuitePath = getTestSuitePath(testFileAbsolutePath, process.cwd())
319
+ isQuarantined = isQuarantinedTest(testSuitePath, this.pickle.name)
320
+ }
302
321
  const attemptAsyncResource = numAttemptToAsyncResource.get(numAttempt)
303
322
 
304
323
  const error = getErrorFromCucumberResult(result)
@@ -307,7 +326,15 @@ function wrapRun (pl, isLatestVersion) {
307
326
  await promises.hitBreakpointPromise
308
327
  }
309
328
  attemptAsyncResource.runInAsyncScope(() => {
310
- testFinishCh.publish({ status, skipReason, error, isNew, isEfdRetry, isFlakyRetry: numAttempt > 0 })
329
+ testFinishCh.publish({
330
+ status,
331
+ skipReason,
332
+ error,
333
+ isNew,
334
+ isEfdRetry,
335
+ isFlakyRetry: numAttempt > 0,
336
+ isQuarantined
337
+ })
311
338
  })
312
339
  })
313
340
  return promise
@@ -396,6 +423,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
396
423
  isFlakyTestRetriesEnabled = configurationResponse.libraryConfig?.isFlakyTestRetriesEnabled
397
424
  numTestRetries = configurationResponse.libraryConfig?.flakyTestRetriesCount
398
425
  isKnownTestsEnabled = configurationResponse.libraryConfig?.isKnownTestsEnabled
426
+ isQuarantinedTestsEnabled = configurationResponse.libraryConfig?.isQuarantinedTestsEnabled
399
427
 
400
428
  if (isKnownTestsEnabled) {
401
429
  const knownTestsResponse = await getChannelPromise(knownTestsCh)
@@ -453,6 +481,15 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
453
481
  }
454
482
  }
455
483
 
484
+ if (isQuarantinedTestsEnabled) {
485
+ const quarantinedTestsResponse = await getChannelPromise(quarantinedTestsCh)
486
+ if (!quarantinedTestsResponse.err) {
487
+ quarantinedTests = quarantinedTestsResponse.quarantinedTests
488
+ } else {
489
+ isQuarantinedTestsEnabled = false
490
+ }
491
+ }
492
+
456
493
  const processArgv = process.argv.slice(2).join(' ')
457
494
  const command = process.env.npm_lifecycle_script || `cucumber-js ${processArgv}`
458
495
 
@@ -500,6 +537,7 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
500
537
  hasForcedToRunSuites: isForcedToRun,
501
538
  isEarlyFlakeDetectionEnabled,
502
539
  isEarlyFlakeDetectionFaulty,
540
+ isQuarantinedTestsEnabled,
503
541
  isParallel
504
542
  })
505
543
  })
@@ -536,6 +574,7 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
536
574
  }
537
575
 
538
576
  let isNew = false
577
+ let isQuarantined = false
539
578
 
540
579
  if (isKnownTestsEnabled) {
541
580
  isNew = isNewTest(testSuitePath, pickle.name)
@@ -543,6 +582,10 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
543
582
  numRetriesByPickleId.set(pickle.id, 0)
544
583
  }
545
584
  }
585
+ if (isQuarantinedTestsEnabled) {
586
+ isQuarantined = isQuarantinedTest(testSuitePath, pickle.name)
587
+ }
588
+
546
589
  // TODO: for >=11 we could use `runTestCaseResult` instead of accumulating results in `lastStatusByPickleId`
547
590
  let runTestCaseResult = await runTestCaseFunction.apply(this, arguments)
548
591
 
@@ -557,6 +600,7 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
557
600
  }
558
601
  let testStatus = lastTestStatus
559
602
  let shouldBePassedByEFD = false
603
+ let shouldBePassedByQuarantine = false
560
604
  if (isNew && isEarlyFlakeDetectionEnabled) {
561
605
  /**
562
606
  * If Early Flake Detection (EFD) is enabled the logic is as follows:
@@ -573,6 +617,11 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
573
617
  }
574
618
  }
575
619
 
620
+ if (isQuarantinedTestsEnabled && isQuarantined) {
621
+ this.success = true
622
+ shouldBePassedByQuarantine = true
623
+ }
624
+
576
625
  if (!pickleResultByFile[testFileAbsolutePath]) {
577
626
  pickleResultByFile[testFileAbsolutePath] = [testStatus]
578
627
  } else {
@@ -604,6 +653,10 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
604
653
  return shouldBePassedByEFD
605
654
  }
606
655
 
656
+ if (isNewerCucumberVersion && isQuarantinedTestsEnabled && isQuarantined) {
657
+ return shouldBePassedByQuarantine
658
+ }
659
+
607
660
  return runTestCaseResult
608
661
  }
609
662
  }
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const dc = require('dc-polyfill')
4
- const semver = require('semver')
4
+ const satisfies = require('semifies')
5
5
  const instrumentations = require('./instrumentations')
6
6
  const { AsyncResource } = require('async_hooks')
7
7
 
@@ -36,7 +36,7 @@ exports.addHook = function addHook ({ name, versions, file, filePattern }, hook)
36
36
 
37
37
  // AsyncResource.bind exists and binds `this` properly only from 17.8.0 and up.
38
38
  // https://nodejs.org/api/async_context.html#asyncresourcebindfn-thisarg
39
- if (semver.satisfies(process.versions.node, '>=17.8.0')) {
39
+ if (satisfies(process.versions.node, '>=17.8.0')) {
40
40
  exports.AsyncResource = AsyncResource
41
41
  } else {
42
42
  exports.AsyncResource = class extends AsyncResource {
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { channel } = require('dc-polyfill')
4
4
  const path = require('path')
5
- const semver = require('semver')
5
+ const satisfies = require('semifies')
6
6
  const Hook = require('./hook')
7
7
  const requirePackageJson = require('../../../dd-trace/src/require-package-json')
8
8
  const log = require('../../../dd-trace/src/log')
@@ -155,7 +155,7 @@ for (const packageName of names) {
155
155
  }
156
156
 
157
157
  function matchVersion (version, ranges) {
158
- return !version || (ranges && ranges.some(range => semver.satisfies(semver.coerce(version), range)))
158
+ return !version || (ranges && ranges.some(range => satisfies(version, range)))
159
159
  }
160
160
 
161
161
  function getVersion (moduleBaseDir) {