Skip to content

JavaScript SDK: All unit tests passing (268/268), cross-SDK tests (138/138)#50

Open
joalves wants to merge 4 commits intomainfrom
fix/all-tests-passing-268-268
Open

JavaScript SDK: All unit tests passing (268/268), cross-SDK tests (138/138)#50
joalves wants to merge 4 commits intomainfrom
fix/all-tests-passing-268-268

Conversation

@joalves
Copy link

@joalves joalves commented Feb 21, 2026

Summary

  • 268/268 unit tests passing, exit code: 0
  • 138/138 cross-SDK test scenarios passing, exit code: 0
  • Improved TypeScript type safety with type keyword for type-only imports
  • Replaced forEach with for...of loops for consistency with code style
  • Extracted magic numbers into named constants (DEFAULT_RETRIES, DEFAULT_TIMEOUT_MS, RETRY_DELAY_MS)
  • Added input validation for attribute names in Context
  • Simplified Context.ready() promise handling
  • Added regex pattern/text length safety limits in MatchOperator
  • Modernized stringToUint8Array to use TextEncoder
  • Used URLSearchParams for query string building in Client
  • Refactored SDK constructor to extract client option parsing into static method
  • Added Absmartly alias export in index.ts
  • Added 226 lines of new context test coverage (custom fields, attributes, overrides, audience matching)

Test plan

  • All 268 unit tests pass (npm test, exit code 0)
  • All 138 cross-SDK test scenarios pass (exit code 0)
  • Review TypeScript type import changes for correctness
  • Verify no runtime behavior changes from forEach -> for...of refactoring
  • Confirm TextEncoder availability in target environments

Summary by CodeRabbit

  • New Features

    • Added new SDK method for context creation with pre-fetched data.
    • Introduced context accessor methods to retrieve SDK instance and current options.
    • Added public SDK export alias alongside existing identifier.
  • Documentation

    • Comprehensive README overhaul with rebranding and clarified product references.
    • Enhanced security guidance for API key handling.
    • Expanded Node.js and browser integration examples.
    • Improved SDK initialisation and context setup documentation.
  • Tests

    • Added extensive test coverage for cache invalidation scenarios.
  • Chores

    • Updated .gitignore with new entries.
    • Internal refactoring and error handling improvements.

…ssing)

- Use TypeScript `type` keyword for type-only imports across all modules
- Replace forEach with for...of loops per code style conventions
- Extract magic numbers into named constants (DEFAULT_RETRIES, DEFAULT_TIMEOUT_MS, RETRY_DELAY_MS)
- Add input validation for attribute names in Context
- Simplify Context.ready() promise handling
- Add regex pattern/text length limits in MatchOperator for safety
- Improve error messages in AudienceMatcher and MatchOperator
- Modernize stringToUint8Array to use TextEncoder
- Use URLSearchParams for query string building in Client
- Extract SDK._extractClientOptions into a static method
- Add Absmartly alias export in index.ts
- Add 226 lines of new context test coverage (custom fields, attributes, overrides, audience matching)
@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

Walkthrough

This pull request introduces comprehensive changes across documentation, test coverage, and source code. The README undergoes a substantial overhaul with branding adjustments, expanded usage examples for Node.js and browser environments, and reorganised sections for context creation, unit management, and event logging. The codebase receives type-only import conversions throughout, input validation enhancements on public-facing methods, and new public accessors (getSDK(), getOptions(), createContextWith()). Internal refactorings replace iteration patterns with for-of loops, abstract fetch implementation logic, extract client options handling, and improve error handling in JSON parsing and regex matching. Operator implementations are modified to support flexible parameter evaluation, and test coverage expands significantly to verify assignment cache invalidation across context refresh scenarios.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • mario-silva
  • calthejuggler

Poem

