@systemfsoftware/stryker-js-instrumenter 5.0.1 → 6.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @systemfsoftware/stryker-js-instrumenter
2
2
 
3
+ ## 6.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - Nothing a consumer can observe moved in the four packages above, so no release is warranted.
8
+
9
+ `@systemfsoftware/stryker-js-instrumenter` now answers with promises: `transform` and `placeHeader` return `Promise`, and `AstTransformer` is a promise-returning function type. Await them where you call them. The parser is read on first use rather than at import, so importing this package no longer constructs Node's WebAssembly runtime, and `ExperimentalWarning: WASI` no longer appears until something is actually parsed.
10
+
11
+ ### Patch Changes
12
+
13
+ - Releases the workspace so its published versions track the shared dependency graph this change moves.
14
+
15
+ - The `@systemfsoftware/source` export condition is gone. It resolved to a package's TypeScript sources for editors and in-repo typechecks; each package now exports only its built entry. If your tsconfig sets `customConditions: ["@systemfsoftware/source"]`, or a bundler config names that condition, remove it — resolution falls back to the built entry, which is what every consumer already got.
16
+
17
+ ## 5.0.2
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies:
22
+ - @systemfsoftware/effect-cell-types@7.0.0
23
+
3
24
  ## 5.0.1
4
25
 
5
26
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { FileDescription, Mutant } from "@systemfsoftware/stryker-js/Mutant";
2
2
  import * as Effect from "effect/Effect";
3
- import { Wire } from "@systemfsoftware/effect-cell-types";
4
3
  import * as S from "effect/Schema";
5
4
  import "effect/Option";
6
5
  import { IgnorerService } from "@systemfsoftware/stryker-js/Ignorer";
@@ -13,10 +12,10 @@ declare class InstrumentError extends InstrumentError_base {
13
12
  get message(): string;
14
13
  }
15
14
  declare const InstrumenterOptionsSchema: S.Struct<{
16
- excludedMutations: S.$Array<S.String & Wire.Mark> & Wire.Mark;
17
- ignorers: S.$Array<S.Unknown & Wire.Mark> & Wire.Mark;
18
- noHeader: S.optional<S.Boolean & Wire.Mark> & Wire.Mark;
19
- }> & Wire.Mark;
15
+ readonly excludedMutations: S.$Array<S.String>;
16
+ readonly ignorers: S.$Array<S.Unknown>;
17
+ readonly noHeader: S.optional<S.Boolean>;
18
+ }>;
20
19
  type InstrumenterOptions = typeof InstrumenterOptionsSchema.Type;
