@teamscale/lib-instrument 1.0.0-beta.6 → 1.0.0-beta.7

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/lib/index.d.ts CHANGED
@@ -1,10 +1,5 @@
1
1
  import { Instrumenter, InstrumenterOptions } from './instrumenter';
2
2
  export type { InstrumenterOptions } from './instrumenter';
3
3
  export { programVisitor } from './visitor';
4
- /**
5
- * Creates a new coverage instrumenter.
6
- *
7
- * @param opts - instrumenter options
8
- */
9
4
  export declare function createInstrumenter(opts: InstrumenterOptions): Instrumenter;
10
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,mBAAmB,EAAC,MAAM,gBAAgB,CAAC;AAEjE,YAAY,EAAC,mBAAmB,EAAC,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAC,cAAc,EAAC,MAAM,WAAW,CAAC;AAEzC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,YAAY,CAE1E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,mBAAmB,EAAC,MAAM,gBAAgB,CAAC;AAEjE,YAAY,EAAC,mBAAmB,EAAC,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAC,cAAc,EAAC,MAAM,WAAW,CAAC;AAOzC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,YAAY,CAE1E"}
package/lib/index.js CHANGED
@@ -5,11 +5,6 @@ exports.createInstrumenter = createInstrumenter;
5
5
  const instrumenter_1 = require("./instrumenter");
6
6
  var visitor_1 = require("./visitor");
7
7
  Object.defineProperty(exports, "programVisitor", { enumerable: true, get: function () { return visitor_1.programVisitor; } });
8
- /**
9
- * Creates a new coverage instrumenter.
10
- *
11
- * @param opts - instrumenter options
12
- */
13
8
  function createInstrumenter(opts) {
14
9
  return new instrumenter_1.Instrumenter(opts);
15
10
  }
@@ -3,43 +3,18 @@ import { SourceLocation } from "@babel/types";
3
3
  import { ParserPlugin as PluginConfig } from '@babel/parser';
4
4
  import { RawSourceMap } from "source-map";
5
5
  import { InstrumentationOptions } from "./utils";
6
- /**
7
- * Options for configuring the coverage instrumenter.
8
- */
9
6
  export type InstrumenterOptions = InstrumentationOptions & Partial<{
10
- /** Preserve comments in output */
11
7
  preserveComments: boolean;
12
- /** Generate compact code */
13
8
  compact: boolean;
14
- /** Set to true to instrument ES6 modules */
15
9
  esModules: boolean;
16
- /** Set to true to allow `return` statements outside of functions */
17
10
  autoWrap: boolean;
18
- /** Approach to produce a source map for the instrumented code */
19
11
  produceSourceMap: 'none' | 'inline' | 'external';
20
- /** Turn debugging on */
21
12
  debug: boolean;
22
- /** Set babel parser plugins */
23
13
  parserPlugins: PluginConfig[];
24
14
  }>;
25
- /**
26
- * The main class of the instrumenter.
27
- */
28
15
  export declare class Instrumenter {
29
16
  private readonly opts;
30
17
  constructor(opts?: Partial<InstrumenterOptions>);
31
- /**
32
- * Instrument the supplied code with coverage statements.
33
- * To instrument EcmaScript modules, make sure to set the
34
- * `esModules` option to `true` when creating the instrumenter.
35
- *
36
- * @param code - the code to instrument
37
- * @param filename - the name of the file the code stems from.
38
- * @param inputSourceMap - the source map that maps the not instrumented code back to its original
39
- * @param shouldInstrumentCallback - a callback to decide if a given code fragment should be instrumented
40
- *
41
- * @returns the instrumented code.
42
- */
43
18
  instrument(code: string, filename: string | undefined, inputSourceMap: RawSourceMap | undefined, shouldInstrumentCallback?: (path: NodePath, location: SourceLocation) => boolean): Promise<string>;
44
19
  }
45
20
  //# sourceMappingURL=instrumenter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrumenter.d.ts","sourceRoot":"","sources":["../src/instrumenter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,QAAQ,EAAgB,MAAM,aAAa,CAAC;AACpD,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAC,YAAY,IAAI,YAAY,EAAC,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAoB,MAAM,YAAY,CAAC;AAG3D,OAAO,EAAC,sBAAsB,EAAC,MAAM,SAAS,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,sBAAsB,GAAG,OAAO,CAAC;IAC/D,kCAAkC;IAClC,gBAAgB,EAAE,OAAO,CAAC;IAE1B,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IAEjB,4CAA4C;IAC5C,SAAS,EAAE,OAAO,CAAC;IAEnB,oEAAoE;IACpE,QAAQ,EAAE,OAAO,CAAC;IAElB,iEAAiE;IACjE,gBAAgB,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEjD,wBAAwB;IACxB,KAAK,EAAE,OAAO,CAAC;IAEf,+BAA+B;IAC/B,aAAa,EAAE,YAAY,EAAE,CAAC;CACjC,CAAC,CAAC;AAYH;;GAEG;AACH,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;gBAE/B,IAAI,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAI/C;;;;;;;;;;;OAWG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,cAAc,EAAE,YAAY,GAAG,SAAS,EACpF,wBAAwB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CA0DtH"}