🐰 With whiskers twitching, types grow tight,
Documentation sees the light,
Validators check what enters in,
New methods bloom—let tests begin!
Fresh operators twist and turn,
The codebase learns, the cache will burn.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title references test counts (268/268, 138/138) but the changeset includes extensive code modifications beyond tests: refactoring loops, extracting constants, adding validation, modernizing utilities, restructuring documentation, and adding new public methods. Revise title to reflect the primary change more clearly. Consider: 'Refactor SDK internals and add public accessors' or specify the main category (e.g., code quality improvements, test coverage, or API enhancements) rather than test counts alone.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/all-tests-passing-268-268

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.41.0)
src/__tests__/context.test.js

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Fix eq operator to handle numeric string comparisons and in operator
to properly check string containment and collection membership.
Exposes the SDK instance and context options through public API so
React and Angular SDKs no longer need to access private _sdk/_opts fields.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
src/fetch.ts (1)

34-37: Consider throwing an error when no fetch implementation is available.

Returning undefined when no fetch implementation is found could lead to confusing runtime errors when exported is invoked. A descriptive error would aid debugging.

💡 Suggested improvement
-	return undefined;
+	throw new Error(
+		"No fetch implementation available. Ensure you are running in a supported environment (browser, Node.js, or Web Worker)."
+	);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/fetch.ts` around lines 34 - 37, getFetchImplementation currently returns
undefined when no fetch implementation is found, which causes unclear runtime
failures when the module-level exported variable exported is used; change
getFetchImplementation so that instead of returning undefined it throws a clear,
descriptive Error (e.g., "No fetch implementation available: please provide
global fetch or a polyfill") and ensure the module still assigns const exported
= getFetchImplementation(); so callers fail fast with the descriptive exception.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Around line 131-141: Replace the non-standard script tag attribute
type="javascript" with a valid attribute (either type="text/javascript") or
remove the type attribute entirely so the browser treats it as JavaScript;
update the <script> tag that contains the request object and the call to
sdk.createContextWith(request, {{ serverSideContext.data() }}) to use the
corrected type or no type so the snippet is valid.
- Around line 51-54: The fenced code block containing "Browser --> Your Server
(with API key) --> ABsmartly API" is missing a language specifier; update that
fenced block in README.md to use a language token such as ```text or
```plaintext so the block becomes ```text ... ``` and satisfies linting and
improves rendering consistency.

In `@src/client.ts`:
- Line 268: The retry wrapper call uses the raw instance option
this._opts.timeout instead of the resolved per-request timeout
(options.timeout), causing incorrect retry/timeout accounting; update the call
to tryWith in the function that currently passes this._opts.timeout to instead
pass the already-resolved timeout (e.g., options.timeout) with the same fallback
(options.timeout ?? DEFAULT_TIMEOUT_MS) while keeping the retries fallback
(this._opts.retries ?? DEFAULT_RETRIES) unchanged.

In `@src/context.ts`:
- Around line 835-845: The scheduled publish/refresh timeout handlers call
this._logError in their outer catch, which duplicates errors already logged by
this._flush and this._refresh; remove the outer this._logError calls inside the
setTimeout handlers (the handlers that call this._flush and this._refresh via
the this._publishTimeout and the similar scheduled block at 1038-1048) so that
only the inner _flush/_refresh error paths log the error. Ensure the timeout
handlers still swallow/recover the error (no rethrow) after removing the outer
log to preserve behavior.

In `@src/fetch.ts`:
- Around line 19-32: The current runtime check uses a bare identifier "global"
which can throw ReferenceError in strict browser environments; update the check
to safely detect the environment (e.g., use typeof global !== "undefined" or
globalThis) and prefer globalThis.fetch when available, and only fall back to
importing "node-fetch" if no fetch exists; update the branch that currently
returns global.fetch.bind(global) and the fallback that imports "node-fetch"
(the anonymous function handling url/opts and the import("node-fetch") logic) to
use the safe existence check so no ReferenceError occurs.

In `@src/jsonexpr/operators/match.ts`:
- Around line 13-23: Before compiling untrusted regex patterns, validate them
with a ReDoS-safe checker: import safe-regex2 (e.g. safeRegex) and, after the
text length check and before new RegExp(pattern), call if (!safeRegex(pattern))
{ console.error("Unsafe regex pattern rejected"); return null; } — update the
code around the RegExp compilation and the variables pattern, text,
MAX_PATTERN_LENGTH, MAX_TEXT_LENGTH, and compiled to perform this check so
catastrophic-backtracking patterns are rejected prior to compilation.

---

Nitpick comments:
In `@src/fetch.ts`:
- Around line 34-37: getFetchImplementation currently returns undefined when no
fetch implementation is found, which causes unclear runtime failures when the
module-level exported variable exported is used; change getFetchImplementation
so that instead of returning undefined it throws a clear, descriptive Error
(e.g., "No fetch implementation available: please provide global fetch or a
polyfill") and ensure the module still assigns const exported =
getFetchImplementation(); so callers fail fast with the descriptive exception.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87abcae and 589f8c9.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (18)
  • .gitignore
  • README.md
  • src/__tests__/context.test.js
  • src/__tests__/jsonexpr/operators/eq.test.js
  • src/__tests__/jsonexpr/operators/in.test.js
  • src/abort-controller-shim.ts
  • src/client.ts
  • src/context.ts
  • src/fetch.ts
  • src/index.ts
  • src/jsonexpr/operators/eq.ts
  • src/jsonexpr/operators/in.ts
  • src/jsonexpr/operators/match.ts
  • src/matcher.ts
  • src/provider.ts
  • src/publisher.ts
  • src/sdk.ts
  • src/utils.ts

Comment on lines +51 to +54
```
Browser --> Your Server (with API key) --> ABsmartly API
session token only
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language specifier to the fenced code block.