21
20
  declare const InstrumentResult_base: S.Class<InstrumentResult$1, S.TaggedStruct<"InstrumentResult", {
22
21
  readonly files: S.$Array<S.Struct<{
package/dist/index.mjs CHANGED
@@ -1,12 +1,10 @@
1
1
  import { INSTRUMENTER_CONSTANTS, Mutant } from "@systemfsoftware/stryker-js/Mutant";
2
2
  import * as Effect from "effect/Effect";
3
3
  import * as Predicate from "effect/Predicate";
4
- import { Wire } from "@systemfsoftware/effect-cell-types";
5
4
  import * as S from "effect/Schema";
6
5
  import * as Arr from "effect/Array";
7
6
  import * as Match from "effect/Match";
8
7
  import * as Option from "effect/Option";
9
- import { parseSync } from "oxc-parser";
10
8
  import path from "path";
11
9
  import "@systemfsoftware/stryker-js/Ignorer";
12
10
  import { propertyPath, strykerReportBugUrl } from "@systemfsoftware/stryker-js/Schema";
@@ -36,12 +34,12 @@ const FileSchema = S.Struct({
36
34
  content: S.String,
37
35
  mutate: MutateDescriptionSchema
38
36
  });
39
- const IgnorerSchema = Wire.mint(S.Unknown);
40
- const AstSchema = Wire.mint(S.Unknown);
41
- const InstrumenterOptionsSchema = Wire.wire({
42
- excludedMutations: Wire.mint(S.Array(Wire.mint(S.String))),
43
- ignorers: Wire.mint(S.Array(IgnorerSchema)),
44
- noHeader: Wire.mint(S.optional(Wire.mint(S.Boolean)))
37
+ const IgnorerSchema = S.Unknown;
38
+ const AstSchema = S.Unknown;
39
+ const InstrumenterOptionsSchema = S.Struct({
40
+ excludedMutations: S.Array(S.String),
41
+ ignorers: S.Array(IgnorerSchema),
42
+ noHeader: S.optional(S.Boolean)
45
43
  });
46
44
  var InstrumentCommand = class extends S.TaggedClass()("InstrumentCommand", {
47
45
  files: S.Array(FileSchema),
@@ -642,6 +640,13 @@ function isIndexedList(container, index) {
642
640
  return isNodeList(container) && Number.isInteger(index);
643
641
  }
644
642
  //#endregion
643
+ //#region src/Oxc.ts
644
+ let oxc;
645
+ const loadOxc = async () => {
646
+ if (oxc === void 0) oxc = await import("oxc-parser");
647
+ return oxc;
648
+ };
649
+ //#endregion
645
650
  //#region src/Parser.schema.ts
646
651
  var ParseFailed = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/ParseFailed")("ParseFailed", {
647
652
  fileName: S.String,
@@ -724,7 +729,8 @@ function fieldOf(value, key) {
724
729
  function appendIfDefined(values, value) {
725
730
  if (value !== void 0) values.push(value);
726
731
  }
727
- function parseWithOxc(text, fileName, lang) {
732
+ async function parseWithOxc(text, fileName, lang) {
733
+ const { parseSync } = await loadOxc();
728
734
  const result = parseSync(fileName, text, {
729
735
  lang,
730
736
  range: true
@@ -796,7 +802,7 @@ function getFormat(fileName, override) {
796
802
  }
797
803
  function createJSParser() {
798
804
  return async function parse(text, fileName) {
799
- const { root, comments } = parseWithOxc(text, fileName, "js");
805
+ const { root, comments } = await parseWithOxc(text, fileName, "js");
800
806
  return {
801
807
  originFileName: fileName,
802
808
  rawContent: text,
@@ -807,7 +813,7 @@ function createJSParser() {
807
813
  };
808
814
  }
809
815
  async function parseTS(text, fileName) {
810
- const { root, comments } = parseWithOxc(text, fileName, "ts");
816
+ const { root, comments } = await parseWithOxc(text, fileName, "ts");
811
817
  return {
812
818
  originFileName: fileName,
813
819
  rawContent: text,
@@ -817,7 +823,7 @@ async function parseTS(text, fileName) {
817
823
  };
818
824
  }
819
825
  async function parseTsx(text, fileName) {
820
- const { root, comments } = parseWithOxc(text, fileName, "tsx");
826
+ const { root, comments } = await parseWithOxc(text, fileName, "tsx");
821
827
  return {
822
828
  root,
823
829
  comments,
@@ -4795,7 +4801,7 @@ function isPropertyBearing(node) {
4795
4801
  }
4796
4802
  const strykerPlugins = [];
4797
4803
  const frameworkPluginsFileUrl = import.meta.url;
4798
- const parsedInstrumentationHeader = parseSync("instrumenter-header.js", `// @ts-nocheck
4804
+ const INSTRUMENTATION_HEADER_SOURCE = `// @ts-nocheck
4799
4805
  var ${STRYKER_NAMESPACE_HELPER} = function(){
4800
4806
  var g = typeof globalThis === 'object' && globalThis && globalThis.Math === Math && globalThis || new Function("return this")();
4801
4807
  var ns = g.${INSTRUMENTER_CONSTANTS.NAMESPACE} || (g.${INSTRUMENTER_CONSTANTS.NAMESPACE} = {});
@@ -4839,34 +4845,37 @@ var ${IS_MUTANT_ACTIVE_HELPER} = function(id) {
4839
4845
  }
4840
4846
  ${IS_MUTANT_ACTIVE_HELPER} = isActive;
4841
4847
  return isActive(id);
4842
- }`, {
4843
- lang: "js",
4844
- range: true
4845
- });
4846
- if (parsedInstrumentationHeader.errors.length > 0) throw new Error("Instrumentation header failed to parse");
4847
- const instrumentationHeader = parsedInstrumentationHeader.program.body;
4848
- deepFreeze(instrumentationHeader);
4849
- function placeHeaderIfNeeded(mutantCollector, originFileName, options, root) {
4850
- if (shouldPlaceHeader(mutantCollector, originFileName, options)) placeHeader(root);
4848
+ }`;
4849
+ let instrumentationHeaderValue;
4850
+ const instrumentationHeader = async () => {
4851
+ if (instrumentationHeaderValue === void 0) {
4852
+ instrumentationHeaderValue = (await parseWithOxc(INSTRUMENTATION_HEADER_SOURCE, "instrumenter-header.js", "js")).root.body;
4853
+ deepFreeze(instrumentationHeaderValue);
4854
+ }
4855
+ return instrumentationHeaderValue;
4856
+ };
4857
+ async function placeHeaderIfNeeded(mutantCollector, originFileName, options, root) {
4858
+ if (shouldPlaceHeader(mutantCollector, originFileName, options)) await placeHeader(root);
4851
4859
  }
4852
4860
  function shouldPlaceHeader(mutantCollector, originFileName, options) {
4853
4861
  return hasPlacedMutants(mutantCollector, originFileName) && options.noHeader !== true;
4854
4862
  }
4855
- function placeHeader(root) {
4856
- root.body.unshift(...headerFor(root));
4863
+ async function placeHeader(root) {
4864
+ root.body.unshift(...await headerFor(root));
4857
4865
  }
4858
- function headerFor(root) {
4866
+ async function headerFor(root) {
4867
+ const header = await instrumentationHeader();
4859
4868
  return Option.match(leadingCommentsOf(root), {
4860
- onNone: () => instrumentationHeader,
4861
- onSome: (leadingComments) => [commentedHeader(leadingComments), ...instrumentationHeader.slice(1)]
4869
+ onNone: () => header,
4870
+ onSome: (leadingComments) => [commentedHeader(leadingComments, header), ...header.slice(1)]
4862
4871
  });
4863
4872
  }
4864
4873
  function leadingCommentsOf(root) {
4865
4874
  const firstStatement = root.body[0];
4866
4875
  return Option.filter(Option.fromNullishOr(firstStatement?.leadingComments), isUnknownArray);
4867
4876
  }
4868
- function commentedHeader(leadingComments) {
4869
- const cloned = cloneNode(Option.getOrThrowWith(Option.fromNullishOr(instrumentationHeader[0]), () => /* @__PURE__ */ new Error("Instrumentation header is empty")));
4877
+ function commentedHeader(leadingComments, header) {
4878
+ const cloned = cloneNode(Option.getOrThrowWith(Option.fromNullishOr(header[0]), () => /* @__PURE__ */ new Error("Instrumentation header is empty")));
4870
4879
  cloned.leadingComments = leadingComments;
4871
4880
  return cloned;
4872
4881
  }
@@ -4906,7 +4915,7 @@ function isMap(value) {
4906
4915
  function isSet(value) {
4907
4916
  return value instanceof Set;
4908
4917
  }
4909
- function transform(ast, mutantCollector, transformerContext) {
4918
+ async function transform(ast, mutantCollector, transformerContext) {
4910
4919
  const context = {
4911
4920
  ...transformerContext,
4912
4921
  transform
@@ -4919,34 +4928,31 @@ function transform(ast, mutantCollector, transformerContext) {
4919
4928
  case "svelte": return transformSvelte(ast, mutantCollector, context);
4920
4929
  }
4921
4930
  }
4922
- const transformHtml = ({ root }, mutantCollector, context) => {
4931
+ const transformHtml = async ({ root }, mutantCollector, context) => {
4923
4932
  const warnings = [];
4924
- root.scripts.forEach((ast) => {
4925
- warnings.push(...context.transform(ast, mutantCollector, context));
4926
- });
4933
+ for (const script of root.scripts) warnings.push(...await context.transform(script, mutantCollector, context));
4927
4934
  return warnings;
4928
4935
  };
4929
4936
  const moduleScript = `<script context="module">
4930
4937
  \n<\/script>\n`;
4931
- const transformSvelte = (svelte, mutantCollector, context) => {
4938
+ const transformSvelte = async (svelte, mutantCollector, context) => {
4932
4939
  const warnings = [];
4933
4940
  const { root } = svelte;
4934
- [root.moduleScript, ...root.additionalScripts].filter(Predicate.isNotNullish).forEach((script) => {
4935
- warnings.push(...context.transform(script.ast, mutantCollector, {
4936
- ...context,
4937
- options: {
4938
- ...context.options,
4939
- noHeader: true
4940
- }
4941
- }));
4942
- });
4943
- placeModuleHeaderIfNeeded(svelte, mutantCollector);
4941
+ const scripts = [root.moduleScript, ...root.additionalScripts].filter(Predicate.isNotNullish);
4942
+ for (const script of scripts) warnings.push(...await context.transform(script.ast, mutantCollector, {
4943
+ ...context,
4944
+ options: {
4945
+ ...context.options,
4946
+ noHeader: true
4947
+ }
4948
+ }));
4949
+ await placeModuleHeaderIfNeeded(svelte, mutantCollector);
4944
4950
  return warnings;
4945
4951
  };
4946
- function placeModuleHeaderIfNeeded(svelte, mutantCollector) {
4947
- if (hasPlacedMutants(mutantCollector, svelte.originFileName)) placeModuleHeader(svelte);
4952
+ async function placeModuleHeaderIfNeeded(svelte, mutantCollector) {
4953
+ if (hasPlacedMutants(mutantCollector, svelte.originFileName)) await placeModuleHeader(svelte);
4948
4954
  }
4949
- function placeModuleHeader(svelte) {
4955
+ async function placeModuleHeader(svelte) {
4950
4956
  const { root, originFileName } = svelte;
4951
4957
  if (!root.moduleScript) {
4952
4958
  root.moduleScript = {
@@ -4969,7 +4975,7 @@ function placeModuleHeader(svelte) {
4969
4975
  script.range.end += moduleScript.length;
4970
4976
  });
4971
4977
  }
4972
- placeHeader(root.moduleScript.ast.root);
4978
+ await placeHeader(root.moduleScript.ast.root);
4973
4979
  }
4974
4980
  function emptyProgram() {
4975
4981
  return {
@@ -4981,7 +4987,7 @@ function emptyProgram() {
4981
4987
  function isMutateRangeList(value) {
4982
4988
  return Array.isArray(value);
4983
4989
  }
4984
- const transformScript = ({ root, originFileName, rawContent, offset, comments }, mutantCollector, { options, mutateDescription }, mutators, mutantPlacers) => {
4990
+ const transformScript = async ({ root, originFileName, rawContent, offset, comments }, mutantCollector, { options, mutateDescription }, mutators, mutantPlacers) => {
4985
4991
  const lineTable = buildLineTable(rawContent);
4986
4992
  attachComments(root, comments, lineTable);
4987
4993
  const placementMap = /* @__PURE__ */ new Map();
@@ -5002,7 +5008,7 @@ const transformScript = ({ root, originFileName, rawContent, offset, comments },
5002
5008
  if (hasAppliedMutants(placement)) applyPlacement(path, placement);
5003
5009
  }
5004
5010
  });
5005
- placeHeaderIfNeeded(mutantCollector, originFileName, options, root);
5011
+ await placeHeaderIfNeeded(mutantCollector, originFileName, options, root);
5006
5012
  return warnings;
5007
5013
  function visitNode(path) {
5008
5014
  if (shouldSkip(path)) {
@@ -5304,7 +5310,7 @@ const readCollected = (command) => Effect.gen(function* () {
5304
5310
  ast
5305
5311
  })));
5306
5312
  const collector = createMutantCollector();
5307
- yield* Effect.forEach(parsed, ({ file, ast }) => Effect.try({
5313
+ yield* Effect.forEach(parsed, ({ file, ast }) => Effect.tryPromise({
5308
5314
  try: () => transform(ast, collector, {
5309
5315
  options: toTransformerOptions(options),
5310
5316
  mutateDescription: toOneBasedLineNumber(file.mutate)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@systemfsoftware/stryker-js-instrumenter",
3
- "version": "5.0.1",
3
+ "version": "6.0.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/systemfsoftware/systemfsoftware.git",
@@ -24,11 +24,11 @@
24
24
  "angular-html-parser": "~10.4.0",
25
25
  "effect": "4.0.0-rc.112",
26
26
  "oxc-parser": "^0.140.0",
27
- "@systemfsoftware/effect-cell-types": "^6.0.1",
28
- "@systemfsoftware/stryker-js": "^3.0.0"
27
+ "@systemfsoftware/stryker-js": "^3.0.2",
28
+ "@systemfsoftware/effect-cell-types": "^7.0.1"
29
29
  },
30
30
  "devDependencies": {
31
- "@systemfsoftware/arethetypeswrong-cli": "^1.1.1",
31
+ "@systemfsoftware/arethetypeswrong-cli": "^4.1.0",
32
32
  "@types/estree": "1.0.8",
33
33
  "@types/node": "^24",
34
34
  "oxlint": "^1.77.0",
@@ -37,11 +37,11 @@
37
37
  "tsdown": "^0.22.14",
38
38
  "typescript": "^7",
39
39
  "vitest": "^4",
40
- "@systemfsoftware/oxlint-config": "^0.1.0",
41
- "@systemfsoftware/effect-gherkin-spec": "^4.0.1",
40
+ "@systemfsoftware/all": "^2.0.1",
41
+ "@systemfsoftware/effect-gherkin-spec": "^4.0.2",
42
42
  "@systemfsoftware/vitest-config": "^0.1.0",
43
- "@systemfsoftware/tsconfig": "^1.3.3",
44
- "@systemfsoftware/all": "^2.0.0"
43
+ "@systemfsoftware/oxlint-config": "^0.1.0",
44
+ "@systemfsoftware/tsconfig": "^1.3.4"
45
45
  },
46
46
  "engines": {
47
47
  "node": ">=20.0.0"