1
+ {"version":3,"file":"instrumenter.d.ts","sourceRoot":"","sources":["../src/instrumenter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,QAAQ,EAAgB,MAAM,aAAa,CAAC;AACpD,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAC,YAAY,IAAI,YAAY,EAAC,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAoB,MAAM,YAAY,CAAC;AAG3D,OAAO,EAAC,sBAAsB,EAAC,MAAM,SAAS,CAAC;AAK/C,MAAM,MAAM,mBAAmB,GAAG,sBAAsB,GAAG,OAAO,CAAC;IAE/D,gBAAgB,EAAE,OAAO,CAAC;IAG1B,OAAO,EAAE,OAAO,CAAC;IAGjB,SAAS,EAAE,OAAO,CAAC;IAGnB,QAAQ,EAAE,OAAO,CAAC;IAGlB,gBAAgB,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IAGjD,KAAK,EAAE,OAAO,CAAC;IAGf,aAAa,EAAE,YAAY,EAAE,CAAC;CACjC,CAAC,CAAC;AAeH,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;gBAE/B,IAAI,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAgBzC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,cAAc,EAAE,YAAY,GAAG,SAAS,EACpF,wBAAwB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CA0DtH"}
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Instrumenter = void 0;
4
- /*
5
- Copyright 2012-2015, Yahoo Inc.
6
- Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
7
- */
8
4
  const core_1 = require("@babel/core");
9
5
  const source_map_1 = require("source-map");
10
6
  const visitor_1 = require("./visitor");
@@ -17,29 +13,15 @@ function mapSourceMapsOption(produceSourceMap) {
17
13
  }
18
14
  return produceSourceMap;
19
15
  }