The architecture diagram code block lacks a language specifier. While this is plain text, adding text or plaintext satisfies linting rules and improves rendering consistency.

📝 Proposed fix
-```
+```text
 Browser --> Your Server (with API key) --> ABsmartly API
             session token only
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 51-51: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 51 - 54, The fenced code block containing "Browser
--> Your Server (with API key) --> ABsmartly API" is missing a language
specifier; update that fenced block in README.md to use a language token such as
```text or ```plaintext so the block becomes ```text ... ``` and satisfies
linting and improves rendering consistency.

Comment on lines +131 to +141
<head>
<script type="javascript">
const request = {
units: {
session_id: "5ebf06d8cb5d8137290c4abb64155584fbdb64d8",
},
};

const context = sdk.createContextWith(request, {{ serverSideContext.data() }});
</script>
</head>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix invalid type attribute in script tag.

The type="javascript" attribute is non-standard. Use type="text/javascript" or omit the attribute entirely (modern browsers default to JavaScript).

📝 Proposed fix
-    <script type="javascript">
+    <script type="text/javascript">

Or simply:

-    <script type="javascript">
+    <script>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<head>
<script type="javascript">
const request = {
units: {
session_id: "5ebf06d8cb5d8137290c4abb64155584fbdb64d8",
},
};
const context = sdk.createContextWith(request, {{ serverSideContext.data() }});
</script>
</head>
<head>
<script>
const request = {
units: {
session_id: "5ebf06d8cb5d8137290c4abb64155584fbdb64d8",
},
};
const context = sdk.createContextWith(request, {{ serverSideContext.data() }});
</script>
</head>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 131 - 141, Replace the non-standard script tag
attribute type="javascript" with a valid attribute (either
type="text/javascript") or remove the type attribute entirely so the browser
treats it as JavaScript; update the <script> tag that contains the request
object and the call to sdk.createContextWith(request, {{
serverSideContext.data() }}) to use the corrected type or no type so the snippet
is valid.

};

return tryWith(this._opts.retries ?? 5, this._opts.timeout ?? 3000)
return tryWith(this._opts.retries ?? DEFAULT_RETRIES, this._opts.timeout ?? DEFAULT_TIMEOUT_MS)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Per-request timeout is not honoured in retry accounting.

Line 268 passes this._opts.timeout into tryWith, but Line 252 already resolves the effective timeout (options.timeout fallback included). This can produce wrong retry/timeout behaviour for per-request overrides.

