dd-trace 6.20.1 → 6.22.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.
- package/ci/diagnose.js +9 -14
- package/ci/init.js +1 -2
- package/ci/test-optimization-validation/ci-discovery.js +9 -4
- package/ci/test-optimization-validation/executable.js +1 -5
- package/ci/test-optimization-validation/framework-adapters/cypress.js +1 -4
- package/ci/test-optimization-validation/framework-adapters/vitest.js +1 -1
- package/ci/test-optimization-validation/generated-files.js +6 -4
- package/ci/test-optimization-validation/generated-test-contract.js +7 -3
- package/ci/test-optimization-validation/manifest-scaffold.js +7 -2
- package/ci/test-optimization-validation/manifest-schema.js +6 -7
- package/ci/test-optimization-validation/report-writer.js +6 -2
- package/ci/test-optimization-validation/runner-command.js +2 -4
- package/ci/test-optimization-validation/runner-contract.js +1 -2
- package/ci/test-optimization-validation/scenarios/auto-test-retries.js +1 -15
- package/ci/vitest-no-worker-init-setup.mjs +10 -7
- package/index.d.ts +116 -17
- package/initialize.mjs +1 -3
- package/openfeature/rules-based.d.ts +11 -0
- package/openfeature/rules-based.js +7 -0
- package/package.json +13 -11
- package/packages/datadog-core/src/storage.js +16 -0
- package/packages/datadog-esbuild/index.js +18 -12
- package/packages/datadog-instrumentations/src/aerospike.js +3 -3
- package/packages/datadog-instrumentations/src/ai.js +3 -3
- package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +0 -6
- package/packages/datadog-instrumentations/src/aws-sdk.js +21 -13
- package/packages/datadog-instrumentations/src/cassandra-driver.js +25 -20
- package/packages/datadog-instrumentations/src/claude-agent-sdk.js +9 -23
- package/packages/datadog-instrumentations/src/cucumber.js +48 -33
- package/packages/datadog-instrumentations/src/elasticsearch.js +1 -5
- package/packages/datadog-instrumentations/src/electron.js +6 -6
- package/packages/datadog-instrumentations/src/fastify.js +13 -4
- package/packages/datadog-instrumentations/src/fs.js +2 -2
- package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +9 -5
- package/packages/datadog-instrumentations/src/grpc/client.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +2 -2
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/register.js +36 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +87 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +5 -6
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +48 -31
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +64 -11
- package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +42 -4
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +7 -10
- package/packages/datadog-instrumentations/src/ioredis.js +7 -5
- package/packages/datadog-instrumentations/src/iovalkey.js +7 -5
- package/packages/datadog-instrumentations/src/jest.js +122 -11
- package/packages/datadog-instrumentations/src/knex.js +9 -5
- package/packages/datadog-instrumentations/src/mariadb-bundle.js +3 -3
- package/packages/datadog-instrumentations/src/mocha/common.js +20 -8
- package/packages/datadog-instrumentations/src/mocha/main.js +140 -43
- package/packages/datadog-instrumentations/src/mocha/utils.js +127 -38
- package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +61 -34
- package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
- package/packages/datadog-instrumentations/src/mongodb-core.js +3 -3
- package/packages/datadog-instrumentations/src/mongoose.js +3 -3
- package/packages/datadog-instrumentations/src/nova-sonic/audio.js +173 -0
- package/packages/datadog-instrumentations/src/nova-sonic/index.js +209 -0
- package/packages/datadog-instrumentations/src/nova-sonic/session.js +483 -0
- package/packages/datadog-instrumentations/src/openai-realtime/index.js +18 -6
- package/packages/datadog-instrumentations/src/openai-realtime/session.js +1 -1
- package/packages/datadog-instrumentations/src/openai.js +7 -0
- package/packages/datadog-instrumentations/src/pino.js +5 -6
- package/packages/datadog-instrumentations/src/playwright.js +3 -0
- package/packages/datadog-instrumentations/src/redis.js +27 -13
- package/packages/datadog-instrumentations/src/router.js +30 -0
- package/packages/datadog-instrumentations/src/rum-browser-scripts.js +2 -6
- package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +7 -5
- package/packages/datadog-instrumentations/src/vitest-main.js +9 -17
- package/packages/datadog-instrumentations/src/vitest-util.js +2 -2
- package/packages/datadog-instrumentations/src/vitest-worker.js +1 -2
- package/packages/datadog-instrumentations/src/vitest.js +2 -2
- package/packages/datadog-instrumentations/src/webdriverio.js +118 -21
- package/packages/datadog-instrumentations/src/ws.js +1 -4
- package/packages/datadog-plugin-amqplib/src/client.js +1 -2
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -5
- package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/handler.js +1 -2
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -8
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +18 -0
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/sonic.js +45 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +9 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -5
- package/packages/datadog-plugin-azure-durable-functions/src/index.js +5 -4
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -3
- package/packages/datadog-plugin-claude-agent-sdk/src/index.js +0 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +18 -5
- package/packages/datadog-plugin-cypress/src/index.js +6 -6
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +1 -2
- package/packages/datadog-plugin-cypress/src/support.js +1 -4
- package/packages/datadog-plugin-express/src/code_origin.js +1 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -2
- package/packages/datadog-plugin-graphql/src/execute.js +5 -5
- package/packages/datadog-plugin-grpc/src/util.js +1 -2
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -2
- package/packages/datadog-plugin-mocha/src/index.js +223 -39
- package/packages/datadog-plugin-mocha/src/webdriverio-video.js +453 -0
- package/packages/datadog-plugin-mongodb-core/src/query.js +8 -5
- package/packages/datadog-plugin-next/src/index.js +1 -2
- package/packages/datadog-plugin-openai/src/tracing.js +5 -2
- package/packages/datadog-plugin-openai-agents/src/integration.js +6 -2
- package/packages/datadog-plugin-openai-agents/src/processor.js +2 -4
- package/packages/datadog-plugin-postgres/src/index.js +24 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -5
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -4
- package/packages/datadog-plugin-vitest/src/index.js +5 -2
- package/packages/datadog-shimmer/src/shimmer.js +5 -4
- package/packages/datadog-webpack/index.js +55 -43
- package/packages/datadog-webpack/src/loader.js +56 -8
- package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -4
- package/packages/dd-trace/src/aiguard/messages/utils.js +1 -2
- package/packages/dd-trace/src/aiguard/redaction.js +8 -2
- package/packages/dd-trace/src/appsec/api_security/normalized-route.js +3 -2
- package/packages/dd-trace/src/appsec/api_security/sampler.js +2 -6
- package/packages/dd-trace/src/appsec/downstream_requests.js +1 -9
- package/packages/dd-trace/src/appsec/handlers/http-request.js +3 -9
- package/packages/dd-trace/src/appsec/handlers/http-response.js +7 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +1 -4
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +7 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -3
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -3
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +1 -6
- package/packages/dd-trace/src/appsec/lambda.js +1 -3
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +37 -27
- package/packages/dd-trace/src/appsec/rasp/lfi.js +9 -5
- package/packages/dd-trace/src/appsec/reporter.js +21 -1
- package/packages/dd-trace/src/appsec/stack_trace.js +1 -2
- package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +3 -6
- package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +13 -7
- package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +1 -2
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +2 -8
- package/packages/dd-trace/src/ci-visibility/resolve-runfile-path.js +54 -0
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +5 -8
- package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +2 -53
- package/packages/dd-trace/src/config/config-types.d.ts +2 -2
- package/packages/dd-trace/src/config/defaults.js +5 -5
- package/packages/dd-trace/src/config/generated-config-types.d.ts +8 -0
- package/packages/dd-trace/src/config/helper.js +34 -3
- package/packages/dd-trace/src/config/index.js +10 -9
- package/packages/dd-trace/src/config/normalize-service.js +1 -1
- package/packages/dd-trace/src/config/parsers.js +2 -2
- package/packages/dd-trace/src/config/supported-configurations.json +35 -0
- package/packages/dd-trace/src/datastreams/processor.js +3 -2
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -4
- package/packages/dd-trace/src/debugger/constants.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +5 -3
- package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +17 -12
- package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -2
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/worker-error.js +21 -0
- package/packages/dd-trace/src/debugger/guardrail-metrics.js +2 -2
- package/packages/dd-trace/src/debugger/index.js +24 -2
- package/packages/dd-trace/src/debugger/probe_sampler.js +108 -11
- package/packages/dd-trace/src/dogstatsd.js +1 -1
- package/packages/dd-trace/src/encode/tags-processors.js +2 -2
- package/packages/dd-trace/src/exporters/common/request.js +2 -5
- package/packages/dd-trace/src/exporters/common/url.js +1 -1
- package/packages/dd-trace/src/id.js +15 -5
- package/packages/dd-trace/src/lambda/handler.js +179 -19
- package/packages/dd-trace/src/lambda/index.js +15 -1
- package/packages/dd-trace/src/lambda/runtime/patch.js +34 -7
- package/packages/dd-trace/src/llmobs/agent-manifest.js +296 -0
- package/packages/dd-trace/src/llmobs/audio-utils.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +13 -0
- package/packages/dd-trace/src/llmobs/experiments/experiment.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/anthropic/index.js +15 -0
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +1 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +1 -3
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/nova-sonic.js +92 -0
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +56 -2
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +38 -0
- package/packages/dd-trace/src/llmobs/prompts/manager.js +5 -7
- package/packages/dd-trace/src/llmobs/prompts/prompt.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +23 -6
- package/packages/dd-trace/src/llmobs/span_processor.js +18 -8
- package/packages/dd-trace/src/llmobs/tagger.js +56 -3
- package/packages/dd-trace/src/llmobs/util.js +1 -2
- package/packages/dd-trace/src/llmobs/writers/base.js +7 -6
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -1
- package/packages/dd-trace/src/log/log.js +1 -5
- package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +30 -1
- package/packages/dd-trace/src/openfeature/configuration_source.js +17 -2
- package/packages/dd-trace/src/openfeature/debug-logging-hook.js +25 -0
- package/packages/dd-trace/src/openfeature/evaluation-telemetry-opt-out-hook.js +51 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +59 -3
- package/packages/dd-trace/src/openfeature/remote_config.js +9 -0
- package/packages/dd-trace/src/openfeature/writers/util.js +43 -4
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -2
- package/packages/dd-trace/src/opentelemetry/otlp/common.proto +1 -1
- package/packages/dd-trace/src/opentelemetry/resource-attributes.js +1 -1
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +6 -23
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +53 -13
- package/packages/dd-trace/src/otel-sampling.js +4 -5
- package/packages/dd-trace/src/otel-thread-ctx.js +81 -15
- package/packages/dd-trace/src/plugins/database.js +7 -16
- package/packages/dd-trace/src/plugins/util/git.js +9 -25
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +1 -5
- package/packages/dd-trace/src/plugins/util/test.js +48 -4
- package/packages/dd-trace/src/priority_sampler.js +1 -2
- package/packages/dd-trace/src/profiling/profiler.js +4 -6
- package/packages/dd-trace/src/profiling/profilers/wall.js +4 -10
- package/packages/dd-trace/src/proxy.js +3 -2
- package/packages/dd-trace/src/ritm.js +4 -2
- package/packages/dd-trace/src/serverless.js +10 -0
- package/packages/dd-trace/src/span_processor.js +13 -17
- package/packages/dd-trace/src/storage-channels.js +112 -46
- package/packages/dd-trace/src/telemetry/endpoints.js +1 -3
- package/packages/dd-trace/src/util.js +29 -0
- package/packages/dd-trace/src/web-tags-cache.js +6 -2
- package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/LICENSE +201 -0
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.d.ts +925 -0
- package/vendor/dist/@datadog/openfeature-node-server/rules-based/index.js +1 -0
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
|
@@ -12,11 +12,37 @@ const POSTGRES_SIMPLE_DBM_QUERIES = '__ddTracePostgresSimpleDbmQueries'
|
|
|
12
12
|
const POSTGRES_STATEMENT = 'this.string ?? (this.tagged && this.strings?.length !== 1 ? undefined : this.strings?.[0])'
|
|
13
13
|
|
|
14
14
|
module.exports = {
|
|
15
|
+
postgresQueryAcquire,
|
|
15
16
|
postgresQueryHandlers,
|
|
16
17
|
postgresQueryLifecycle,
|
|
17
18
|
postgresQueryPreparation,
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @param {object} state
|
|
23
|
+
* @param {import('estree').Program} program
|
|
24
|
+
*/
|
|
25
|
+
function postgresQueryAcquire (state, program) {
|
|
26
|
+
const channelVariable = injectPostgresTracingChannel(state, program)
|
|
27
|
+
const executeFunctions = query(program, 'FunctionDeclaration[id.name="execute"]')
|
|
28
|
+
assert(executeFunctions.length === 1, 'postgresQueryAcquire: unexpected execute function count')
|
|
29
|
+
|
|
30
|
+
const execute = executeFunctions[0]
|
|
31
|
+
const queryParameter = execute.params[0]
|
|
32
|
+
assert(queryParameter?.type === 'Identifier', 'postgresQueryAcquire: execute query parameter changed')
|
|
33
|
+
assert(execute.body.type === 'BlockStatement', 'postgresQueryAcquire: execute body changed')
|
|
34
|
+
|
|
35
|
+
const body = execute.body.body
|
|
36
|
+
const executeIndex = body.findIndex(statement => statement.type === 'TryStatement')
|
|
37
|
+
assert(executeIndex !== -1, 'postgresQueryAcquire: execute try block changed')
|
|
38
|
+
|
|
39
|
+
body.splice(executeIndex, 0, ...parse(`
|
|
40
|
+
if (${channelVariable}.start.hasSubscribers) {
|
|
41
|
+
${channelVariable}.start.publish({ query: ${queryParameter.name} });
|
|
42
|
+
}
|
|
43
|
+
`).body)
|
|
44
|
+
}
|
|
45
|
+
|
|
20
46
|
/**
|
|
21
47
|
* Starts a Postgres.js query at the pool handler that owns its connection options.
|
|
22
48
|
*
|
|
@@ -154,6 +180,7 @@ function wrapPostgresHandler (handler, queryParameter, channelVariable) {
|
|
|
154
180
|
assert(handler.body.type === 'BlockStatement', 'postgresQueryHandlers: handler body changed')
|
|
155
181
|
assert(!handler.async && !handler.generator, 'postgresQueryHandlers: unsupported handler kind')
|
|
156
182
|
|
|
183
|
+
// Direct handoffs publish before the handler returns, so they record zero pool wait.
|
|
157
184
|
const originalBody = handler.body.body
|
|
158
185
|
const wrapperBody = parse(`
|
|
159
186
|
function wrapper () {
|
|
@@ -167,12 +194,18 @@ function wrapPostgresHandler (handler, queryParameter, channelVariable) {
|
|
|
167
194
|
__ddTraceContext.host = ${POSTGRES_OPTIONS}.host[0];
|
|
168
195
|
__ddTraceContext.port = ${POSTGRES_OPTIONS}.port[0];
|
|
169
196
|
}
|
|
170
|
-
|
|
197
|
+
const __ddTraceResult = ${channelVariable}.start.runStores(__ddTraceContext, () => {});
|
|
198
|
+
if (!__ddTraceContext.poolWaitFinished) {
|
|
199
|
+
__ddTraceContext.poolWaitStartMs = performance.now();
|
|
200
|
+
}
|
|
201
|
+
return __ddTraceResult;
|
|
171
202
|
}
|
|
172
203
|
}
|
|
173
204
|
`).body[0].body.body
|
|
174
205
|
|
|
175
|
-
wrapperBody[0]
|
|
206
|
+
const tracingCalls = query(wrapperBody[0], 'CallExpression[callee.property.name="runStores"]')
|
|
207
|
+
assert(tracingCalls.length === 1, 'postgresQueryHandlers: runStores call changed')
|
|
208
|
+
tracingCalls[0].arguments[1].body.body = originalBody
|
|
176
209
|
handler.body.body = [...wrapperBody, ...originalBody]
|
|
177
210
|
}
|
|
178
211
|
|
|
@@ -272,8 +305,13 @@ function findPostgresQueryIdentifier (program) {
|
|
|
272
305
|
|
|
273
306
|
const declarations = query(program, 'VariableDeclarator[id.type="ObjectPattern"]')
|
|
274
307
|
for (const declaration of declarations) {
|
|
275
|
-
if (
|
|
276
|
-
|
|
308
|
+
if (
|
|
309
|
+
declaration.init?.type !== 'CallExpression' ||
|
|
310
|
+
declaration.init.callee.name !== 'require' ||
|
|
311
|
+
declaration.init.arguments[0]?.value !== './query.js'
|
|
312
|
+
) {
|
|
313
|
+
continue
|
|
314
|
+
}
|
|
277
315
|
|
|
278
316
|
for (const property of declaration.id.properties) {
|
|
279
317
|
if (property.type === 'Property' && property.key.name === 'Query' && property.value.type === 'Identifier') {
|
|
@@ -140,8 +140,7 @@ function awaitContextCallback (state, node, _parent, ancestry) {
|
|
|
140
140
|
const generatedCallback = createAwaitedContextCallback(
|
|
141
141
|
state,
|
|
142
142
|
insertionTarget,
|
|
143
|
-
callbackAncestry
|
|
144
|
-
'awaitContextCallback'
|
|
143
|
+
callbackAncestry
|
|
145
144
|
)
|
|
146
145
|
if (!generatedCallback) return
|
|
147
146
|
|
|
@@ -158,8 +157,7 @@ function awaitContextCallback (state, node, _parent, ancestry) {
|
|
|
158
157
|
const generatedCallback = createAwaitedContextCallback(
|
|
159
158
|
state,
|
|
160
159
|
node.consequent,
|
|
161
|
-
ancestry
|
|
162
|
-
'awaitContextCallback'
|
|
160
|
+
ancestry
|
|
163
161
|
)
|
|
164
162
|
if (!generatedCallback) return
|
|
165
163
|
|
|
@@ -181,18 +179,17 @@ function awaitContextCallback (state, node, _parent, ancestry) {
|
|
|
181
179
|
* @param {Parameters<typeof awaitContextCallback>[0]} state
|
|
182
180
|
* @param {import('estree').BlockStatement} insertionTarget
|
|
183
181
|
* @param {import('estree').Node[]} ancestry
|
|
184
|
-
* @param {string} transformName
|
|
185
182
|
* @returns {{
|
|
186
183
|
* callbackStatements: import('estree').Statement[],
|
|
187
184
|
* callbackVariable: string
|
|
188
185
|
* }|undefined}
|
|
189
186
|
*/
|
|
190
|
-
function createAwaitedContextCallback (state, insertionTarget, ancestry
|
|
187
|
+
function createAwaitedContextCallback (state, insertionTarget, ancestry) {
|
|
191
188
|
const { callbackArgumentNames = [], callbackName, callbackThis = false } = state.transformOptions ?? {}
|
|
192
189
|
|
|
193
|
-
assert(identifierPattern.test(callbackName),
|
|
190
|
+
assert(identifierPattern.test(callbackName), 'awaitContextCallback: callbackName must be an identifier')
|
|
194
191
|
assert(Array.isArray(callbackArgumentNames) && callbackArgumentNames.every(name => identifierPattern.test(name)),
|
|
195
|
-
|
|
192
|
+
'awaitContextCallback: callbackArgumentNames must be identifiers')
|
|
196
193
|
|
|
197
194
|
let enclosingFunction
|
|
198
195
|
let hasTraceWrapper = false
|
|
@@ -215,8 +212,8 @@ function createAwaitedContextCallback (state, insertionTarget, ancestry, transfo
|
|
|
215
212
|
hasTraceWrapper ||= hasContextBinding && hasTracedBinding
|
|
216
213
|
}
|
|
217
214
|
|
|
218
|
-
assert(enclosingFunction?.async,
|
|
219
|
-
assert(hasTraceWrapper,
|
|
215
|
+
assert(enclosingFunction?.async, 'awaitContextCallback: expected an enclosing async function')
|
|
216
|
+
assert(hasTraceWrapper, 'awaitContextCallback: expected an enclosing trace wrapper')
|
|
220
217
|
|
|
221
218
|
const callbackVariable = `__apm$${callbackName}`
|
|
222
219
|
if (query(insertionTarget, `[id.name="${callbackVariable}"]`).length > 0) return
|
|
@@ -14,9 +14,7 @@ const connectionOptionsCache = new WeakMap()
|
|
|
14
14
|
|
|
15
15
|
function wrapRedis (Redis) {
|
|
16
16
|
shimmer.wrap(Redis.prototype, 'sendCommand', sendCommand => function (command, stream) {
|
|
17
|
-
if (!startCh.hasSubscribers) return sendCommand.call(this, command, stream)
|
|
18
|
-
|
|
19
|
-
if (!command?.promise) return sendCommand.call(this, command, stream)
|
|
17
|
+
if (!startCh.hasSubscribers || !command?.promise) return sendCommand.call(this, command, stream)
|
|
20
18
|
|
|
21
19
|
const options = this.options || {}
|
|
22
20
|
let connectionOptions = connectionOptionsCache.get(this)
|
|
@@ -32,7 +30,7 @@ function wrapRedis (Redis) {
|
|
|
32
30
|
connectionName: options.connectionName,
|
|
33
31
|
}
|
|
34
32
|
return startCh.runStores(ctx, () => {
|
|
35
|
-
command.promise.then(() => finish(
|
|
33
|
+
command.promise.then(() => finish(ctx), err => finish(ctx, err))
|
|
36
34
|
|
|
37
35
|
return sendCommand.call(this, command, stream)
|
|
38
36
|
})
|
|
@@ -51,7 +49,11 @@ addHook({ name: 'ioredis', versions: ['>=4.11.0 <5'], file: 'built/redis/index.j
|
|
|
51
49
|
|
|
52
50
|
addHook({ name: 'ioredis', versions: ['>=5'] }, wrapRedis)
|
|
53
51
|
|
|
54
|
-
|
|
52
|
+
/**
|
|
53
|
+
* @param {Record<string, unknown> & { error?: Error }} ctx
|
|
54
|
+
* @param {Error} [error]
|
|
55
|
+
*/
|
|
56
|
+
function finish (ctx, error) {
|
|
55
57
|
if (error) {
|
|
56
58
|
ctx.error = error
|
|
57
59
|
errorCh.publish(ctx)
|
|
@@ -12,9 +12,7 @@ const errorCh = channel('apm:iovalkey:command:error')
|
|
|
12
12
|
|
|
13
13
|
addHook({ name: 'iovalkey', versions: ['>=0.0.1'] }, Valkey => {
|
|
14
14
|
shimmer.wrap(Valkey.prototype, 'sendCommand', sendCommand => function (command, stream) {
|
|
15
|
-
if (!startCh.hasSubscribers) return sendCommand.apply(this, arguments)
|
|
16
|
-
|
|
17
|
-
if (!command?.promise) return sendCommand.apply(this, arguments)
|
|
15
|
+
if (!startCh.hasSubscribers || !command?.promise) return sendCommand.apply(this, arguments)
|
|
18
16
|
|
|
19
17
|
const options = this.options || {}
|
|
20
18
|
const connectionName = options.connectionName
|
|
@@ -22,7 +20,7 @@ addHook({ name: 'iovalkey', versions: ['>=0.0.1'] }, Valkey => {
|
|
|
22
20
|
|
|
23
21
|
const ctx = { command: command.name, args: command.args, connectionOptions, connectionName }
|
|
24
22
|
return startCh.runStores(ctx, () => {
|
|
25
|
-
command.promise.then(() => finish(
|
|
23
|
+
command.promise.then(() => finish(ctx), err => finish(ctx, err))
|
|
26
24
|
|
|
27
25
|
try {
|
|
28
26
|
return sendCommand.apply(this, arguments)
|
|
@@ -37,7 +35,11 @@ addHook({ name: 'iovalkey', versions: ['>=0.0.1'] }, Valkey => {
|
|
|
37
35
|
return Valkey
|
|
38
36
|
})
|
|
39
37
|
|
|
40
|
-
|
|
38
|
+
/**
|
|
39
|
+
* @param {Record<string, unknown> & { error?: Error }} ctx
|
|
40
|
+
* @param {Error} [error]
|
|
41
|
+
*/
|
|
42
|
+
function finish (ctx, error) {
|
|
41
43
|
if (error) {
|
|
42
44
|
ctx.error = error
|
|
43
45
|
errorCh.publish(ctx)
|
|
@@ -10,6 +10,7 @@ const { performance } = require('node:perf_hooks')
|
|
|
10
10
|
const path = require('path')
|
|
11
11
|
const satisfies = require('../../../vendor/dist/semifies')
|
|
12
12
|
const { DD_MAJOR } = require('../../../version')
|
|
13
|
+
const { storage } = require('../../datadog-core')
|
|
13
14
|
const shimmer = require('../../datadog-shimmer')
|
|
14
15
|
const { getEnvironmentVariable, getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
15
16
|
const log = require('../../dd-trace/src/log')
|
|
@@ -88,6 +89,8 @@ const testSkippedCh = channel('ci:jest:test:skip')
|
|
|
88
89
|
const testFinishCh = channel('ci:jest:test:finish')
|
|
89
90
|
const testErrCh = channel('ci:jest:test:err')
|
|
90
91
|
const testFnCh = channel('ci:jest:test:fn')
|
|
92
|
+
const snapshotStorage = storage('ci:jest:snapshots')
|
|
93
|
+
let activeSnapshotTrackers = 0
|
|
91
94
|
const testSuiteHookFnCh = channel('ci:jest:test-suite:hook:fn')
|
|
92
95
|
const consoleLogSubmissionCh = channel('ci:log-submission:console')
|
|
93
96
|
const logSubmissionFlushCh = channel('ci:log-submission:flush')
|
|
@@ -666,7 +669,12 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
666
669
|
#discardedEfdRetryTests
|
|
667
670
|
#earlyFlakeDetectionRetryPolicy
|
|
668
671
|
#efdRetryGatesByName
|
|
672
|
+
#expect
|
|
669
673
|
#pendingPre30ConcurrentTests
|
|
674
|
+
/** @type {(() => void)|undefined} */
|
|
675
|
+
#restoreSnapshotState
|
|
676
|
+
/** @type {Set<string>|undefined} */
|
|
677
|
+
#snapshotTestNames
|
|
670
678
|
|
|
671
679
|
constructor (config, context) {
|
|
672
680
|
super(config, context)
|
|
@@ -883,8 +891,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
883
891
|
*/
|
|
884
892
|
wrapConcurrentTestFunction (target, methodName, state) {
|
|
885
893
|
let concurrentTest = target?.[methodName]
|
|
886
|
-
if (typeof concurrentTest !== 'function') return
|
|
887
|
-
if (this.wrappedConcurrentTestFunctions.has(concurrentTest)) return
|
|
894
|
+
if (typeof concurrentTest !== 'function' || this.wrappedConcurrentTestFunctions.has(concurrentTest)) return
|
|
888
895
|
|
|
889
896
|
const originalConcurrentTest = getOriginalConcurrentTest(concurrentTest)
|
|
890
897
|
if (originalConcurrentTest !== concurrentTest) {
|
|
@@ -1445,6 +1452,98 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
1445
1452
|
}
|
|
1446
1453
|
}
|
|
1447
1454
|
|
|
1455
|
+
getSnapshotState () {
|
|
1456
|
+
return this.#expect?.getState?.()?.snapshotState
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* Attributes snapshot increments to the executing test when serial and concurrent bodies can overlap.
|
|
1461
|
+
* Both Jest and image snapshot matchers write this shared counter directly.
|
|
1462
|
+
*/
|
|
1463
|
+
#trackQuarantinedSnapshots () {
|
|
1464
|
+
if (!this.hasConcurrentTests || !this.testManagementTestsForThisSuite?.quarantined?.length) return
|
|
1465
|
+
|
|
1466
|
+
const snapshotState = this.getSnapshotState()
|
|
1467
|
+
const descriptor = snapshotState && Object.getOwnPropertyDescriptor(snapshotState, 'unmatched')
|
|
1468
|
+
if (!descriptor?.configurable || typeof descriptor.value !== 'number') return
|
|
1469
|
+
|
|
1470
|
+
let unmatched = descriptor.value
|
|
1471
|
+
try {
|
|
1472
|
+
Object.defineProperty(snapshotState, 'unmatched', {
|
|
1473
|
+
configurable: true,
|
|
1474
|
+
enumerable: descriptor.enumerable,
|
|
1475
|
+
get () { return unmatched },
|
|
1476
|
+
/** @param {number} value */
|
|
1477
|
+
set (value) {
|
|
1478
|
+
const ctx = /** @type {{ unmatchedSnapshots?: number }|undefined} */ (snapshotStorage.getStore())
|
|
1479
|
+
if (ctx?.unmatchedSnapshots !== undefined && value > unmatched) {
|
|
1480
|
+
ctx.unmatchedSnapshots += value - unmatched
|
|
1481
|
+
}
|
|
1482
|
+
unmatched = value
|
|
1483
|
+
},
|
|
1484
|
+
})
|
|
1485
|
+
} catch (error) {
|
|
1486
|
+
log.error('Could not track quarantined Jest snapshots: %s', error)
|
|
1487
|
+
return
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
if (activeSnapshotTrackers++ === 0) testFnCh.bindStore(snapshotStorage)
|
|
1491
|
+
this.#restoreSnapshotState = () => {
|
|
1492
|
+
try {
|
|
1493
|
+
Object.defineProperty(snapshotState, 'unmatched', { ...descriptor, value: unmatched })
|
|
1494
|
+
} catch (error) {
|
|
1495
|
+
log.error('Could not restore Jest snapshot state: %s', error)
|
|
1496
|
+
} finally {
|
|
1497
|
+
if (--activeSnapshotTrackers === 0) testFnCh.unbindStore(snapshotStorage)
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
/**
|
|
1503
|
+
* Keeps the snapshot results of a quarantined test from failing the run.
|
|
1504
|
+
*
|
|
1505
|
+
* Jest fails the run on unmatched or obsolete snapshots even when no test failed.
|
|
1506
|
+
*
|
|
1507
|
+
* @param {object} test
|
|
1508
|
+
*/
|
|
1509
|
+
ignoreQuarantinedSnapshotResults (test) {
|
|
1510
|
+
const ctx = testContexts.get(test)
|
|
1511
|
+
const unmatchedBeforeTest = ctx?.unmatchedSnapshotsBeforeTest
|
|
1512
|
+
const unmatchedSnapshots = ctx?.unmatchedSnapshots
|
|
1513
|
+
// Jest retries the attempts that still have errors and resets their snapshot results itself.
|
|
1514
|
+
if ((unmatchedBeforeTest === undefined && unmatchedSnapshots === undefined) || test.errors?.length) return
|
|
1515
|
+
|
|
1516
|
+
const snapshotState = this.getSnapshotState()
|
|
1517
|
+
if (!snapshotState) return
|
|
1518
|
+
|
|
1519
|
+
if (unmatchedSnapshots !== undefined) {
|
|
1520
|
+
snapshotState.unmatched -= unmatchedSnapshots
|
|
1521
|
+
ctx.unmatchedSnapshots = 0
|
|
1522
|
+
} else if (snapshotState.unmatched > unmatchedBeforeTest) {
|
|
1523
|
+
snapshotState.unmatched = unmatchedBeforeTest
|
|
1524
|
+
}
|
|
1525
|
+
// Jest's name-based marker can consume other tests' keys, so delete only keys owned by this test.
|
|
1526
|
+
const keys = snapshotState._uncheckedKeys
|
|
1527
|
+
const testNames = this.#snapshotTestNames
|
|
1528
|
+
if (!keys?.delete || !testNames) return
|
|
1529
|
+
const testName = getRawJestTestName(test)
|
|
1530
|
+
const hintPrefix = `${testName}: `
|
|
1531
|
+
for (const key of keys) {
|
|
1532
|
+
const snapshotName = key.slice(0, key.lastIndexOf(' '))
|
|
1533
|
+
if (snapshotName !== testName && !snapshotName.startsWith(hintPrefix)) continue
|
|
1534
|
+
let belongsToAnotherTest = false
|
|
1535
|
+
// Snapshot names do not identify their owner when another registered name matches the same key.
|
|
1536
|
+
for (const name of testNames) {
|
|
1537
|
+
if (name !== testName &&
|
|
1538
|
+
(snapshotName === name || snapshotName.startsWith(`${name}: `))) {
|
|
1539
|
+
belongsToAnotherTest = true
|
|
1540
|
+
break
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
if (!belongsToAnotherTest) keys.delete(key)
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1448
1547
|
// This function returns an array if the known tests are valid and null otherwise.
|
|
1449
1548
|
getKnownTestsForSuite (suiteKnownTests) {
|
|
1450
1549
|
// `suiteKnownTests` is `this.testEnvironmentOptions._ddKnownTests`,
|
|
@@ -1819,6 +1918,11 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
1819
1918
|
if (event.concurrent) {
|
|
1820
1919
|
this.hasConcurrentTests = true
|
|
1821
1920
|
}
|
|
1921
|
+
const registeredTest = getTestEntries(state.currentDescribeBlock)?.at(-1)
|
|
1922
|
+
if (registeredTest && this.testManagementTestsForThisSuite?.quarantined?.length) {
|
|
1923
|
+
this.#snapshotTestNames ??= new Set()
|
|
1924
|
+
this.#snapshotTestNames.add(getRawJestTestName(registeredTest))
|
|
1925
|
+
}
|
|
1822
1926
|
if (event.failing) {
|
|
1823
1927
|
return
|
|
1824
1928
|
}
|
|
@@ -1827,7 +1931,6 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
1827
1931
|
const concurrentTestContexts = this.concurrentTestContexts.get(testFullName)
|
|
1828
1932
|
const concurrentTestState = this.concurrentTestStates.get(event.fn) ||
|
|
1829
1933
|
concurrentTestContexts?.at(-1)?.concurrentTestState
|
|
1830
|
-
const registeredTest = getTestEntries(state.currentDescribeBlock)?.at(-1)
|
|
1831
1934
|
if (concurrentTestState && registeredTest?.fn === event.fn) {
|
|
1832
1935
|
testContexts.set(registeredTest, concurrentTestState.ctx)
|
|
1833
1936
|
}
|
|
@@ -1925,10 +2028,12 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
1925
2028
|
}
|
|
1926
2029
|
|
|
1927
2030
|
if (event.name === 'run_start') {
|
|
2031
|
+
this.#trackQuarantinedSnapshots()
|
|
1928
2032
|
const registerResultHandler = dynamicAtrResultHandlerRegistrations.get(this)
|
|
1929
2033
|
dynamicAtrResultHandlerRegistrations.delete(this)
|
|
1930
2034
|
registerResultHandler?.()
|
|
1931
2035
|
} else if (event.name === 'setup') {
|
|
2036
|
+
this.#expect = event.runtimeGlobals?.expect ?? this.global.expect
|
|
1932
2037
|
this.wrapConcurrentTest(state)
|
|
1933
2038
|
this.bindTestEach(this.global.test)
|
|
1934
2039
|
}
|
|
@@ -2044,6 +2149,13 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
2044
2149
|
ctx.concurrentTestState = concurrentTestState
|
|
2045
2150
|
concurrentTestState.ctx = ctx
|
|
2046
2151
|
}
|
|
2152
|
+
if (isQuarantined && !isAttemptToFix && !event.test.concurrent && !ctx.concurrentTestState) {
|
|
2153
|
+
if (this.#restoreSnapshotState) {
|
|
2154
|
+
ctx.unmatchedSnapshots = 0
|
|
2155
|
+
} else if (!this.hasConcurrentTests) {
|
|
2156
|
+
ctx.unmatchedSnapshotsBeforeTest = this.getSnapshotState()?.unmatched
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2047
2159
|
testContexts.set(event.test, ctx)
|
|
2048
2160
|
|
|
2049
2161
|
if (isAttemptToFix) {
|
|
@@ -2282,6 +2394,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
2282
2394
|
event.test.errors = []
|
|
2283
2395
|
}
|
|
2284
2396
|
}
|
|
2397
|
+
this.ignoreQuarantinedSnapshotResults(event.test)
|
|
2285
2398
|
|
|
2286
2399
|
// Quarantine must consume terminal failures before we save errors for Jest's final result.
|
|
2287
2400
|
if (dynamicAtrCount !== undefined && failedAllTests && event.test.errors?.length) {
|
|
@@ -2359,6 +2472,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
2359
2472
|
ctx.currentStore = undefined
|
|
2360
2473
|
}
|
|
2361
2474
|
} else if (event.name === 'run_finish') {
|
|
2475
|
+
this.#restoreSnapshotState?.()
|
|
2476
|
+
this.#restoreSnapshotState = undefined
|
|
2362
2477
|
this.removeDiscardedEfdRetries()
|
|
2363
2478
|
for (const [test, errors] of atrSuppressedErrors) {
|
|
2364
2479
|
// Do not restore errors for non-ATF quarantined tests — they should stay suppressed
|
|
@@ -2528,6 +2643,8 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
2528
2643
|
}
|
|
2529
2644
|
|
|
2530
2645
|
teardown () {
|
|
2646
|
+
this.#restoreSnapshotState?.()
|
|
2647
|
+
this.#restoreSnapshotState = undefined
|
|
2531
2648
|
if (this._globalProxy?.propertyToValue) {
|
|
2532
2649
|
for (const [key] of this._globalProxy.propertyToValue) {
|
|
2533
2650
|
if (typeof key === 'string' && key.startsWith('_dd')) {
|
|
@@ -2557,10 +2674,7 @@ function getTestEnvironment (pkg, jestVersion) {
|
|
|
2557
2674
|
const wrappedTestEnvironment = getWrappedEnvironment(pkg.default, jestVersion)
|
|
2558
2675
|
return new Proxy(pkg, {
|
|
2559
2676
|
get (target, prop) {
|
|
2560
|
-
if (prop === 'default') {
|
|
2561
|
-
return wrappedTestEnvironment
|
|
2562
|
-
}
|
|
2563
|
-
if (prop === 'TestEnvironment') {
|
|
2677
|
+
if (prop === 'default' || prop === 'TestEnvironment') {
|
|
2564
2678
|
return wrappedTestEnvironment
|
|
2565
2679
|
}
|
|
2566
2680
|
return target[prop]
|
|
@@ -4377,10 +4491,7 @@ function sendWrapper (send) {
|
|
|
4377
4491
|
// In here we modify the `config.testEnvironmentOptions` to include the known tests for the suite.
|
|
4378
4492
|
// This way the suite only knows about the tests that are part of it.
|
|
4379
4493
|
const args = request.at(-1)
|
|
4380
|
-
if (args.length > 1) {
|
|
4381
|
-
return send.apply(this, arguments)
|
|
4382
|
-
}
|
|
4383
|
-
if (!args[0]?.config) {
|
|
4494
|
+
if (args.length > 1 || !args[0]?.config) {
|
|
4384
4495
|
return send.apply(this, arguments)
|
|
4385
4496
|
}
|
|
4386
4497
|
const [{ globalConfig, config, path: testSuiteAbsolutePath }] = args
|
|
@@ -62,13 +62,13 @@ addHook({
|
|
|
62
62
|
const rawResult = raw.apply(this, args)
|
|
63
63
|
shimmer.wrap(rawResult, 'then', originalThen => function (...args) {
|
|
64
64
|
return rawQuerySubscribes.runStores(context, () => {
|
|
65
|
-
args[0] = wrapCallbackWithFinish(args[0],
|
|
66
|
-
if (args[1]) args[1] = wrapCallbackWithFinish(args[1],
|
|
65
|
+
args[0] = wrapCallbackWithFinish(args[0], context)
|
|
66
|
+
if (args[1]) args[1] = wrapCallbackWithFinish(args[1], context)
|
|
67
67
|
|
|
68
68
|
const originalThenResult = originalThen.apply(this, args)
|
|
69
69
|
|
|
70
70
|
shimmer.wrap(originalThenResult, 'catch', originalCatch => function (...args) {
|
|
71
|
-
args[0] = wrapCallbackWithFinish(args[0],
|
|
71
|
+
args[0] = wrapCallbackWithFinish(args[0], context)
|
|
72
72
|
return originalCatch.apply(this, args)
|
|
73
73
|
})
|
|
74
74
|
|
|
@@ -78,7 +78,7 @@ addHook({
|
|
|
78
78
|
|
|
79
79
|
shimmer.wrap(rawResult, 'asCallback', originalAsCallback => function (...args) {
|
|
80
80
|
return rawQuerySubscribes.runStores(context, () => {
|
|
81
|
-
args[0] = wrapCallbackWithFinish(args[0],
|
|
81
|
+
args[0] = wrapCallbackWithFinish(args[0], context)
|
|
82
82
|
return originalAsCallback.apply(this, args)
|
|
83
83
|
})
|
|
84
84
|
})
|
|
@@ -118,7 +118,11 @@ addHook({
|
|
|
118
118
|
return Transaction
|
|
119
119
|
})
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
/**
|
|
122
|
+
* @param {unknown} callback
|
|
123
|
+
* @param {object} context
|
|
124
|
+
*/
|
|
125
|
+
function wrapCallbackWithFinish (callback, context) {
|
|
122
126
|
if (typeof callback !== 'function') return callback
|
|
123
127
|
|
|
124
128
|
return shimmer.wrapFunction(callback, callback => function (...args) {
|
|
@@ -1055,9 +1055,9 @@ function createWrapCallbackGetConnection (options) {
|
|
|
1055
1055
|
return function wrapGetConnection (getConnection) {
|
|
1056
1056
|
return function () {
|
|
1057
1057
|
const callback = arguments[arguments.length - 1]
|
|
1058
|
-
if (typeof callback !== 'function'
|
|
1059
|
-
|
|
1060
|
-
|
|
1058
|
+
if (typeof callback !== 'function' || !connectionStartCh.hasSubscribers) {
|
|
1059
|
+
return getConnection.apply(this, arguments)
|
|
1060
|
+
}
|
|
1061
1061
|
|
|
1062
1062
|
if (!acquireStartCh.hasSubscribers) {
|
|
1063
1063
|
const ctx = {}
|
|
@@ -11,33 +11,45 @@ const MINIMUM_MOCHA_VERSION = DD_MAJOR >= 6 ? '>=8.0.0' : '>=5.2.0'
|
|
|
11
11
|
const parameterizedTestCh = channel('ci:mocha:test:parameterize')
|
|
12
12
|
const patched = new WeakSet()
|
|
13
13
|
|
|
14
|
+
/** @typedef {{ moduleBaseDir?: string }} MochaHookMeta */
|
|
15
|
+
|
|
14
16
|
/**
|
|
15
17
|
* Registers every Mocha package view that can expose the constructor.
|
|
16
18
|
*
|
|
17
19
|
* @param {string[]} versions
|
|
18
|
-
* @param {(Mocha: Function, frameworkVersion: string) => Function} wrapMochaRun
|
|
20
|
+
* @param {(Mocha: Function, frameworkVersion: string, hookMeta: MochaHookMeta) => Function} wrapMochaRun
|
|
19
21
|
*/
|
|
20
22
|
function addMochaRunHooks (versions, wrapMochaRun) {
|
|
21
|
-
const patchedMochaConstructors = new
|
|
23
|
+
const patchedMochaConstructors = new WeakMap()
|
|
22
24
|
|
|
23
25
|
/**
|
|
24
26
|
* @param {Function} Mocha
|
|
25
27
|
* @param {string} frameworkVersion
|
|
28
|
+
* @param {boolean | undefined} isIitm
|
|
29
|
+
* @param {{ moduleBaseDir: string } | undefined} hookMeta
|
|
26
30
|
* @returns {Function}
|
|
27
31
|
*/
|
|
28
|
-
function wrapMochaOnce (Mocha, frameworkVersion) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
function wrapMochaOnce (Mocha, frameworkVersion, isIitm, hookMeta) {
|
|
33
|
+
let metadata = patchedMochaConstructors.get(Mocha)
|
|
34
|
+
if (metadata) {
|
|
35
|
+
// A bundler can expose the constructor before an ordinary loader supplies its package directory.
|
|
36
|
+
metadata.moduleBaseDir ??= hookMeta?.moduleBaseDir
|
|
37
|
+
return Mocha
|
|
38
|
+
}
|
|
39
|
+
metadata = { moduleBaseDir: hookMeta?.moduleBaseDir }
|
|
40
|
+
patchedMochaConstructors.set(Mocha, metadata)
|
|
41
|
+
return wrapMochaRun(Mocha, frameworkVersion, metadata)
|
|
32
42
|
}
|
|
33
43
|
|
|
34
44
|
/**
|
|
35
45
|
* @param {object|Function} MochaPackage
|
|
36
46
|
* @param {string} frameworkVersion
|
|
47
|
+
* @param {boolean | undefined} isIitm
|
|
48
|
+
* @param {{ moduleBaseDir: string } | undefined} hookMeta
|
|
37
49
|
* @returns {object|Function}
|
|
38
50
|
*/
|
|
39
|
-
function wrapMochaPackage (MochaPackage, frameworkVersion) {
|
|
40
|
-
wrapMochaOnce(MochaPackage.default ?? MochaPackage, frameworkVersion)
|
|
51
|
+
function wrapMochaPackage (MochaPackage, frameworkVersion, isIitm, hookMeta) {
|
|
52
|
+
wrapMochaOnce(MochaPackage.default ?? MochaPackage, frameworkVersion, isIitm, hookMeta)
|
|
41
53
|
return MochaPackage
|
|
42
54
|
}
|
|
43
55
|
|