@swagger-api/apidom-parser-adapter-json 1.8.0 → 1.10.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swagger-api/apidom-parser-adapter-json",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "Parser adapter for parsing JSON documents into base namespace.",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -56,9 +56,9 @@
56
56
  "license": "Apache-2.0",
57
57
  "dependencies": {
58
58
  "@babel/runtime-corejs3": "^7.26.10",
59
- "@swagger-api/apidom-ast": "^1.8.0",
60
- "@swagger-api/apidom-core": "^1.8.0",
61
- "@swagger-api/apidom-error": "^1.8.0",
59
+ "@swagger-api/apidom-ast": "^1.10.0",
60
+ "@swagger-api/apidom-core": "^1.10.0",
61
+ "@swagger-api/apidom-error": "^1.10.0",
62
62
  "@types/ramda": "~0.30.0",
63
63
  "ramda": "~0.30.0",
64
64
  "ramda-adjunct": "^5.0.0",
@@ -80,5 +80,5 @@
80
80
  "README.md",
81
81
  "CHANGELOG.md"
82
82
  ],
83
- "gitHead": "1dd54ab78366b9936cdd0422949093b93e958ab7"
83
+ "gitHead": "c72e92fc541b7df2b92335a0f2df147eb7b9b945"
84
84
  }
@@ -21,13 +21,17 @@ const detect = async source => {
21
21
  if (!_adapter.detectionRegExp.test(source)) {
22
22
  return false;
23
23
  }
24
+ let cst = null;
24
25
  try {
25
- const cst = await (0, _browser.default)(source);
26
+ cst = await (0, _browser.default)(source);
26
27
  const isError = cst.rootNode.type !== 'ERROR';
27
- cst.delete();
28
28
  return isError;
29
29
  } catch {
30
30
  return false;
31
+ } finally {
32
+ if (cst !== null) {
33
+ cst.delete();
34
+ }
31
35
  }
32
36
  };
33
37
 