💡 Proposed fix
-		return tryWith(this._opts.retries ?? DEFAULT_RETRIES, this._opts.timeout ?? DEFAULT_TIMEOUT_MS)
+		return tryWith(this._opts.retries ?? DEFAULT_RETRIES, timeout)
 			.then((value: string) => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return tryWith(this._opts.retries ?? DEFAULT_RETRIES, this._opts.timeout ?? DEFAULT_TIMEOUT_MS)
return tryWith(this._opts.retries ?? DEFAULT_RETRIES, timeout)
.then((value: string) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client.ts` at line 268, The retry wrapper call uses the raw instance
option this._opts.timeout instead of the resolved per-request timeout
(options.timeout), causing incorrect retry/timeout accounting; update the call
to tryWith in the function that currently passes this._opts.timeout to instead
pass the already-resolved timeout (e.g., options.timeout) with the same fallback
(options.timeout ?? DEFAULT_TIMEOUT_MS) while keeping the retries fallback
(this._opts.retries ?? DEFAULT_RETRIES) unchanged.

Comment on lines +835 to +845
this._publishTimeout = setTimeout(async () => {
try {
await new Promise<void>((resolve, reject) => {
this._flush((error?: Error) => {
if (error) reject(error);
else resolve();
});
});
} catch (error) {
this._logError(error as Error);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Scheduled publish/refresh failures are logged twice.

At Line 844 and Line 1047, the outer catch logs again, but _flush (Lines 917-919) and _refresh (Lines 949-950) already log the same error. This duplicates "error" events for a single failure.

💡 Proposed fix
-				} catch (error) {
-					this._logError(error as Error);
+				} catch {
+					// _flush already logs publish errors.
 				}
@@
-				} catch (error) {
-					this._logError(error as Error);
+				} catch {
+					// _refresh already logs refresh errors.
 				}

Also applies to: 1038-1048

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/context.ts` around lines 835 - 845, The scheduled publish/refresh timeout
handlers call this._logError in their outer catch, which duplicates errors
already logged by this._flush and this._refresh; remove the outer this._logError
calls inside the setTimeout handlers (the handlers that call this._flush and
this._refresh via the this._publishTimeout and the similar scheduled block at
1038-1048) so that only the inner _flush/_refresh error paths log the error.
Ensure the timeout handlers still swallow/recover the error (no rethrow) after
removing the outer log to preserve behavior.

Comment on lines +19 to +32
if (global) {
if (global.fetch) {
return global.fetch.bind(global);
}
return function (url: string, opts: Record<string, unknown>) {
return new Promise((resolve, reject) => {
import("node-fetch")
.then((fetchNode) => {
fetchNode.default(url.replace(/^\/\//g, "https://"), opts).then(resolve).catch(reject);
})
.catch(reject);
});
};
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential ReferenceError when accessing global in strict browser environments.

The check if (global) may throw a ReferenceError in browser environments where global is not defined. Consider using a safer check:

🛡️ Proposed fix for safer global check
-	if (global) {
-		if (global.fetch) {
-			return global.fetch.bind(global);
+	if (typeof global !== "undefined") {
+		if (global.fetch) {
+			return global.fetch.bind(global);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (global) {
if (global.fetch) {
return global.fetch.bind(global);
}
return function (url: string, opts: Record<string, unknown>) {
return new Promise((resolve, reject) => {
import("node-fetch")
.then((fetchNode) => {
fetchNode.default(url.replace(/^\/\//g, "https://"), opts).then(resolve).catch(reject);
})
.catch(reject);
});
};
}
if (typeof global !== "undefined") {
if (global.fetch) {
return global.fetch.bind(global);
}
return function (url: string, opts: Record<string, unknown>) {
return new Promise((resolve, reject) => {
import("node-fetch")
.then((fetchNode) => {
fetchNode.default(url.replace(/^\/\//g, "https://"), opts).then(resolve).catch(reject);
})
.catch(reject);
});
};
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/fetch.ts` around lines 19 - 32, The current runtime check uses a bare
identifier "global" which can throw ReferenceError in strict browser
environments; update the check to safely detect the environment (e.g., use
typeof global !== "undefined" or globalThis) and prefer globalThis.fetch when
available, and only fall back to importing "node-fetch" if no fetch exists;
update the branch that currently returns global.fetch.bind(global) and the
fallback that imports "node-fetch" (the anonymous function handling url/opts and
the import("node-fetch") logic) to use the safe existence check so no
ReferenceError occurs.

Comment on lines +13 to 23
if (pattern.length > MAX_PATTERN_LENGTH) {
console.error(`Regex pattern too long: ${pattern.length} > ${MAX_PATTERN_LENGTH}`);
return null;
}
if (text.length > MAX_TEXT_LENGTH) {
console.error(`Text too long for regex matching: ${text.length} > ${MAX_TEXT_LENGTH}`);
return null;
}
try {
const compiled = new RegExp(pattern);
return compiled.test(text);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd /tmp && find . -name "match.ts" -type f 2>/dev/null | head -20

Repository: absmartly/javascript-sdk

Length of output: 50


🏁 Script executed:

git ls-files | grep -E "match\.ts|package\.json"

Repository: absmartly/javascript-sdk

Length of output: 112


🏁 Script executed:

cat -n src/jsonexpr/operators/match.ts | head -50

Repository: absmartly/javascript-sdk

Length of output: 1251


🏁 Script executed:

cat package.json | head -100

Repository: absmartly/javascript-sdk

Length of output: 3016


🏁 Script executed:

grep -i "safe-regex\|redos\|security" package.json

Repository: absmartly/javascript-sdk

Length of output: 50


🏁 Script executed:

git log --oneline src/jsonexpr/operators/match.ts | head -10

Repository: absmartly/javascript-sdk

Length of output: 137


🌐 Web query:

safe-regex2 npm package maintained

💡 Result:

Yes—safe-regex2 is still maintained (it’s in the fastify/safe-regex2 repo). The latest release is v5.0.0 (Mar 8, 2025) [1], and the repository has continued to receive commits after that (commit activity shown through Oct 17, 2025) [2]. Third-party health trackers also rate its maintenance as “Sustainable” and report recent commits/releases within the last year (relative to their scan dates) [3].

Sources:
[1] fastify/safe-regex2 GitHub releases (v5.0.0) (github.com)
[2] fastify/safe-regex2 commit history (github.com)
[3] Snyk package health for safe-regex2 (security.snyk.io)

Citations:


🏁 Script executed:

grep -r "safeRegex\|safe-regex\|ReDoS" src/ --include="*.ts" --include="*.js"

Repository: absmartly/javascript-sdk

Length of output: 50


🏁 Script executed:

grep -r "RegExp\|new RegExp" src/jsonexpr/ --include="*.ts" | head -20

Repository: absmartly/javascript-sdk

Length of output: 142


Add ReDoS protection before regex compilation in dynamic pattern matching.

Length caps alone do not prevent ReDoS attacks. Patterns like (a+)+ or (a|a)+ cause catastrophic backtracking despite being short enough to pass the 1000-character limit. Since this SDK processes untrusted user-supplied regex patterns, add pattern validation using safe-regex2 before compilation:

import safeRegex from "safe-regex2";

// After text length check, before RegExp compilation:
if (!safeRegex(pattern)) {
    console.error("Unsafe regex pattern rejected");
    return null;
}

The try-catch block catches syntax errors only; it does not prevent execution hangs caused by catastrophic backtracking.

🧰 Tools
🪛 ast-grep (0.41.0)

[warning] 21-21: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(pattern)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/jsonexpr/operators/match.ts` around lines 13 - 23, Before compiling
untrusted regex patterns, validate them with a ReDoS-safe checker: import
safe-regex2 (e.g. safeRegex) and, after the text length check and before new
RegExp(pattern), call if (!safeRegex(pattern)) { console.error("Unsafe regex
pattern rejected"); return null; } — update the code around the RegExp
compilation and the variables pattern, text, MAX_PATTERN_LENGTH,
MAX_TEXT_LENGTH, and compiled to perform this check so catastrophic-backtracking
patterns are rejected prior to compilation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant