fhirsmith 0.9.4 → 0.9.5
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 +11 -0
- package/library/regex-utilities.js +17 -3
- package/package.json +1 -1
- package/test-scripts/repro-re2-wasm-leak.js +33 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ All notable changes to the Health Intersections Node Server will be documented i
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
|
|
9
|
+
## [v0.9.5] - 2026-05-16
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Workaround for memory leak in re2-wasm library that reduces it's severity
|
|
14
|
+
|
|
15
|
+
### Tx Conformance Statement
|
|
16
|
+
|
|
17
|
+
FHIRsmith passed all 1649 HL7 terminology service tests (modes tx.fhir.org+omop+general+snomed, tests v1.9.1, runner v6.9.7)
|
|
18
|
+
|
|
8
19
|
## [v0.9.4] - 2026-05-01
|
|
9
20
|
|
|
10
21
|
### Added
|
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
const { RE2 } = require('re2-wasm');
|
|
1
|
+
const { RE2 } = require('re2-wasm');
|
|
2
2
|
|
|
3
3
|
class RegExUtilities {
|
|
4
4
|
|
|
5
|
+
constructor() {
|
|
6
|
+
this._cache = new Map();
|
|
7
|
+
}
|
|
8
|
+
|
|
5
9
|
compile(pattern, flags) {
|
|
6
|
-
//
|
|
10
|
+
// re2-wasm has a fixed 16 MB WASM heap with no real free(): every
|
|
11
|
+
// new RE2(...) permanently consumes a few KB. Cache by (pattern, flags)
|
|
12
|
+
// so the same regex compiles at most once.
|
|
13
|
+
// TODO: replace re2-wasm with native re2 to eliminate the underlying leak.
|
|
7
14
|
const re2Flags = flags && flags.includes('u') ? flags : (flags || '') + 'u';
|
|
8
|
-
|
|
15
|
+
const key = pattern + '|' + re2Flags;
|
|
16
|
+
let compiled = this._cache.get(key);
|
|
17
|
+
if (!compiled) {
|
|
18
|
+
compiled = new RE2(pattern, re2Flags);
|
|
19
|
+
this._cache.set(key, compiled);
|
|
20
|
+
}
|
|
21
|
+
return compiled;
|
|
9
22
|
}
|
|
10
23
|
|
|
11
24
|
}
|
|
12
25
|
|
|
13
26
|
module.exports = new RegExUtilities();
|
|
27
|
+
|
package/package.json
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Manual reproducer for the re2-wasm WASM heap leak.
|
|
2
|
+
// See library/regex-utilities.js for the workaround.
|
|
3
|
+
//
|
|
4
|
+
// node test-scripts/repro-re2-wasm-leak.js # same-pattern stress
|
|
5
|
+
// node test-scripts/repro-re2-wasm-leak.js --unique # unique-pattern stress
|
|
6
|
+
//
|
|
7
|
+
// Without the cache, same-pattern OOMs at ~2965 iterations.
|
|
8
|
+
// With the cache, same-pattern runs indefinitely.
|
|
9
|
+
// Unique-pattern still OOMs (each pattern is a real compile and the underlying
|
|
10
|
+
// re2-wasm heap leak still applies). A proper fix is to replace re2-wasm with
|
|
11
|
+
// the native `re2` package.
|
|
12
|
+
|
|
13
|
+
const re = require('../library/regex-utilities');
|
|
14
|
+
|
|
15
|
+
const mode = process.argv.includes('--unique') ? 'unique' : 'same';
|
|
16
|
+
const basePattern =
|
|
17
|
+
'CYTO|HL7\\.CYTOGEN|HL7\\.GENETICS|^PATH(\\..*)?|^MOLPATH(\\..*)?|NR STATS|H&P\\.HX\\.LAB|CHALSKIN|LABORDERS';
|
|
18
|
+
|
|
19
|
+
console.log(`mode: ${mode}-pattern`);
|
|
20
|
+
|
|
21
|
+
let i = 0;
|
|
22
|
+
try {
|
|
23
|
+
for (;;) {
|
|
24
|
+
const pattern = mode === 'unique' ? basePattern + `|UNIQUE${i}` : basePattern;
|
|
25
|
+
re.compile(pattern);
|
|
26
|
+
i++;
|
|
27
|
+
if (i % 100 === 0) console.log(`iter ${i}`);
|
|
28
|
+
}
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.error(`OOMed at iteration ${i}: ${e.message}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|