@@ -46,18 +50,21 @@ const parse = async (source, {
46
50
  sourceMap = false,
47
51
  syntacticAnalysis = 'direct'
48
52
  } = {}) => {
49
- const cst = await (0, _browser.default)(source);
50
- let apiDOM;
51
- if (syntacticAnalysis === 'indirect') {
52
- apiDOM = (0, _index2.default)(cst, {
53
- sourceMap
54
- });
55
- } else {
56
- apiDOM = (0, _index.default)(cst, {
53
+ let cst = null;
54
+ try {
55
+ cst = await (0, _browser.default)(source);
56
+ if (syntacticAnalysis === 'indirect') {
57
+ return (0, _index2.default)(cst, {
58
+ sourceMap
59
+ });
60
+ }
61
+ return (0, _index.default)(cst, {
57
62
  sourceMap
58
63
  });
64
+ } finally {
65
+ if (cst !== null) {
66
+ cst.delete();
67
+ }
59
68
  }
60
- cst.delete();
61
- return apiDOM;
62
69
  };
63
70
  exports.parse = parse;
@@ -13,13 +13,17 @@ export const detect = async source => {
13
13
  if (!detectionRegExp.test(source)) {
14
14
  return false;
15
15
  }
16
+ let cst = null;
16
17
  try {
17
- const cst = await lexicalAnalysis(source);
18
+ cst = await lexicalAnalysis(source);
18
19
  const isError = cst.rootNode.type !== 'ERROR';
19
- cst.delete();
20
20
  return isError;
21
21
  } catch {
22
22
  return false;
23
+ } finally {
24
+ if (cst !== null) {
25
+ cst.delete();
26
+ }
23
27
  }
24
28
  };
25
29
 
@@ -38,17 +42,20 @@ export const parse = async (source, {
38
42
  sourceMap = false,
39
43
  syntacticAnalysis = 'direct'
40
44
  } = {}) => {
41
- const cst = await lexicalAnalysis(source);
42
- let apiDOM;
43
- if (syntacticAnalysis === 'indirect') {
44
- apiDOM = syntacticAnalysisIndirect(cst, {
45
- sourceMap
46
- });
47
- } else {
48
- apiDOM = syntacticAnalysisDirect(cst, {
45
+ let cst = null;
46
+ try {
47
+ cst = await lexicalAnalysis(source);
48
+ if (syntacticAnalysis === 'indirect') {
49
+ return syntacticAnalysisIndirect(cst, {
50
+ sourceMap
51
+ });
52
+ }
53
+ return syntacticAnalysisDirect(cst, {
49
54
  sourceMap
50
55
  });
56
+ } finally {
57
+ if (cst !== null) {
58
+ cst.delete();
59
+ }
51
60
  }
52
- cst.delete();
53
- return apiDOM;
54
61
  };
@@ -11,14 +11,12 @@ var _treeSitterJson = _interopRequireDefault(require("../../wasm/tree-sitter-jso
11
11
 
12
12
  let parser = null;
13
13
  let parserInitLock = null;
14
- let currentTree = null;
14
+ const activeTrees = new Set();
15
+ const MAX_ACTIVE_TREES = 5;
15
16
 
16
17
  /**
17
18
  * Lexical Analysis of source string using WebTreeSitter.
18
19
  * This is WebAssembly version of TreeSitters Lexical Analysis.
19
- *
20
- * Given JavaScript doesn't support true parallelism, this
21
- * code should be as lazy as possible and temporal safety should be fine.
22
20
  * @public
23
21
  */
24
22
  const analyze = async source => {
@@ -39,8 +37,27 @@ const analyze = async source => {
39
37
  } else if (parser === null) {
40
38
  throw new _apidomError.ApiDOMError('Error while initializing web-tree-sitter and loading tree-sitter-json grammar.');
41
39
  }
42
- currentTree = parser.parse(source);
40
+
41
+ // prevent WASM OOM during concurrency spikes by evicting oldest trees
42
+ // when the pool exceeds threshold; tree.delete() is idempotent so
43
+ // callers that still hold a reference can safely call delete() again
44
+ if (activeTrees.size >= MAX_ACTIVE_TREES) {
45
+ const treesToEvict = [...activeTrees];
46
+ activeTrees.clear();
47
+ for (const oldTree of treesToEvict) {
48
+ oldTree.delete();
49
+ }
50
+ }
51
+ const tree = parser.parse(source);
52
+ activeTrees.add(tree);
53
+
54
+ // remove from tracking when caller deletes
55
+ const originalDelete = tree.delete;
56
+ tree.delete = function deleteAndUntrack() {
57
+ activeTrees.delete(this);
58
+ originalDelete.call(this);
59
+ };
43
60
  parser.reset();
44
- return currentTree;
61
+ return tree;
45
62
  };
46
63
  var _default = exports.default = analyze;
@@ -6,14 +6,12 @@ import { ApiDOMError } from '@swagger-api/apidom-error';
6
6
  import treeSitterJson from '../../wasm/tree-sitter-json.wasm';
7
7
  let parser = null;
8
8
  let parserInitLock = null;
9
- let currentTree = null;
9
+ const activeTrees = new Set();
10
+ const MAX_ACTIVE_TREES = 5;
10
11
 
11
12
  /**
12
13
  * Lexical Analysis of source string using WebTreeSitter.
13
14
  * This is WebAssembly version of TreeSitters Lexical Analysis.
14
- *
15
- * Given JavaScript doesn't support true parallelism, this
16
- * code should be as lazy as possible and temporal safety should be fine.
17
15
  * @public
18
16
  */
19
17
  const analyze = async source => {
@@ -34,8 +32,27 @@ const analyze = async source => {
34
32
  } else if (parser === null) {
35
33
  throw new ApiDOMError('Error while initializing web-tree-sitter and loading tree-sitter-json grammar.');
36
34
  }
37
- currentTree = parser.parse(source);
35
+
36
+ // prevent WASM OOM during concurrency spikes by evicting oldest trees
37
+ // when the pool exceeds threshold; tree.delete() is idempotent so
38
+ // callers that still hold a reference can safely call delete() again
39
+ if (activeTrees.size >= MAX_ACTIVE_TREES) {
40
+ const treesToEvict = [...activeTrees];
41
+ activeTrees.clear();
42
+ for (const oldTree of treesToEvict) {
43
+ oldTree.delete();
44
+ }
45
+ }
46
+ const tree = parser.parse(source);
47
+ activeTrees.add(tree);
48
+
49
+ // remove from tracking when caller deletes
50
+ const originalDelete = tree.delete;
51
+ tree.delete = function deleteAndUntrack() {
52
+ activeTrees.delete(this);
53
+ originalDelete.call(this);
54
+ };
38
55
  parser.reset();
39
- return currentTree;
56
+ return tree;
40
57
  };
41
58
  export default analyze;
@@ -44,9 +44,6 @@ export declare class JSONMediaTypes extends MediaTypes<string> {
44
44
  /**
45
45
  * Lexical Analysis of source string using WebTreeSitter.
46
46
  * This is WebAssembly version of TreeSitters Lexical Analysis.
47
- *
48
- * Given JavaScript doesn't support true parallelism, this
49
- * code should be as lazy as possible and temporal safety should be fine.
50
47
  * @public
51
48
  */
52
49
  export declare const lexicalAnalysis: (source: string) => Promise<Tree_2>;