20
- /**
21
- * The main class of the instrumenter.
22
- */
23
16
  class Instrumenter {
17
+ opts;
24
18
  constructor(opts) {
25
19
  this.opts = { ...opts };
26
20
  }
27
- /**
28
- * Instrument the supplied code with coverage statements.
29
- * To instrument EcmaScript modules, make sure to set the
30
- * `esModules` option to `true` when creating the instrumenter.
31
- *
32
- * @param code - the code to instrument
33
- * @param filename - the name of the file the code stems from.
34
- * @param inputSourceMap - the source map that maps the not instrumented code back to its original
35
- * @param shouldInstrumentCallback - a callback to decide if a given code fragment should be instrumented
36
- *
37
- * @returns the instrumented code.
38
- */
39
21
  async instrument(code, filename, inputSourceMap, shouldInstrumentCallback) {
40
- filename = filename !== null && filename !== void 0 ? filename : String(new Date().getTime()) + '.js';
22
+ filename = filename ?? String(new Date().getTime()) + '.js';
41
23
  const { opts } = this;
42
- const sourceMapToUse = inputSourceMap !== null && inputSourceMap !== void 0 ? inputSourceMap : opts.inputSourceMap;
24
+ const sourceMapToUse = inputSourceMap ?? opts.inputSourceMap;
43
25
  let inputSourceMapConsumer = undefined;
44
26
  if (sourceMapToUse) {
45
27
  inputSourceMapConsumer = await new source_map_1.SourceMapConsumer(sourceMapToUse);
@@ -69,7 +51,7 @@ class Instrumenter {
69
51
  inputSourceMap,
70
52
  isInstrumentedToken: opts.isInstrumentedToken,
71
53
  codeToPrepend: opts.codeToPrepend,
72
- shouldInstrumentCallback: shouldInstrumentCallback !== null && shouldInstrumentCallback !== void 0 ? shouldInstrumentCallback : opts.shouldInstrumentCallback
54
+ shouldInstrumentCallback: shouldInstrumentCallback ?? opts.shouldInstrumentCallback
73
55
  });
74
56
  return {
75
57
  visitor: {
package/lib/origins.d.ts CHANGED
@@ -1,32 +1,12 @@
1
1
  import { SourceLocation } from "@babel/types";
2
2
  import { SourceMapConsumer } from "source-map";
3
- /**
4
- * Generator for identifiers that are unique across files to instrument.
5
- * Relevant in case no Ecmascript modules are used.
6
- *
7
- * We assume that the files to be executed in a browser can
8
- * stem from different runs of the instrumenter. We have to decrease
9
- * the probability of colliding identifiers.
10
- */
11
3
  export declare const fileIdSeqGenerator: {
12
4
  next: () => string;
13
5
  };
14
- /**
15
- * Mapping source locations to their origins, before the last transpilation,
16
- * based on the source map.
17
- */
18
6
  export declare class SourceOrigins {
19
7
  private readonly sourceMap?;
20
- /**
21
- * The mapping of file ids to the file names in the transpiler origin,
22
- * that is, the file names found in the source map.
23
- */
24
8
  readonly originToIdMap: Map<string, string>;
25
9
  constructor(sourceMap: SourceMapConsumer | undefined);
26
- /**
27
- * Register source origin file and retrieve a unique identifier for it; furthermore, map
28
- * the given location to the location in the origin.
29
- */
30
10
  ensureKnownOrigin(loc: SourceLocation): [string, SourceLocation];
31
11
  }
32
12
  //# sourceMappingURL=origins.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"origins.d.ts","sourceRoot":"","sources":["../src/origins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAyB,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAErE;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE;IAAE,IAAI,EAAE,MAAM,MAAM,CAAA;CAkBjD,CAAC;AAEL;;;GAGG;AACH,qBAAa,aAAa;IAEtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAoB;IAE/C;;;OAGG;IACH,SAAgB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAEvC,SAAS,EAAE,iBAAiB,GAAG,SAAS;IAKpD;;;OAGG;IACH,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC;CA6BnE"}
1
+ {"version":3,"file":"origins.d.ts","sourceRoot":"","sources":["../src/origins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAyB,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAUrE,eAAO,MAAM,kBAAkB,EAAE;IAAE,IAAI,EAAE,MAAM,MAAM,CAAA;CAkBjD,CAAC;AAML,qBAAa,aAAa;IAEtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAoB;IAM/C,SAAgB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAEvC,SAAS,EAAE,iBAAiB,GAAG,SAAS;IASpD,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC;CA6BnE"}
package/lib/origins.js CHANGED
@@ -1,14 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SourceOrigins = exports.fileIdSeqGenerator = void 0;
4
- /**
5
- * Generator for identifiers that are unique across files to instrument.
6
- * Relevant in case no Ecmascript modules are used.
7
- *
8
- * We assume that the files to be executed in a browser can
9
- * stem from different runs of the instrumenter. We have to decrease
10
- * the probability of colliding identifiers.
11
- */
12
4
  exports.fileIdSeqGenerator = (() => {
13
5
  const instrumenterRunId = process.pid;
14
6
  let fileIdSeq = 0;
@@ -29,28 +21,21 @@ exports.fileIdSeqGenerator = (() => {
29
21
  }
30
22
  };
31
23
  })();
32
- /**
33
- * Mapping source locations to their origins, before the last transpilation,
34
- * based on the source map.
35
- */
36
24
  class SourceOrigins {
25
+ sourceMap;
26
+ originToIdMap;
37
27
  constructor(sourceMap) {
38
28
  this.originToIdMap = new Map();
39
29
  this.sourceMap = sourceMap;
40
30
  }
41
- /**
42
- * Register source origin file and retrieve a unique identifier for it; furthermore, map
43
- * the given location to the location in the origin.
44
- */
45
31
  ensureKnownOrigin(loc) {
46
- var _a, _b;
47
32
  let startPos = undefined;
48
33
  let endPos = undefined;
49
- let filename = (_a = loc.filename) !== null && _a !== void 0 ? _a : '';
34
+ let filename = loc.filename ?? '';
50
35
  if (this.sourceMap) {
51
36
  startPos = this.sourceMap.originalPositionFor({ line: loc.start.line, column: loc.start.column });
52
37
  endPos = this.sourceMap.originalPositionFor({ line: loc.end.line, column: loc.end.column });
53
- filename = (_b = startPos.source) !== null && _b !== void 0 ? _b : loc.filename;
38
+ filename = startPos.source ?? loc.filename;
54
39
  }
55
40
  if (!startPos || !endPos) {
56
41
  startPos = { line: loc.start.line, column: loc.start.column, source: null, name: null };
package/lib/utils.d.ts CHANGED
@@ -1,28 +1,15 @@
1
1
  import { SourceLocation } from "@babel/types";
2
2
  import { RawSourceMap } from "source-map";
3
3
  import { NodePath } from "@babel/core";
4
- /**
5
- * Options to configure the instrumenter.
6
- */
7
4
  export type InstrumentationOptions = Partial<{
8
- /** Report boolean value of logical expressions */
9
5
  reportLogic: boolean;
10
- /** Use an evaluated function to find coverageGlobalScope */
11
6
  coverageGlobalScopeFunc: boolean;
12
- /** Names of methods to ignore by default on classes */
13
7
  ignoreClassMethods: string[];
14
- /** The input source map, that maps the uninstrumented code back to the original code */
15
8
  inputSourceMap?: RawSourceMap;
16
- /** Token to add in the very beginning to indicate that the instrumentation has been performed */
17
9
  isInstrumentedToken?: string;
18
- /** Code to add before the instrumented input code */
19
10
  codeToPrepend?: string;
20
- /** Callback for determining if a given code fragment should be instrument */
21
11
  shouldInstrumentCallback?: (path: NodePath, loc: SourceLocation) => boolean;
22
12
  }>;
23
- /**
24
- * Source code fragment within on file.
25
- */
26
13
  export type CodeRange = {
27
14
  start: {
28
15
  line?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AACxC,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC;IACzC,kDAAkD;IAClD,WAAW,EAAE,OAAO,CAAC;IAErB,4DAA4D;IAC5D,uBAAuB,EAAE,OAAO,CAAC;IAEjC,uDAAuD;IACvD,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAE7B,wFAAwF;IACxF,cAAc,CAAC,EAAE,YAAY,CAAC;IAE9B,iGAAiG;IACjG,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,6EAA6E;IAC7E,wBAAwB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC;CAC/E,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACpB,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,GAAG,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AACxC,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAKrC,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC;IAEzC,WAAW,EAAE,OAAO,CAAC;IAGrB,uBAAuB,EAAE,OAAO,CAAC;IAGjC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAG7B,cAAc,CAAC,EAAE,YAAY,CAAC;IAG9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAG7B,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,wBAAwB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC;CAC/E,CAAC,CAAC;AAKH,MAAM,MAAM,SAAS,GAAG;IACpB,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,GAAG,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C,CAAC"}
package/lib/visitor.d.ts CHANGED
@@ -3,25 +3,6 @@ import { Program } from "@babel/types";
3
3
  type BabelTypes = typeof import("@babel/types");
4
4
  import { SourceMapConsumer } from "source-map";
5
5
  import { InstrumentationOptions } from "./utils";
6
- /**
7
- * `programVisitor` is a `babel` adaptor for instrumentation.
8
- *
9
- * It returns an object with two methods `enter` and `exit`.
10
- * These should be assigned to or called from `Program` entry and exit functions
11
- * in a babel visitor.
12
- *
13
- * These functions do not make assumptions about the state set by Babel and thus
14
- * can be used in a context other than a Babel plugin.
15
- *
16
- * The exit function returns an object that currently has the following keys:
17
- *
18
- * `fileCoverage` - the file coverage object created for the source file.
19
- * `sourceMappingURL` - any source mapping URL found when processing the file.
20
- *
21
- * @param types - an instance of babel-types.
22
- * @param inputSourceMapConsumer - access object for the source map of the input.
23
- * @param opts - additional options.
24
- */
25
6
  export declare function programVisitor(types: BabelTypes, inputSourceMapConsumer: SourceMapConsumer | undefined, opts: InstrumentationOptions): {
26
7
  enter(path: NodePath<Program>): void;
27
8
  exit(path: NodePath<Program>): void;
@@ -1 +1 @@
1
- {"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../src/visitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,QAAQ,EAAQ,MAAM,aAAa,CAAC;AAElD,OAAO,EAK8C,OAAO,EAE3D,MAAM,cAAc,CAAC;AAEtB,KAAK,UAAU,GAAG,cAAc,cAAc,CAAC,CAAA;AAE/C,OAAO,EAAC,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAG7C,OAAO,EAAC,sBAAsB,EAAC,MAAM,SAAS,CAAC;AAsmB/C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EACjB,sBAAsB,EAAE,iBAAiB,GAAG,SAAS,EACrD,IAAI,EAAE,sBAAsB;gBAYvC,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI;eASzB,QAAQ,CAAC,OAAO,CAAC;EA+BnC"}
1
+ {"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../src/visitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,QAAQ,EAAQ,MAAM,aAAa,CAAC;AAElD,OAAO,EAK8C,OAAO,EAE3D,MAAM,cAAc,CAAC;AAEtB,KAAK,UAAU,GAAG,cAAc,cAAc,CAAC,CAAA;AAE/C,OAAO,EAAC,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAG7C,OAAO,EAAC,sBAAsB,EAAC,MAAM,SAAS,CAAC;AAwnB/C,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EACjB,sBAAsB,EAAE,iBAAiB,GAAG,SAAS,EACrD,IAAI,EAAE,sBAAsB;gBAYvC,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI;eASzB,QAAQ,CAAC,OAAO,CAAC;EA+BnC"}
package/lib/visitor.js CHANGED
@@ -3,15 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.programVisitor = programVisitor;
4
4
  const core_1 = require("@babel/core");
5
5
  const origins_1 = require("./origins");
6
- // Pattern for istanbul to ignore a section
7
6
  const COMMENT_RE = /^\s*istanbul\s+ignore\s+(if|else|next)(?=\W|$)/;
8
- // Pattern for istanbul to ignore the whole file
9
7
  const COMMENT_FILE_RE = /^\s*istanbul\s+ignore\s+(file)(?=\W|$)/;
10
- /**
11
- * `VisitState` holds the state of the visitor, provides helper functions
12
- * and is the `this` for the individual coverage visitors.
13
- */
14
8
  class VisitState {
9
+ types;
10
+ attrs;
11
+ nextIgnore;
12
+ ignoreClassMethods;
13
+ reportLogic;
14
+ shouldInstrumentCallback;
15
+ origins;
15
16
  constructor(types, inputSourceMapConsumer, ignoreClassMethods = [], reportLogic = false, shouldInstrumentCallback) {
16
17
  this.attrs = {};
17
18
  this.nextIgnore = null;
@@ -21,27 +22,21 @@ class VisitState {
21
22
  this.shouldInstrumentCallback = shouldInstrumentCallback;
22
23
  this.origins = new origins_1.SourceOrigins(inputSourceMapConsumer);
23
24
  }
24
- /**
25
- * Use the configured callback, if available, to check if the given source
26
- * location should be instrumented.
27
- */
28
25
  shouldInstrument(path, loc) {
29
26
  if (this.shouldInstrumentCallback) {
30
27
  return this.shouldInstrumentCallback(path, loc);
31
28
  }
32
29
  return true;
33
30
  }
34
- /** Should we ignore the node? Yes, if specifically ignoring or if the node is generated. */
35
31
  shouldIgnore(path) {
36
32
  return this.nextIgnore !== null || !path.node.loc;
37
33
  }
38
- /** Extract the ignore comment hint (next|if|else) or null. */
39
34
  hintFor(node) {
40
35
  let hint = null;
41
36
  if (node.leadingComments) {
42
37
  node.leadingComments.forEach(c => {
43
38
  const v = (c.value || '').trim();
44
- const groups = v.match(COMMENT_RE);
39
+ const groups = COMMENT_RE.exec(v);
45
40
  if (groups) {
46
41
  hint = groups[1];
47
42
  }
@@ -49,35 +44,26 @@ class VisitState {
49
44
  }
50
45
  return hint;
51
46
  }
52
- /**
53
- * For these expressions the statement counter needs to be hoisted, so
54
- * function name inference can be preserved.
55
- */
56
47
  counterNeedsHoisting(path) {
57
48
  return (path.isFunctionExpression() ||
58
49
  path.isArrowFunctionExpression() ||
59
50
  path.isClassExpression());
60
51
  }
61
- /** All the generic stuff that needs to be done on enter for every node. */
62
52
  onEnter(path) {
63
53
  const n = path.node;
64
- // if already ignoring, nothing more to do
65
54
  if (this.nextIgnore !== null) {
66
55
  return;
67
56
  }
68
- // check hint to see if ignore should be turned on
69
57
  const hint = this.hintFor(n);
70
58
  if (hint === 'next') {
71
59
  this.nextIgnore = n;
72
60
  return;
73
61
  }
74
- // else check custom node attribute set by a prior visitor
75
62
  if (this.getAttr(path.node, 'skip-all') !== null) {
76
63
  this.nextIgnore = n;
77
64
  }
78
- // else check for ignored class methods
79
65
  if (path.isFunctionExpression() &&
80
- this.ignoreClassMethods.some(name => path.node.id && name === path.node.id.name)) {
66
+ this.ignoreClassMethods.some(name => name === path.node.id?.name)) {
81
67
  this.nextIgnore = n;
82
68
  return;
83
69
  }
@@ -87,23 +73,16 @@ class VisitState {
87
73
  return;
88
74
  }
89
75
  }
90
- /**
91
- * All the generic stuff on exit of a node, including resetting ignores and custom node attrs.
92
- */
93
76
  onExit(path) {
94
- // restore ignore status, if needed
95
77
  if (path.node === this.nextIgnore) {
96
78
  this.nextIgnore = null;
97
79
  }
98
- // nuke all attributes for the node
99
80
  delete path.node.__cov__;
100
81
  }
101
- /** Set a node attribute for the supplied node. */
102
82
  setAttr(node, name, value) {
103
83
  node.__cov__ = node.__cov__ || {};
104
84
  node.__cov__[name] = value;
105
85
  }
106
- /** Retrieve a node attribute for the supplied node or null. */
107
86
  getAttr(node, name) {
108
87
  const c = node.__cov__;
109
88
  if (!c) {
@@ -112,7 +91,6 @@ class VisitState {
112
91
  return c[name];
113
92
  }
114
93
  insertCounter(path, increment) {
115
- var _a, _b;
116
94
  const T = this.types;
117
95
  if (path.isBlockStatement()) {
118
96
  path.node.body.unshift(T.expressionStatement(increment));
@@ -122,11 +100,9 @@ class VisitState {
122
100
  }
123
101
  else if (this.counterNeedsHoisting(path) &&
124
102
  T.isVariableDeclarator(path.parent)) {
125
- // make an attempt to hoist the statement counter, so that
126
- // function names are maintained.
127
- const grandParentPath = (_a = path.parentPath) === null || _a === void 0 ? void 0 : _a.parentPath;
103
+ const grandParentPath = path.parentPath?.parentPath;
128
104
  if (grandParentPath && T.isExportNamedDeclaration(grandParentPath.parent)) {
129
- (_b = grandParentPath.parentPath) === null || _b === void 0 ? void 0 : _b.insertBefore(T.expressionStatement(increment));
105
+ grandParentPath.parentPath?.insertBefore(T.expressionStatement(increment));
130
106
  }
131
107
  else if (grandParentPath &&
132
108
  (T.isProgram(grandParentPath.parent) ||
@@ -145,9 +121,8 @@ class VisitState {
145
121
  }
146
122
  }
147
123
  insertFunctionCounter(path) {
148
- var _a, _b, _c;
149
124
  const T = this.types;
150
- if (!((_a = path.node) === null || _a === void 0 ? void 0 : _a.loc)) {
125
+ if (!(path.node?.loc)) {
151
126
  return;
152
127
  }
153
128
  const n = path.node;
@@ -156,23 +131,21 @@ class VisitState {
156
131
  case 'FunctionDeclaration':
157
132
  case 'FunctionExpression':
158
133
  if (n.id) {
159
- declarationLocation = (_b = n.id.loc) !== null && _b !== void 0 ? _b : undefined;
134
+ declarationLocation = n.id.loc ?? undefined;
160
135
  }
161
136
  break;
162
137
  }
163
138
  const body = path.get('body');
164
- const loc = (_c = path.node.loc) !== null && _c !== void 0 ? _c : declarationLocation;
139
+ const loc = path.node.loc ?? declarationLocation;
165
140
  const [originFileId, originPos] = this.origins.ensureKnownOrigin(loc);
166
141
  if (body.isBlockStatement() && this.shouldInstrument(path, originPos)) {
167
- // For functions, we only cover the first line of its body.
168
142
  originPos.end = originPos.start;
169
143
  const increment = newLineCoverageExpression(originFileId, originPos);
170
144
  body.node.body.unshift(T.expressionStatement(increment));
171
145
  }
172
146
  }
173
147
  insertStatementCounter(path) {
174
- var _a;
175
- const loc = (_a = path.node) === null || _a === void 0 ? void 0 : _a.loc;
148
+ const loc = path.node?.loc;
176
149
  if (!loc) {
177
150
  return;
178
151
  }
@@ -184,7 +157,7 @@ class VisitState {
184
157
  this.insertCounter(path, increment);
185
158
  }
186
159
  insertBranchCounter(path, loc) {
187
- loc = loc !== null && loc !== void 0 ? loc : path.node.loc;
160
+ loc = loc ?? path.node.loc;
188
161
  if (!loc) {
189
162
  return;
190
163
  }
@@ -214,16 +187,11 @@ class VisitState {
214
187
  }
215
188
  }
216
189
  }
217
- /**
218
- * Create a line coverage reporting statement node.
219
- */
220
190
  function newLineCoverageExpression(originFileId, range) {
221
191
  const argumentList = [
222
192
  { type: 'Identifier', name: originFileId },
223
193
  { type: 'NumericLiteral', value: range.start.line }
224
194
  ];
225
- // Only pass end line argument if they are different.
226
- // See also https://v8.dev/blog/adaptor-frame for performance considerations
227
195
  if (range.start.line !== range.end.line) {
228
196
  argumentList.push({ type: 'NumericLiteral', value: range.end.line });
229
197
  }
@@ -233,9 +201,6 @@ function newLineCoverageExpression(originFileId, range) {
233
201
  arguments: argumentList
234
202
  };
235
203
  }
236
- /**
237
- * Creates a new string constant AST node.
238
- */
239
204
  function newStringConstDeclarationNode(name, value) {
240
205
  return {
241
206
  type: 'VariableDeclaration',
@@ -255,18 +220,7 @@ function newStringConstDeclarationNode(name, value) {
255
220
  ]
256
221
  };
257
222
  }
258
- /**
259
- * Generic function that takes a set of visitor methods and
260
- * returns a visitor object with `enter` and `exit` properties,
261
- * such that:
262
- *
263
- * - standard entry processing is done
264
- * - the supplied visitors are called only when ignore is not in effect;
265
- * it reliefs them from worrying about ignore states and generated nodes.
266
- * - standard exit processing is done
267
- */
268
223
  function entries(...enter) {
269
- // the enter function
270
224
  const wrappedEntry = function (path, node) {
271
225
  this.onEnter(path);
272
226
  if (this.shouldIgnore(path)) {
@@ -311,8 +265,6 @@ function coverSequenceExpression(path) {
311
265
  const increment = newLineCoverageExpression(originFileId, originPos);
312
266
  newExpressions.push(increment);
313
267
  }
314
- // We must add the expression to be evaluated after the coverage increment
315
- // to not change the return value of the sequence expression.
316
268
  newExpressions.push(expression);
317
269
  }
318
270
  path.replaceWith(T.sequenceExpression(newExpressions));
@@ -354,14 +306,11 @@ function convertArrowExpression(path) {
354
306
  const T = this.types;
355
307
  if (!T.isBlockStatement(node.body)) {
356
308
  const bloc = node.body.loc;
357
- if (node.expression === true) {
309
+ if (node.expression) {
358
310
  node.expression = false;
359
311
  }
360
312
  node.body = T.blockStatement([T.returnStatement(node.body)]);
361
- // restore body location
362
313
  node.body.loc = bloc;
363
- // set up the location for the return statement so it gets
364
- // instrumented
365
314
  node.body.body[0].loc = bloc;
366
315
  }
367
316
  }
@@ -383,8 +332,7 @@ function coverIfBranches(path) {
383
332
  this.insertBranchCounter(path.get('alternate'), undefined);
384
333
  }
385
334
  }
386
- function createSwitchBranch(path) {
387
- // Intentionally left blank
335
+ function createSwitchBranch() {
388
336
  }
389
337
  function coverSwitchCase(path) {
390
338
  const T = this.types;
@@ -412,7 +360,7 @@ function coverTernary(path) {
412
360
  function coverLogicalExpression(path) {
413
361
  const T = this.types;
414
362
  if (path.parentPath.node.type === 'LogicalExpression') {
415
- return; // already processed
363
+ return;
416
364
  }
417
365
  const leaves = [];
418
366
  this.findLeaves(path.node, leaves, undefined, undefined);
@@ -442,9 +390,9 @@ function coverLogicalExpression(path) {
442
390
  const codeVisitor = {
443
391
  ArrowFunctionExpression: entries(convertArrowExpression, coverFunction),
444
392
  AssignmentPattern: entries(coverAssignmentPattern),
445
- BlockStatement: entries(), // ignore processing only
446
- ExportDefaultDeclaration: entries(), // ignore processing only
447
- ExportNamedDeclaration: entries(), // ignore processing only
393
+ BlockStatement: entries(),
394
+ ExportDefaultDeclaration: entries(),
395
+ ExportNamedDeclaration: entries(),
448
396
  ClassMethod: entries(coverFunction),
449
397
  ClassDeclaration: entries(parenthesizedExpressionProp('superClass')),
450
398
  ClassProperty: entries(coverClassPropDeclarator),
@@ -457,7 +405,7 @@ const codeVisitor = {
457
405
  ReturnStatement: entries(coverStatement),
458
406
  ThrowStatement: entries(coverStatement),
459
407
  TryStatement: entries(coverStatement),
460
- VariableDeclaration: entries(), // ignore processing only
408
+ VariableDeclaration: entries(),
461
409
  VariableDeclarator: entries(coverVariableDeclarator),
462
410
  IfStatement: entries(blockProp('consequent'), blockProp('alternate'), coverStatement, coverIfBranches),
463
411
  ForStatement: entries(blockProp('body'), coverStatement),
@@ -475,18 +423,11 @@ const codeVisitor = {
475
423
  LogicalExpression: entries(coverLogicalExpression),
476
424
  SequenceExpression: entries(coverSequenceExpression),
477
425
  };
478
- /**
479
- * The rewire plugin (and potentially other babel middleware)
480
- * may cause files to be instrumented twice, see:
481
- * https://github.com/istanbuljs/babel-plugin-istanbul/issues/94
482
- * we should only instrument code for coverage the first time
483
- * it's run through lib-instrument.
484
- */
485
426
  function alreadyInstrumented(path, visitState) {
486
427
  return path.scope.hasBinding(visitState.varName);
487
428
  }
488
429
  function getParentComments(path) {
489
- if (!(path === null || path === void 0 ? void 0 : path.parent)) {
430
+ if (!path?.parent) {
490
431
  return [];
491
432
  }
492
433
  if (!('comments' in path.parent)) {
@@ -498,28 +439,8 @@ function shouldIgnoreFile(programNodePath) {
498
439
  if (!programNodePath) {
499
440
  return false;
500
441
  }
501
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
502
442
  return getParentComments(programNodePath).some(c => COMMENT_FILE_RE.test(c.value));
503
443
  }
504
- /**
505
- * `programVisitor` is a `babel` adaptor for instrumentation.
506
- *
507
- * It returns an object with two methods `enter` and `exit`.
508
- * These should be assigned to or called from `Program` entry and exit functions
509
- * in a babel visitor.
510
- *
511
- * These functions do not make assumptions about the state set by Babel and thus
512
- * can be used in a context other than a Babel plugin.
513
- *
514
- * The exit function returns an object that currently has the following keys:
515
- *
516
- * `fileCoverage` - the file coverage object created for the source file.
517
- * `sourceMappingURL` - any source mapping URL found when processing the file.
518
- *
519
- * @param types - an instance of babel-types.
520
- * @param inputSourceMapConsumer - access object for the source map of the input.
521
- * @param opts - additional options.
522
- */
523
444
  function programVisitor(types, inputSourceMapConsumer, opts) {
524
445
  opts = { ...opts };
525
446
  const visitState = new VisitState(types, inputSourceMapConsumer, opts.ignoreClassMethods, opts.reportLogic, opts.shouldInstrumentCallback);
@@ -548,12 +469,10 @@ function programVisitor(types, inputSourceMapConsumer, opts) {
548
469
  body.unshift(...codeToPrependAst.program.body);
549
470
  }
550
471
  }
551
- // Add a variable definition for each origin file on top of the file.
552
472
  for (const [originPath, originId] of originData.originToIdMap.entries()) {
553
473
  const declaration = newStringConstDeclarationNode(originId, originPath);
554
474
  body.unshift(declaration);
555
475
  }
556
- // Add a token for signaling that the file has been instrumented.
557
476
  if (opts.isInstrumentedToken) {
558
477
  types.addComment(path.node, 'leading', opts.isInstrumentedToken, false);
559
478
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamscale/lib-instrument",
3
- "version": "1.0.0-beta.6",
3
+ "version": "1.0.0-beta.7",
4
4
  "description": "Library for adding coverage statements to JS code; forked from istanbul-lib-coverage",
5
5
  "author": "Krishnan Anantheswaran <kananthmail-github@yahoo.com>",
6
6
  "maintainers": [
@@ -14,12 +14,12 @@
14
14
  "lib"
15
15
  ],
16
16
  "dependencies": {
17
- "@babel/core": "^7.26.8",
18
- "@babel/parser": "^7.26.8",
19
- "@babel/traverse": "^7.26.8",
20
- "@types/node": "^22.13.4",
21
- "source-map": "^0.7.4",
22
- "typescript": "^5.7.3"
17
+ "@babel/core": "^7.28.5",
18
+ "@babel/parser": "^7.28.5",
19
+ "@babel/traverse": "^7.28.5",
20
+ "@types/node": "^22.18.12",
21
+ "source-map": "^0.7.6",
22
+ "typescript": "^5.8.3"
23
23
  },
24
24
  "license": "BSD-3-Clause",
25
25
  "homepage": "https://docs.teamscale.com/howto/setting-up-profiler-tga/javascript/",
@@ -29,6 +29,6 @@
29
29
  "scripts": {
30
30
  "clean": "rimraf lib tsconfig.tsbuildinfo",
31
31
  "build": "tsc",
32
- "test": "pnpm build && NODE_OPTIONS='--experimental-vm-modules --max-old-space-size=8192' jest --forceExit --coverage --silent=true --detectOpenHandles"
32
+ "test": "node --import tsx --test test/**/*.test.ts"
33
33
  }
34
34
  }