yume-dsl-rich-text 1.2.2 → 1.2.3
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/README.md +2 -2
- package/dist/index.cjs +241 -84
- package/dist/index.d.cts +2 -42
- package/dist/index.d.ts +2 -42
- package/dist/index.js +241 -82
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -801,13 +801,13 @@ const tokens = dsl.parse(input);
|
|
|
801
801
|
| Category | Exports |
|
|
802
802
|
|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
803
803
|
| **Core** | `parseRichText`, `stripRichText`, `createParser`, `parseStructural`, `printStructural`, `buildZones` |
|
|
804
|
-
| **Incremental Parsing** | `parseIncremental`, `
|
|
804
|
+
| **Incremental Parsing** | `parseIncremental`, `createIncrementalSession` |
|
|
805
805
|
| **Configuration** | `DEFAULT_SYNTAX`, `createEasySyntax`, `createSyntax`, `DEFAULT_TAG_NAME`, `createTagNameConfig`, `createEasyStableId` |
|
|
806
806
|
| **Handler Helpers** | `createPipeHandlers`, `createSimpleInlineHandlers`, `createSimpleBlockHandlers`, `createSimpleRawHandlers`, `declareMultilineTags` |
|
|
807
807
|
| **Handler Utilities** | `parsePipeArgs`, `parsePipeTextArgs`, `parsePipeTextList`, `extractText`, `createTextToken`, `splitTokensByPipe`, `materializeTextTokens`, `unescapeInline`, `readEscapedSequence`, `createToken`, `createTokenGuard` |
|
|
808
808
|
| **Token Traversal** | `walkTokens`, `mapTokens` |
|
|
809
809
|
| **Position Tracking** | `buildPositionTracker` |
|
|
810
|
-
| **Types** | `TextToken`, `TokenDraft`, `CreateId`, `DslContext`, `TagHandler`, `TagForm`, `ParseOptions`, `ParserBaseOptions`, `StructuralParseOptions`, `Parser`, `SyntaxInput`, `SyntaxConfig`, `TagNameConfig`, `BlockTagInput`, `MultilineForm`, `ErrorCode`, `ParseError`, `StructuralNode`, `SourcePosition`, `SourceSpan`, `PositionTracker`, `PipeArgs`, `PipeHandlerDefinition`, `EasyStableIdOptions`, `PrintOptions`, `TokenVisitContext`, `WalkVisitor`, `MapVisitor`, `Zone`, `IncrementalDocument`, `IncrementalEdit`, `IncrementalParseOptions`, `
|
|
810
|
+
| **Types** | `TextToken`, `TokenDraft`, `CreateId`, `DslContext`, `TagHandler`, `TagForm`, `ParseOptions`, `ParserBaseOptions`, `StructuralParseOptions`, `Parser`, `SyntaxInput`, `SyntaxConfig`, `TagNameConfig`, `BlockTagInput`, `MultilineForm`, `ErrorCode`, `ParseError`, `StructuralNode`, `SourcePosition`, `SourceSpan`, `PositionTracker`, `PipeArgs`, `PipeHandlerDefinition`, `EasyStableIdOptions`, `PrintOptions`, `TokenVisitContext`, `WalkVisitor`, `MapVisitor`, `Zone`, `IncrementalDocument`, `IncrementalEdit`, `IncrementalParseOptions`, `IncrementalSessionOptions`, `NarrowToken`, `NarrowDraft`, `NarrowTokenUnion` |
|
|
811
811
|
|
|
812
812
|
See the [Exports wiki page](https://github.com/chiba233/yumeDSL/wiki/en-Exports) for full signatures and detailed
|
|
813
813
|
documentation.
|
package/dist/index.cjs
CHANGED
|
@@ -56,9 +56,7 @@ __export(index_exports, {
|
|
|
56
56
|
resetTokenIdSeed: () => resetTokenIdSeed,
|
|
57
57
|
splitTokensByPipe: () => splitTokensByPipe,
|
|
58
58
|
stripRichText: () => stripRichText,
|
|
59
|
-
tryUpdateIncremental: () => tryUpdateIncremental,
|
|
60
59
|
unescapeInline: () => unescapeInline,
|
|
61
|
-
updateIncremental: () => updateIncremental,
|
|
62
60
|
walkTokens: () => walkTokens,
|
|
63
61
|
withSyntax: () => withSyntax,
|
|
64
62
|
withTagNameConfig: () => withTagNameConfig
|
|
@@ -2252,10 +2250,53 @@ var isIncrementalUpdateError = (error) => {
|
|
|
2252
2250
|
const withCode = error;
|
|
2253
2251
|
return withCode.code === "INVALID_EDIT_RANGE" || withCode.code === "NEW_SOURCE_LENGTH_MISMATCH" || withCode.code === "EDIT_TEXT_MISMATCH" || withCode.code === "UNKNOWN";
|
|
2254
2252
|
};
|
|
2253
|
+
var isPlainObject = (value) => {
|
|
2254
|
+
if (!value || typeof value !== "object") return false;
|
|
2255
|
+
const prototype = Object.getPrototypeOf(value);
|
|
2256
|
+
return prototype === Object.prototype || prototype === null;
|
|
2257
|
+
};
|
|
2258
|
+
var cloneSnapshotValueInternal = (value, seen) => {
|
|
2259
|
+
if (Array.isArray(value)) {
|
|
2260
|
+
const seenArray = seen.get(value);
|
|
2261
|
+
if (seenArray) return seenArray;
|
|
2262
|
+
const next = new Array(value.length);
|
|
2263
|
+
seen.set(value, next);
|
|
2264
|
+
for (let i = 0; i < value.length; i++) {
|
|
2265
|
+
next[i] = cloneSnapshotValueInternal(value[i], seen);
|
|
2266
|
+
}
|
|
2267
|
+
return next;
|
|
2268
|
+
}
|
|
2269
|
+
if (isPlainObject(value)) {
|
|
2270
|
+
const seenObject = seen.get(value);
|
|
2271
|
+
if (seenObject) return seenObject;
|
|
2272
|
+
const next = {};
|
|
2273
|
+
seen.set(value, next);
|
|
2274
|
+
const keys = Object.keys(value);
|
|
2275
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2276
|
+
const key = keys[i];
|
|
2277
|
+
next[key] = cloneSnapshotValueInternal(value[key], seen);
|
|
2278
|
+
}
|
|
2279
|
+
return next;
|
|
2280
|
+
}
|
|
2281
|
+
return value;
|
|
2282
|
+
};
|
|
2283
|
+
var cloneSnapshotValue = (value) => cloneSnapshotValueInternal(value, /* @__PURE__ */ new WeakMap());
|
|
2284
|
+
var cloneHandlersSnapshot = (handlers) => {
|
|
2285
|
+
if (!handlers) return void 0;
|
|
2286
|
+
const next = {};
|
|
2287
|
+
const keys = Object.keys(handlers);
|
|
2288
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2289
|
+
const key = keys[i];
|
|
2290
|
+
const handler = handlers[key];
|
|
2291
|
+
next[key] = handler ? cloneSnapshotValue(handler) : handler;
|
|
2292
|
+
}
|
|
2293
|
+
return next;
|
|
2294
|
+
};
|
|
2255
2295
|
var cloneParseOptions = (options) => {
|
|
2256
2296
|
if (!options) return void 0;
|
|
2257
2297
|
return {
|
|
2258
2298
|
...options,
|
|
2299
|
+
handlers: cloneHandlersSnapshot(options.handlers),
|
|
2259
2300
|
syntax: options.syntax ? { ...options.syntax } : void 0,
|
|
2260
2301
|
tagName: options.tagName ? { ...options.tagName } : void 0,
|
|
2261
2302
|
allowForms: options.allowForms ? [...options.allowForms] : void 0
|
|
@@ -2272,28 +2313,53 @@ var getObjectIdentity = (value) => {
|
|
|
2272
2313
|
objectIdentityMap.set(value, next);
|
|
2273
2314
|
return next;
|
|
2274
2315
|
};
|
|
2316
|
+
var getIdentityForUnknown = (value) => {
|
|
2317
|
+
if (typeof value === "object" && value !== null || typeof value === "function") {
|
|
2318
|
+
return getObjectIdentity(value);
|
|
2319
|
+
}
|
|
2320
|
+
return 0;
|
|
2321
|
+
};
|
|
2322
|
+
var buildHandlersShapeFingerprint = (handlers) => {
|
|
2323
|
+
if (!handlers || typeof handlers !== "object") return 0;
|
|
2324
|
+
const record = handlers;
|
|
2325
|
+
const keys = Object.keys(record).sort();
|
|
2326
|
+
let hash = fnvInit();
|
|
2327
|
+
hash = fnvFeedU32(hash, keys.length);
|
|
2328
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2329
|
+
const key = keys[i];
|
|
2330
|
+
const handler = record[key];
|
|
2331
|
+
hash = fnvFeedU32(hash, hashText(key));
|
|
2332
|
+
if (!handler || typeof handler !== "object") continue;
|
|
2333
|
+
const handlerRecord = handler;
|
|
2334
|
+
hash = fnvFeedU32(hash, getIdentityForUnknown(handlerRecord.inline));
|
|
2335
|
+
hash = fnvFeedU32(hash, getIdentityForUnknown(handlerRecord.raw));
|
|
2336
|
+
hash = fnvFeedU32(hash, getIdentityForUnknown(handlerRecord.block));
|
|
2337
|
+
}
|
|
2338
|
+
return hash >>> 0;
|
|
2339
|
+
};
|
|
2340
|
+
var DEFAULT_PARSE_OPTIONS_FINGERPRINT = fnvFeedU32(fnvInit(), 2654435769);
|
|
2275
2341
|
var buildParseOptionsFingerprint = (options) => {
|
|
2276
|
-
if (!options) return
|
|
2342
|
+
if (!options) return DEFAULT_PARSE_OPTIONS_FINGERPRINT;
|
|
2277
2343
|
const syntax = options.syntax ?? {};
|
|
2278
2344
|
const tagName = options.tagName ?? {};
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2345
|
+
const allowForms = options.allowForms ?? [];
|
|
2346
|
+
let hash = fnvInit();
|
|
2347
|
+
hash = fnvFeedU32(hash, buildHandlersShapeFingerprint(options.handlers));
|
|
2348
|
+
hash = fnvFeedU32(hash, allowForms.length);
|
|
2349
|
+
for (let i = 0; i < allowForms.length; i++) {
|
|
2350
|
+
hash = fnvFeedU32(hash, hashText(allowForms[i]));
|
|
2351
|
+
}
|
|
2352
|
+
hash = fnvFeedU32(hash, hashText(syntax.tagOpen ?? ""));
|
|
2353
|
+
hash = fnvFeedU32(hash, hashText(syntax.tagClose ?? ""));
|
|
2354
|
+
hash = fnvFeedU32(hash, hashText(syntax.endTag ?? ""));
|
|
2355
|
+
hash = fnvFeedU32(hash, hashText(syntax.tagDivider ?? ""));
|
|
2356
|
+
hash = fnvFeedU32(hash, hashText(syntax.rawOpen ?? ""));
|
|
2357
|
+
hash = fnvFeedU32(hash, hashText(syntax.rawClose ?? ""));
|
|
2358
|
+
hash = fnvFeedU32(hash, hashText(syntax.blockOpen ?? ""));
|
|
2359
|
+
hash = fnvFeedU32(hash, hashText(syntax.blockClose ?? ""));
|
|
2360
|
+
hash = fnvFeedU32(hash, getObjectIdentity(tagName.isTagStartChar));
|
|
2361
|
+
hash = fnvFeedU32(hash, getObjectIdentity(tagName.isTagChar));
|
|
2362
|
+
return hash >>> 0;
|
|
2297
2363
|
};
|
|
2298
2364
|
var hasUnsafeZoneCoverageTailGap = (doc, edit) => {
|
|
2299
2365
|
const lastZone = doc.zones[doc.zones.length - 1];
|
|
@@ -2318,8 +2384,10 @@ var flattenZones = (zones) => {
|
|
|
2318
2384
|
}
|
|
2319
2385
|
return tree;
|
|
2320
2386
|
};
|
|
2387
|
+
var LEFT_LOOKBEHIND_ZONES = 1;
|
|
2321
2388
|
var RIGHT_REUSE_PROBE_ZONES = 2;
|
|
2322
2389
|
var RIGHT_REUSE_PROBE_EXTRA_ZONES = 1;
|
|
2390
|
+
var RIGHT_REUSE_PROBE_SIGNATURE_NODE_BUDGET = 4096;
|
|
2323
2391
|
var NODE_TAG_TEXT = 1;
|
|
2324
2392
|
var NODE_TAG_ESCAPE = 2;
|
|
2325
2393
|
var NODE_TAG_SEPARATOR = 3;
|
|
@@ -2328,9 +2396,20 @@ var NODE_TAG_RAW = 5;
|
|
|
2328
2396
|
var NODE_TAG_BLOCK = 6;
|
|
2329
2397
|
var ZONE_TAG = 7;
|
|
2330
2398
|
var zoneSignatureCache = /* @__PURE__ */ new WeakMap();
|
|
2399
|
+
var parseOptionsFingerprintCache = /* @__PURE__ */ new WeakMap();
|
|
2331
2400
|
var incrementalDebugSink;
|
|
2332
2401
|
var hashText = (value) => fnv1a(value);
|
|
2333
|
-
var
|
|
2402
|
+
var getCachedOptionsFingerprint = (doc) => parseOptionsFingerprintCache.get(doc);
|
|
2403
|
+
var setCachedOptionsFingerprint = (doc, fingerprint) => {
|
|
2404
|
+
parseOptionsFingerprintCache.set(doc, fingerprint);
|
|
2405
|
+
};
|
|
2406
|
+
var tryConsumeSignatureBudget = (budget) => {
|
|
2407
|
+
if (budget.remaining <= 0) return false;
|
|
2408
|
+
budget.remaining -= 1;
|
|
2409
|
+
return true;
|
|
2410
|
+
};
|
|
2411
|
+
var nodeSignature = (node, budget) => {
|
|
2412
|
+
if (budget && !tryConsumeSignatureBudget(budget)) return void 0;
|
|
2334
2413
|
if (node.type === "text") {
|
|
2335
2414
|
let hash = fnvInit();
|
|
2336
2415
|
hash = fnvFeedU32(hash, NODE_TAG_TEXT);
|
|
@@ -2353,7 +2432,9 @@ var nodeSignature = (node) => {
|
|
|
2353
2432
|
hash = fnvFeedU32(hash, NODE_TAG_INLINE);
|
|
2354
2433
|
hash = fnvFeedU32(hash, hashText(node.tag));
|
|
2355
2434
|
for (let i = 0; i < node.children.length; i++) {
|
|
2356
|
-
|
|
2435
|
+
const childHash = nodeSignature(node.children[i], budget);
|
|
2436
|
+
if (childHash === void 0) return void 0;
|
|
2437
|
+
hash = fnvFeedU32(hash, childHash);
|
|
2357
2438
|
}
|
|
2358
2439
|
return hash >>> 0;
|
|
2359
2440
|
}
|
|
@@ -2364,7 +2445,9 @@ var nodeSignature = (node) => {
|
|
|
2364
2445
|
hash = fnvFeedU32(hash, node.content.length);
|
|
2365
2446
|
hash = fnvFeedU32(hash, hashText(node.content));
|
|
2366
2447
|
for (let i = 0; i < node.args.length; i++) {
|
|
2367
|
-
|
|
2448
|
+
const argHash = nodeSignature(node.args[i], budget);
|
|
2449
|
+
if (argHash === void 0) return void 0;
|
|
2450
|
+
hash = fnvFeedU32(hash, argHash);
|
|
2368
2451
|
}
|
|
2369
2452
|
return hash >>> 0;
|
|
2370
2453
|
}
|
|
@@ -2373,26 +2456,36 @@ var nodeSignature = (node) => {
|
|
|
2373
2456
|
hash = fnvFeedU32(hash, NODE_TAG_BLOCK);
|
|
2374
2457
|
hash = fnvFeedU32(hash, hashText(node.tag));
|
|
2375
2458
|
for (let i = 0; i < node.args.length; i++) {
|
|
2376
|
-
|
|
2459
|
+
const argHash = nodeSignature(node.args[i], budget);
|
|
2460
|
+
if (argHash === void 0) return void 0;
|
|
2461
|
+
hash = fnvFeedU32(hash, argHash);
|
|
2377
2462
|
}
|
|
2378
2463
|
for (let i = 0; i < node.children.length; i++) {
|
|
2379
|
-
|
|
2464
|
+
const childHash = nodeSignature(node.children[i], budget);
|
|
2465
|
+
if (childHash === void 0) return void 0;
|
|
2466
|
+
hash = fnvFeedU32(hash, childHash);
|
|
2380
2467
|
}
|
|
2381
2468
|
return hash >>> 0;
|
|
2382
2469
|
}
|
|
2383
2470
|
return assertUnreachable(node);
|
|
2384
2471
|
};
|
|
2385
|
-
var zoneSignature = (zone) => {
|
|
2386
|
-
|
|
2387
|
-
|
|
2472
|
+
var zoneSignature = (zone, budget) => {
|
|
2473
|
+
if (!budget) {
|
|
2474
|
+
const cached = zoneSignatureCache.get(zone);
|
|
2475
|
+
if (cached !== void 0) return cached;
|
|
2476
|
+
}
|
|
2388
2477
|
let hash = fnvInit();
|
|
2389
2478
|
hash = fnvFeedU32(hash, ZONE_TAG);
|
|
2390
2479
|
hash = fnvFeedU32(hash, zone.endOffset - zone.startOffset);
|
|
2391
2480
|
for (let i = 0; i < zone.nodes.length; i++) {
|
|
2392
|
-
|
|
2481
|
+
const signature = nodeSignature(zone.nodes[i], budget);
|
|
2482
|
+
if (signature === void 0) return void 0;
|
|
2483
|
+
hash = fnvFeedU32(hash, signature);
|
|
2393
2484
|
}
|
|
2394
2485
|
const finalized = hash >>> 0;
|
|
2395
|
-
|
|
2486
|
+
if (!budget) {
|
|
2487
|
+
zoneSignatureCache.set(zone, finalized);
|
|
2488
|
+
}
|
|
2396
2489
|
return finalized;
|
|
2397
2490
|
};
|
|
2398
2491
|
var isSafeRightReuse = (oldRightZones, newSource, seamNewOffset, delta, tracker, parseOptions) => {
|
|
@@ -2414,13 +2507,21 @@ var isSafeRightReuse = (oldRightZones, newSource, seamNewOffset, delta, tracker,
|
|
|
2414
2507
|
);
|
|
2415
2508
|
const probeZones = buildZones(probeTree);
|
|
2416
2509
|
if (probeZones.length < probeZoneCount) return { ok: false, probeSliceBytes: probeLength };
|
|
2510
|
+
const signatureBudget = {
|
|
2511
|
+
remaining: RIGHT_REUSE_PROBE_SIGNATURE_NODE_BUDGET
|
|
2512
|
+
};
|
|
2417
2513
|
for (let i = 0; i < probeZoneCount; i++) {
|
|
2418
2514
|
const expected = oldRightZones[i];
|
|
2419
2515
|
const actual = probeZones[i];
|
|
2420
2516
|
if (actual.startOffset !== expected.startOffset + delta) return { ok: false, probeSliceBytes: probeLength };
|
|
2421
2517
|
if (actual.endOffset !== expected.endOffset + delta) return { ok: false, probeSliceBytes: probeLength };
|
|
2422
2518
|
if (actual.nodes.length !== expected.nodes.length) return { ok: false, probeSliceBytes: probeLength };
|
|
2423
|
-
|
|
2519
|
+
const actualSignature = zoneSignature(actual, signatureBudget);
|
|
2520
|
+
if (actualSignature === void 0) return { ok: false, probeSliceBytes: probeLength };
|
|
2521
|
+
const expectedSignature = zoneSignature(expected);
|
|
2522
|
+
if (expectedSignature === void 0 || actualSignature !== expectedSignature) {
|
|
2523
|
+
return { ok: false, probeSliceBytes: probeLength };
|
|
2524
|
+
}
|
|
2424
2525
|
}
|
|
2425
2526
|
return { ok: true, probeSliceBytes: probeLength };
|
|
2426
2527
|
};
|
|
@@ -2519,6 +2620,14 @@ var shiftZone = (zone, delta, tracker) => ({
|
|
|
2519
2620
|
endOffset: zone.endOffset + delta,
|
|
2520
2621
|
nodes: zone.nodes.map((node) => shiftNode(node, delta, tracker))
|
|
2521
2622
|
});
|
|
2623
|
+
var shiftZoneWithSignature = (zone, delta, tracker) => {
|
|
2624
|
+
const shifted = shiftZone(zone, delta, tracker);
|
|
2625
|
+
const signature = zoneSignature(zone);
|
|
2626
|
+
if (signature !== void 0) {
|
|
2627
|
+
zoneSignatureCache.set(shifted, signature);
|
|
2628
|
+
}
|
|
2629
|
+
return shifted;
|
|
2630
|
+
};
|
|
2522
2631
|
var findDirtyRange = (zones, edit) => {
|
|
2523
2632
|
let firstOverlap = -1;
|
|
2524
2633
|
let lastOverlap = -1;
|
|
@@ -2531,7 +2640,7 @@ var findDirtyRange = (zones, edit) => {
|
|
|
2531
2640
|
}
|
|
2532
2641
|
if (firstOverlap !== -1) {
|
|
2533
2642
|
return {
|
|
2534
|
-
from: Math.max(0, firstOverlap -
|
|
2643
|
+
from: Math.max(0, firstOverlap - LEFT_LOOKBEHIND_ZONES),
|
|
2535
2644
|
to: Math.min(zones.length - 1, lastOverlap + 1)
|
|
2536
2645
|
};
|
|
2537
2646
|
}
|
|
@@ -2543,10 +2652,48 @@ var findDirtyRange = (zones, edit) => {
|
|
|
2543
2652
|
}
|
|
2544
2653
|
}
|
|
2545
2654
|
return {
|
|
2546
|
-
from: Math.max(0, insertionIndex -
|
|
2655
|
+
from: Math.max(0, insertionIndex - LEFT_LOOKBEHIND_ZONES),
|
|
2547
2656
|
to: Math.min(zones.length - 1, insertionIndex)
|
|
2548
2657
|
};
|
|
2549
2658
|
};
|
|
2659
|
+
var reparseDirtyWindowUntilStable = (doc, dirtyFrom, dirtyTo, edit, delta, newSource, tracker, parseOptions, cumulativeBudget, cumulativeReparsedBytes) => {
|
|
2660
|
+
let nextDirtyTo = dirtyTo;
|
|
2661
|
+
let nextDirtyZones = [];
|
|
2662
|
+
let nextCumulativeReparsedBytes = cumulativeReparsedBytes;
|
|
2663
|
+
while (true) {
|
|
2664
|
+
const dirtyStartOld = doc.zones[dirtyFrom].startOffset;
|
|
2665
|
+
const dirtyEndOld = doc.zones[nextDirtyTo].endOffset;
|
|
2666
|
+
const dirtyStartNew = mapOldOffsetToNew(edit, delta, dirtyStartOld);
|
|
2667
|
+
const dirtyEndNew = mapOldOffsetToNew(edit, delta, dirtyEndOld);
|
|
2668
|
+
const reparsedWindowSize = dirtyEndNew - dirtyStartNew;
|
|
2669
|
+
nextCumulativeReparsedBytes += reparsedWindowSize;
|
|
2670
|
+
if (nextCumulativeReparsedBytes > cumulativeBudget) {
|
|
2671
|
+
return {
|
|
2672
|
+
budgetExceeded: true,
|
|
2673
|
+
dirtyTo: nextDirtyTo,
|
|
2674
|
+
dirtyZones: nextDirtyZones,
|
|
2675
|
+
cumulativeReparsedBytes: nextCumulativeReparsedBytes
|
|
2676
|
+
};
|
|
2677
|
+
}
|
|
2678
|
+
const dirtyTree = parseWithPositions(
|
|
2679
|
+
newSource.slice(dirtyStartNew, dirtyEndNew),
|
|
2680
|
+
tracker,
|
|
2681
|
+
parseOptions,
|
|
2682
|
+
dirtyStartNew
|
|
2683
|
+
);
|
|
2684
|
+
nextDirtyZones = buildZones(dirtyTree);
|
|
2685
|
+
const reparsedEnd = nextDirtyZones.length > 0 ? nextDirtyZones[nextDirtyZones.length - 1].endOffset : dirtyStartNew;
|
|
2686
|
+
if (reparsedEnd === dirtyEndNew || nextDirtyTo === doc.zones.length - 1) {
|
|
2687
|
+
return {
|
|
2688
|
+
budgetExceeded: false,
|
|
2689
|
+
dirtyTo: nextDirtyTo,
|
|
2690
|
+
dirtyZones: nextDirtyZones,
|
|
2691
|
+
cumulativeReparsedBytes: nextCumulativeReparsedBytes
|
|
2692
|
+
};
|
|
2693
|
+
}
|
|
2694
|
+
nextDirtyTo += 1;
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2550
2697
|
var assertValidEdit = (doc, edit, newSource) => {
|
|
2551
2698
|
if (edit.startOffset < 0 || edit.oldEndOffset < edit.startOffset || edit.oldEndOffset > doc.source.length) {
|
|
2552
2699
|
throw createIncrementalEditError(
|
|
@@ -2573,16 +2720,21 @@ var parseIncremental = (source, options) => {
|
|
|
2573
2720
|
const tracker = buildPositionTracker(source);
|
|
2574
2721
|
const tree = parseWithPositions(source, tracker, options);
|
|
2575
2722
|
const zones = buildZones(tree);
|
|
2723
|
+
for (let i = 0; i < zones.length; i++) {
|
|
2724
|
+
zoneSignature(zones[i]);
|
|
2725
|
+
}
|
|
2576
2726
|
const parseOptions = cloneParseOptions(options);
|
|
2577
|
-
|
|
2727
|
+
const fingerprint = buildParseOptionsFingerprint(parseOptions);
|
|
2728
|
+
const doc = {
|
|
2578
2729
|
source,
|
|
2579
2730
|
tree,
|
|
2580
2731
|
zones,
|
|
2581
|
-
parseOptions
|
|
2582
|
-
optionsFingerprint: buildParseOptionsFingerprint(parseOptions)
|
|
2732
|
+
parseOptions
|
|
2583
2733
|
};
|
|
2734
|
+
setCachedOptionsFingerprint(doc, fingerprint);
|
|
2735
|
+
return doc;
|
|
2584
2736
|
};
|
|
2585
|
-
var
|
|
2737
|
+
var updateIncrementalInternal = (doc, edit, newSource, options, __internalObserver) => {
|
|
2586
2738
|
assertValidEdit(doc, edit, newSource);
|
|
2587
2739
|
let cumulativeReparsedBytes = 0;
|
|
2588
2740
|
let probeSliceBytes = 0;
|
|
@@ -2593,23 +2745,24 @@ var updateIncremental = (doc, edit, newSource, options, __internalObserver) => {
|
|
|
2593
2745
|
fellBackToFull
|
|
2594
2746
|
});
|
|
2595
2747
|
};
|
|
2596
|
-
const
|
|
2597
|
-
const
|
|
2598
|
-
const
|
|
2748
|
+
const previousOptionsFingerprint = getCachedOptionsFingerprint(doc) ?? buildParseOptionsFingerprint(doc.parseOptions);
|
|
2749
|
+
const nextOptionsFingerprint = options ? buildParseOptionsFingerprint(options) : previousOptionsFingerprint;
|
|
2750
|
+
const runtimeParseOptions = options ?? doc.parseOptions;
|
|
2751
|
+
const nextParseOptionsSnapshot = options ? cloneParseOptions(options) : doc.parseOptions;
|
|
2599
2752
|
if (previousOptionsFingerprint !== nextOptionsFingerprint) {
|
|
2600
|
-
const rebuilt = parseIncremental(newSource,
|
|
2753
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2601
2754
|
emitDebug(true);
|
|
2602
2755
|
__internalObserver?.("internal-full-rebuild");
|
|
2603
2756
|
return rebuilt;
|
|
2604
2757
|
}
|
|
2605
2758
|
if (doc.zones.length === 0) {
|
|
2606
|
-
const rebuilt = parseIncremental(newSource,
|
|
2759
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2607
2760
|
emitDebug(true);
|
|
2608
2761
|
__internalObserver?.("internal-full-rebuild");
|
|
2609
2762
|
return rebuilt;
|
|
2610
2763
|
}
|
|
2611
2764
|
if (hasUnsafeZoneCoverageTailGap(doc, edit)) {
|
|
2612
|
-
const rebuilt = parseIncremental(newSource,
|
|
2765
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2613
2766
|
emitDebug(true);
|
|
2614
2767
|
__internalObserver?.("internal-full-rebuild");
|
|
2615
2768
|
return rebuilt;
|
|
@@ -2618,35 +2771,30 @@ var updateIncremental = (doc, edit, newSource, options, __internalObserver) => {
|
|
|
2618
2771
|
const cumulativeBudget = Math.max(newSource.length * 2, 1024);
|
|
2619
2772
|
const delta = newSource.length - doc.source.length;
|
|
2620
2773
|
const dirty = findDirtyRange(doc.zones, edit);
|
|
2621
|
-
|
|
2774
|
+
let dirtyFrom = dirty.from;
|
|
2622
2775
|
let dirtyTo = dirty.to;
|
|
2623
2776
|
let dirtyZones = [];
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
);
|
|
2643
|
-
dirtyZones = buildZones(dirtyTree);
|
|
2644
|
-
const reparsedEnd = dirtyZones.length > 0 ? dirtyZones[dirtyZones.length - 1].endOffset : dirtyStartNew;
|
|
2645
|
-
if (reparsedEnd === dirtyEndNew || dirtyTo === doc.zones.length - 1) {
|
|
2646
|
-
break;
|
|
2647
|
-
}
|
|
2648
|
-
dirtyTo += 1;
|
|
2777
|
+
const firstReparse = reparseDirtyWindowUntilStable(
|
|
2778
|
+
doc,
|
|
2779
|
+
dirtyFrom,
|
|
2780
|
+
dirtyTo,
|
|
2781
|
+
edit,
|
|
2782
|
+
delta,
|
|
2783
|
+
newSource,
|
|
2784
|
+
newTracker,
|
|
2785
|
+
runtimeParseOptions,
|
|
2786
|
+
cumulativeBudget,
|
|
2787
|
+
cumulativeReparsedBytes
|
|
2788
|
+
);
|
|
2789
|
+
cumulativeReparsedBytes = firstReparse.cumulativeReparsedBytes;
|
|
2790
|
+
if (firstReparse.budgetExceeded) {
|
|
2791
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2792
|
+
emitDebug(true);
|
|
2793
|
+
__internalObserver?.("internal-full-rebuild");
|
|
2794
|
+
return rebuilt;
|
|
2649
2795
|
}
|
|
2796
|
+
dirtyTo = firstReparse.dirtyTo;
|
|
2797
|
+
dirtyZones = firstReparse.dirtyZones;
|
|
2650
2798
|
const leftZones = doc.zones.slice(0, dirtyFrom);
|
|
2651
2799
|
const oldRightZones = doc.zones.slice(dirtyTo + 1);
|
|
2652
2800
|
if (oldRightZones.length > 0) {
|
|
@@ -2658,34 +2806,34 @@ var updateIncremental = (doc, edit, newSource, options, __internalObserver) => {
|
|
|
2658
2806
|
seamNewOffset,
|
|
2659
2807
|
delta,
|
|
2660
2808
|
newTracker,
|
|
2661
|
-
|
|
2809
|
+
runtimeParseOptions
|
|
2662
2810
|
);
|
|
2663
2811
|
probeSliceBytes = rightReuseCheck.probeSliceBytes;
|
|
2664
2812
|
if (!rightReuseCheck.ok) {
|
|
2665
|
-
const rebuilt = parseIncremental(newSource,
|
|
2813
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2666
2814
|
emitDebug(true);
|
|
2667
2815
|
__internalObserver?.("internal-full-rebuild");
|
|
2668
2816
|
return rebuilt;
|
|
2669
2817
|
}
|
|
2670
2818
|
}
|
|
2671
|
-
const rightZones = oldRightZones.map((zone) =>
|
|
2819
|
+
const rightZones = oldRightZones.map((zone) => shiftZoneWithSignature(zone, delta, newTracker));
|
|
2672
2820
|
const zones = [...leftZones, ...dirtyZones, ...rightZones];
|
|
2673
2821
|
const updated = {
|
|
2674
2822
|
source: newSource,
|
|
2675
2823
|
zones,
|
|
2676
2824
|
tree: flattenZones(zones),
|
|
2677
|
-
parseOptions
|
|
2678
|
-
optionsFingerprint: nextOptionsFingerprint
|
|
2825
|
+
parseOptions: nextParseOptionsSnapshot
|
|
2679
2826
|
};
|
|
2827
|
+
setCachedOptionsFingerprint(updated, nextOptionsFingerprint);
|
|
2680
2828
|
emitDebug(false);
|
|
2681
2829
|
__internalObserver?.("incremental");
|
|
2682
2830
|
return updated;
|
|
2683
2831
|
};
|
|
2684
|
-
var
|
|
2832
|
+
var tryUpdateIncrementalInternal = (doc, edit, newSource, options, __internalObserver) => {
|
|
2685
2833
|
try {
|
|
2686
2834
|
return {
|
|
2687
2835
|
ok: true,
|
|
2688
|
-
value:
|
|
2836
|
+
value: updateIncrementalInternal(doc, edit, newSource, options, __internalObserver)
|
|
2689
2837
|
};
|
|
2690
2838
|
} catch (error) {
|
|
2691
2839
|
if (isIncrementalUpdateError(error)) {
|
|
@@ -2795,17 +2943,28 @@ var createIncrementalSession = (source, options, sessionOptions) => {
|
|
|
2795
2943
|
return rebuiltResult2;
|
|
2796
2944
|
}
|
|
2797
2945
|
const incrementalStart = now();
|
|
2798
|
-
let
|
|
2799
|
-
const result =
|
|
2800
|
-
|
|
2946
|
+
let mode;
|
|
2947
|
+
const result = tryUpdateIncrementalInternal(currentDoc, edit, newSource, nextOptions, (nextTelemetry) => {
|
|
2948
|
+
mode = nextTelemetry;
|
|
2801
2949
|
});
|
|
2802
2950
|
const incrementalElapsedMs = now() - incrementalStart;
|
|
2803
2951
|
recordBounded(incrementalDurations, incrementalElapsedMs);
|
|
2804
2952
|
if (result.ok) {
|
|
2805
2953
|
currentDoc = result.value;
|
|
2806
|
-
|
|
2954
|
+
const internalFullRebuild = mode === "internal-full-rebuild";
|
|
2955
|
+
recordBounded(fallbackMarks, internalFullRebuild ? 1 : 0);
|
|
2807
2956
|
maybeAdaptPolicy();
|
|
2808
|
-
|
|
2957
|
+
if (internalFullRebuild) {
|
|
2958
|
+
return {
|
|
2959
|
+
doc: currentDoc,
|
|
2960
|
+
mode: "full-fallback",
|
|
2961
|
+
fallbackReason: "INTERNAL_FULL_REBUILD"
|
|
2962
|
+
};
|
|
2963
|
+
}
|
|
2964
|
+
return {
|
|
2965
|
+
doc: currentDoc,
|
|
2966
|
+
mode: "incremental"
|
|
2967
|
+
};
|
|
2809
2968
|
}
|
|
2810
2969
|
recordBounded(fallbackMarks, 1);
|
|
2811
2970
|
const rebuiltResult = runRebuild(newSource, nextOptions, result.error.code);
|
|
@@ -2856,9 +3015,7 @@ var createIncrementalSession = (source, options, sessionOptions) => {
|
|
|
2856
3015
|
resetTokenIdSeed,
|
|
2857
3016
|
splitTokensByPipe,
|
|
2858
3017
|
stripRichText,
|
|
2859
|
-
tryUpdateIncremental,
|
|
2860
3018
|
unescapeInline,
|
|
2861
|
-
updateIncremental,
|
|
2862
3019
|
walkTokens,
|
|
2863
3020
|
withSyntax,
|
|
2864
3021
|
withTagNameConfig
|
package/dist/index.d.cts
CHANGED
|
@@ -322,26 +322,14 @@ interface IncrementalDocument {
|
|
|
322
322
|
tree: StructuralNode[];
|
|
323
323
|
/** Optional parser config carried forward across updates. */
|
|
324
324
|
parseOptions?: IncrementalParseOptions;
|
|
325
|
-
/** Internal compatibility fingerprint for parse options. */
|
|
326
|
-
optionsFingerprint?: string;
|
|
327
325
|
}
|
|
328
326
|
type IncrementalUpdateErrorCode = "INVALID_EDIT_RANGE" | "NEW_SOURCE_LENGTH_MISMATCH" | "EDIT_TEXT_MISMATCH" | "UNKNOWN";
|
|
329
|
-
interface IncrementalUpdateError extends Error {
|
|
330
|
-
code: IncrementalUpdateErrorCode;
|
|
331
|
-
}
|
|
332
|
-
type IncrementalUpdateResult = {
|
|
333
|
-
ok: true;
|
|
334
|
-
value: IncrementalDocument;
|
|
335
|
-
} | {
|
|
336
|
-
ok: false;
|
|
337
|
-
error: IncrementalUpdateError;
|
|
338
|
-
};
|
|
339
327
|
/**
|
|
340
328
|
* Result mode returned by the high-level incremental session API.
|
|
341
329
|
*/
|
|
342
330
|
type IncrementalSessionApplyMode = "incremental" | "full-fallback";
|
|
343
331
|
type IncrementalSessionStrategy = "auto" | "incremental-only" | "full-only";
|
|
344
|
-
type IncrementalSessionFallbackReason = IncrementalUpdateErrorCode | "FULL_ONLY_STRATEGY" | "AUTO_COOLDOWN" | "AUTO_LARGE_EDIT";
|
|
332
|
+
type IncrementalSessionFallbackReason = IncrementalUpdateErrorCode | "INTERNAL_FULL_REBUILD" | "FULL_ONLY_STRATEGY" | "AUTO_COOLDOWN" | "AUTO_LARGE_EDIT";
|
|
345
333
|
interface IncrementalSessionOptions {
|
|
346
334
|
strategy?: IncrementalSessionStrategy;
|
|
347
335
|
sampleWindowSize?: number;
|
|
@@ -825,35 +813,7 @@ declare const createEasyStableId: (options?: EasyStableIdOptions) => CreateId;
|
|
|
825
813
|
*/
|
|
826
814
|
declare const buildZones: (nodes: readonly StructuralNode[]) => Zone[];
|
|
827
815
|
|
|
828
|
-
type InternalUpdateMode = "incremental" | "internal-full-rebuild";
|
|
829
|
-
type InternalUpdateObserver = (mode: InternalUpdateMode) => void;
|
|
830
816
|
declare const parseIncremental: (source: string, options?: IncrementalParseOptions) => IncrementalDocument;
|
|
831
|
-
/**
|
|
832
|
-
* Update an incremental structural snapshot with one edit and a new full source.
|
|
833
|
-
*
|
|
834
|
-
* @experimental
|
|
835
|
-
* Low-level updater for controlled integration paths.
|
|
836
|
-
* For production applications, prefer `createIncrementalSession(...).applyEdit(...)`,
|
|
837
|
-
* which guarantees fallback to full rebuild on errors.
|
|
838
|
-
*
|
|
839
|
-
* Assumption:
|
|
840
|
-
* - Left boundary stabilization is conservative but fixed to one-zone lookbehind.
|
|
841
|
-
* - Right boundary is expanded until stable (or EOF).
|
|
842
|
-
*
|
|
843
|
-
* If your edit may invalidate parsing state further left than one zone, prefer a full
|
|
844
|
-
* rebuild via `parseIncremental(newSource, options)` for correctness.
|
|
845
|
-
*
|
|
846
|
-
* @internal `__internalObserver` is for session-level telemetry only.
|
|
847
|
-
*/
|
|
848
|
-
declare const updateIncremental: (doc: IncrementalDocument, edit: IncrementalEdit, newSource: string, options?: IncrementalParseOptions, __internalObserver?: InternalUpdateObserver) => IncrementalDocument;
|
|
849
|
-
/**
|
|
850
|
-
* @experimental
|
|
851
|
-
* Low-level result-style updater.
|
|
852
|
-
* For production applications, prefer `createIncrementalSession(...).applyEdit(...)`.
|
|
853
|
-
*
|
|
854
|
-
* @internal `__internalObserver` is for session-level telemetry only.
|
|
855
|
-
*/
|
|
856
|
-
declare const tryUpdateIncremental: (doc: IncrementalDocument, edit: IncrementalEdit, newSource: string, options?: IncrementalParseOptions, __internalObserver?: InternalUpdateObserver) => IncrementalUpdateResult;
|
|
857
817
|
declare const createIncrementalSession: (source: string, options?: IncrementalParseOptions, sessionOptions?: IncrementalSessionOptions) => IncrementalSession;
|
|
858
818
|
|
|
859
|
-
export { type BlockTagInput, type BlockTagLookup, type CreateId, DEFAULT_SYNTAX, DEFAULT_TAG_NAME, type DslContext, type EasyStableIdOptions, type ErrorCode, type IncrementalDocument, type IncrementalEdit, type IncrementalParseOptions, type
|
|
819
|
+
export { type BlockTagInput, type BlockTagLookup, type CreateId, DEFAULT_SYNTAX, DEFAULT_TAG_NAME, type DslContext, type EasyStableIdOptions, type ErrorCode, type IncrementalDocument, type IncrementalEdit, type IncrementalParseOptions, type IncrementalSessionOptions, type MapVisitor, type MultilineForm, type NarrowDraft, type NarrowToken, type NarrowTokenUnion, type ParseError, type ParseOptions, type Parser, type ParserBaseOptions, type PipeArgs, type PipeHandlerDefinition, type PositionTracker, type PrintOptions, type SourcePosition, type SourceSpan, type StructuralNode, type StructuralParseOptions, type SyntaxConfig, type SyntaxInput, type TagForm, type TagHandler, type TagNameConfig, type TextToken, type TokenDraft, type TokenVisitContext, type WalkVisitor, type Zone, buildPositionTracker, buildZones, createEasyStableId, createEasySyntax, createIncrementalSession, createParser, createPassthroughTags, createPipeBlockHandlers, createPipeHandlers, createPipeRawHandlers, createSimpleBlockHandlers, createSimpleInlineHandlers, createSimpleRawHandlers, createSyntax, createTagNameConfig, createTextToken, createToken, createTokenGuard, declareMultilineTags, extractText, getSyntax, mapTokens, materializeTextTokens, parseIncremental, parsePipeArgs, parsePipeTextArgs, parsePipeTextList, parseRichText, parseStructural, printStructural, readEscapedSequence, resetTokenIdSeed, splitTokensByPipe, stripRichText, unescapeInline, walkTokens, withSyntax, withTagNameConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -322,26 +322,14 @@ interface IncrementalDocument {
|
|
|
322
322
|
tree: StructuralNode[];
|
|
323
323
|
/** Optional parser config carried forward across updates. */
|
|
324
324
|
parseOptions?: IncrementalParseOptions;
|
|
325
|
-
/** Internal compatibility fingerprint for parse options. */
|
|
326
|
-
optionsFingerprint?: string;
|
|
327
325
|
}
|
|
328
326
|
type IncrementalUpdateErrorCode = "INVALID_EDIT_RANGE" | "NEW_SOURCE_LENGTH_MISMATCH" | "EDIT_TEXT_MISMATCH" | "UNKNOWN";
|
|
329
|
-
interface IncrementalUpdateError extends Error {
|
|
330
|
-
code: IncrementalUpdateErrorCode;
|
|
331
|
-
}
|
|
332
|
-
type IncrementalUpdateResult = {
|
|
333
|
-
ok: true;
|
|
334
|
-
value: IncrementalDocument;
|
|
335
|
-
} | {
|
|
336
|
-
ok: false;
|
|
337
|
-
error: IncrementalUpdateError;
|
|
338
|
-
};
|
|
339
327
|
/**
|
|
340
328
|
* Result mode returned by the high-level incremental session API.
|
|
341
329
|
*/
|
|
342
330
|
type IncrementalSessionApplyMode = "incremental" | "full-fallback";
|
|
343
331
|
type IncrementalSessionStrategy = "auto" | "incremental-only" | "full-only";
|
|
344
|
-
type IncrementalSessionFallbackReason = IncrementalUpdateErrorCode | "FULL_ONLY_STRATEGY" | "AUTO_COOLDOWN" | "AUTO_LARGE_EDIT";
|
|
332
|
+
type IncrementalSessionFallbackReason = IncrementalUpdateErrorCode | "INTERNAL_FULL_REBUILD" | "FULL_ONLY_STRATEGY" | "AUTO_COOLDOWN" | "AUTO_LARGE_EDIT";
|
|
345
333
|
interface IncrementalSessionOptions {
|
|
346
334
|
strategy?: IncrementalSessionStrategy;
|
|
347
335
|
sampleWindowSize?: number;
|
|
@@ -825,35 +813,7 @@ declare const createEasyStableId: (options?: EasyStableIdOptions) => CreateId;
|
|
|
825
813
|
*/
|
|
826
814
|
declare const buildZones: (nodes: readonly StructuralNode[]) => Zone[];
|
|
827
815
|
|
|
828
|
-
type InternalUpdateMode = "incremental" | "internal-full-rebuild";
|
|
829
|
-
type InternalUpdateObserver = (mode: InternalUpdateMode) => void;
|
|
830
816
|
declare const parseIncremental: (source: string, options?: IncrementalParseOptions) => IncrementalDocument;
|
|
831
|
-
/**
|
|
832
|
-
* Update an incremental structural snapshot with one edit and a new full source.
|
|
833
|
-
*
|
|
834
|
-
* @experimental
|
|
835
|
-
* Low-level updater for controlled integration paths.
|
|
836
|
-
* For production applications, prefer `createIncrementalSession(...).applyEdit(...)`,
|
|
837
|
-
* which guarantees fallback to full rebuild on errors.
|
|
838
|
-
*
|
|
839
|
-
* Assumption:
|
|
840
|
-
* - Left boundary stabilization is conservative but fixed to one-zone lookbehind.
|
|
841
|
-
* - Right boundary is expanded until stable (or EOF).
|
|
842
|
-
*
|
|
843
|
-
* If your edit may invalidate parsing state further left than one zone, prefer a full
|
|
844
|
-
* rebuild via `parseIncremental(newSource, options)` for correctness.
|
|
845
|
-
*
|
|
846
|
-
* @internal `__internalObserver` is for session-level telemetry only.
|
|
847
|
-
*/
|
|
848
|
-
declare const updateIncremental: (doc: IncrementalDocument, edit: IncrementalEdit, newSource: string, options?: IncrementalParseOptions, __internalObserver?: InternalUpdateObserver) => IncrementalDocument;
|
|
849
|
-
/**
|
|
850
|
-
* @experimental
|
|
851
|
-
* Low-level result-style updater.
|
|
852
|
-
* For production applications, prefer `createIncrementalSession(...).applyEdit(...)`.
|
|
853
|
-
*
|
|
854
|
-
* @internal `__internalObserver` is for session-level telemetry only.
|
|
855
|
-
*/
|
|
856
|
-
declare const tryUpdateIncremental: (doc: IncrementalDocument, edit: IncrementalEdit, newSource: string, options?: IncrementalParseOptions, __internalObserver?: InternalUpdateObserver) => IncrementalUpdateResult;
|
|
857
817
|
declare const createIncrementalSession: (source: string, options?: IncrementalParseOptions, sessionOptions?: IncrementalSessionOptions) => IncrementalSession;
|
|
858
818
|
|
|
859
|
-
export { type BlockTagInput, type BlockTagLookup, type CreateId, DEFAULT_SYNTAX, DEFAULT_TAG_NAME, type DslContext, type EasyStableIdOptions, type ErrorCode, type IncrementalDocument, type IncrementalEdit, type IncrementalParseOptions, type
|
|
819
|
+
export { type BlockTagInput, type BlockTagLookup, type CreateId, DEFAULT_SYNTAX, DEFAULT_TAG_NAME, type DslContext, type EasyStableIdOptions, type ErrorCode, type IncrementalDocument, type IncrementalEdit, type IncrementalParseOptions, type IncrementalSessionOptions, type MapVisitor, type MultilineForm, type NarrowDraft, type NarrowToken, type NarrowTokenUnion, type ParseError, type ParseOptions, type Parser, type ParserBaseOptions, type PipeArgs, type PipeHandlerDefinition, type PositionTracker, type PrintOptions, type SourcePosition, type SourceSpan, type StructuralNode, type StructuralParseOptions, type SyntaxConfig, type SyntaxInput, type TagForm, type TagHandler, type TagNameConfig, type TextToken, type TokenDraft, type TokenVisitContext, type WalkVisitor, type Zone, buildPositionTracker, buildZones, createEasyStableId, createEasySyntax, createIncrementalSession, createParser, createPassthroughTags, createPipeBlockHandlers, createPipeHandlers, createPipeRawHandlers, createSimpleBlockHandlers, createSimpleInlineHandlers, createSimpleRawHandlers, createSyntax, createTagNameConfig, createTextToken, createToken, createTokenGuard, declareMultilineTags, extractText, getSyntax, mapTokens, materializeTextTokens, parseIncremental, parsePipeArgs, parsePipeTextArgs, parsePipeTextList, parseRichText, parseStructural, printStructural, readEscapedSequence, resetTokenIdSeed, splitTokensByPipe, stripRichText, unescapeInline, walkTokens, withSyntax, withTagNameConfig };
|
package/dist/index.js
CHANGED
|
@@ -2185,10 +2185,53 @@ var isIncrementalUpdateError = (error) => {
|
|
|
2185
2185
|
const withCode = error;
|
|
2186
2186
|
return withCode.code === "INVALID_EDIT_RANGE" || withCode.code === "NEW_SOURCE_LENGTH_MISMATCH" || withCode.code === "EDIT_TEXT_MISMATCH" || withCode.code === "UNKNOWN";
|
|
2187
2187
|
};
|
|
2188
|
+
var isPlainObject = (value) => {
|
|
2189
|
+
if (!value || typeof value !== "object") return false;
|
|
2190
|
+
const prototype = Object.getPrototypeOf(value);
|
|
2191
|
+
return prototype === Object.prototype || prototype === null;
|
|
2192
|
+
};
|
|
2193
|
+
var cloneSnapshotValueInternal = (value, seen) => {
|
|
2194
|
+
if (Array.isArray(value)) {
|
|
2195
|
+
const seenArray = seen.get(value);
|
|
2196
|
+
if (seenArray) return seenArray;
|
|
2197
|
+
const next = new Array(value.length);
|
|
2198
|
+
seen.set(value, next);
|
|
2199
|
+
for (let i = 0; i < value.length; i++) {
|
|
2200
|
+
next[i] = cloneSnapshotValueInternal(value[i], seen);
|
|
2201
|
+
}
|
|
2202
|
+
return next;
|
|
2203
|
+
}
|
|
2204
|
+
if (isPlainObject(value)) {
|
|
2205
|
+
const seenObject = seen.get(value);
|
|
2206
|
+
if (seenObject) return seenObject;
|
|
2207
|
+
const next = {};
|
|
2208
|
+
seen.set(value, next);
|
|
2209
|
+
const keys = Object.keys(value);
|
|
2210
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2211
|
+
const key = keys[i];
|
|
2212
|
+
next[key] = cloneSnapshotValueInternal(value[key], seen);
|
|
2213
|
+
}
|
|
2214
|
+
return next;
|
|
2215
|
+
}
|
|
2216
|
+
return value;
|
|
2217
|
+
};
|
|
2218
|
+
var cloneSnapshotValue = (value) => cloneSnapshotValueInternal(value, /* @__PURE__ */ new WeakMap());
|
|
2219
|
+
var cloneHandlersSnapshot = (handlers) => {
|
|
2220
|
+
if (!handlers) return void 0;
|
|
2221
|
+
const next = {};
|
|
2222
|
+
const keys = Object.keys(handlers);
|
|
2223
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2224
|
+
const key = keys[i];
|
|
2225
|
+
const handler = handlers[key];
|
|
2226
|
+
next[key] = handler ? cloneSnapshotValue(handler) : handler;
|
|
2227
|
+
}
|
|
2228
|
+
return next;
|
|
2229
|
+
};
|
|
2188
2230
|
var cloneParseOptions = (options) => {
|
|
2189
2231
|
if (!options) return void 0;
|
|
2190
2232
|
return {
|
|
2191
2233
|
...options,
|
|
2234
|
+
handlers: cloneHandlersSnapshot(options.handlers),
|
|
2192
2235
|
syntax: options.syntax ? { ...options.syntax } : void 0,
|
|
2193
2236
|
tagName: options.tagName ? { ...options.tagName } : void 0,
|
|
2194
2237
|
allowForms: options.allowForms ? [...options.allowForms] : void 0
|
|
@@ -2205,28 +2248,53 @@ var getObjectIdentity = (value) => {
|
|
|
2205
2248
|
objectIdentityMap.set(value, next);
|
|
2206
2249
|
return next;
|
|
2207
2250
|
};
|
|
2251
|
+
var getIdentityForUnknown = (value) => {
|
|
2252
|
+
if (typeof value === "object" && value !== null || typeof value === "function") {
|
|
2253
|
+
return getObjectIdentity(value);
|
|
2254
|
+
}
|
|
2255
|
+
return 0;
|
|
2256
|
+
};
|
|
2257
|
+
var buildHandlersShapeFingerprint = (handlers) => {
|
|
2258
|
+
if (!handlers || typeof handlers !== "object") return 0;
|
|
2259
|
+
const record = handlers;
|
|
2260
|
+
const keys = Object.keys(record).sort();
|
|
2261
|
+
let hash = fnvInit();
|
|
2262
|
+
hash = fnvFeedU32(hash, keys.length);
|
|
2263
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2264
|
+
const key = keys[i];
|
|
2265
|
+
const handler = record[key];
|
|
2266
|
+
hash = fnvFeedU32(hash, hashText(key));
|
|
2267
|
+
if (!handler || typeof handler !== "object") continue;
|
|
2268
|
+
const handlerRecord = handler;
|
|
2269
|
+
hash = fnvFeedU32(hash, getIdentityForUnknown(handlerRecord.inline));
|
|
2270
|
+
hash = fnvFeedU32(hash, getIdentityForUnknown(handlerRecord.raw));
|
|
2271
|
+
hash = fnvFeedU32(hash, getIdentityForUnknown(handlerRecord.block));
|
|
2272
|
+
}
|
|
2273
|
+
return hash >>> 0;
|
|
2274
|
+
};
|
|
2275
|
+
var DEFAULT_PARSE_OPTIONS_FINGERPRINT = fnvFeedU32(fnvInit(), 2654435769);
|
|
2208
2276
|
var buildParseOptionsFingerprint = (options) => {
|
|
2209
|
-
if (!options) return
|
|
2277
|
+
if (!options) return DEFAULT_PARSE_OPTIONS_FINGERPRINT;
|
|
2210
2278
|
const syntax = options.syntax ?? {};
|
|
2211
2279
|
const tagName = options.tagName ?? {};
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2280
|
+
const allowForms = options.allowForms ?? [];
|
|
2281
|
+
let hash = fnvInit();
|
|
2282
|
+
hash = fnvFeedU32(hash, buildHandlersShapeFingerprint(options.handlers));
|
|
2283
|
+
hash = fnvFeedU32(hash, allowForms.length);
|
|
2284
|
+
for (let i = 0; i < allowForms.length; i++) {
|
|
2285
|
+
hash = fnvFeedU32(hash, hashText(allowForms[i]));
|
|
2286
|
+
}
|
|
2287
|
+
hash = fnvFeedU32(hash, hashText(syntax.tagOpen ?? ""));
|
|
2288
|
+
hash = fnvFeedU32(hash, hashText(syntax.tagClose ?? ""));
|
|
2289
|
+
hash = fnvFeedU32(hash, hashText(syntax.endTag ?? ""));
|
|
2290
|
+
hash = fnvFeedU32(hash, hashText(syntax.tagDivider ?? ""));
|
|
2291
|
+
hash = fnvFeedU32(hash, hashText(syntax.rawOpen ?? ""));
|
|
2292
|
+
hash = fnvFeedU32(hash, hashText(syntax.rawClose ?? ""));
|
|
2293
|
+
hash = fnvFeedU32(hash, hashText(syntax.blockOpen ?? ""));
|
|
2294
|
+
hash = fnvFeedU32(hash, hashText(syntax.blockClose ?? ""));
|
|
2295
|
+
hash = fnvFeedU32(hash, getObjectIdentity(tagName.isTagStartChar));
|
|
2296
|
+
hash = fnvFeedU32(hash, getObjectIdentity(tagName.isTagChar));
|
|
2297
|
+
return hash >>> 0;
|
|
2230
2298
|
};
|
|
2231
2299
|
var hasUnsafeZoneCoverageTailGap = (doc, edit) => {
|
|
2232
2300
|
const lastZone = doc.zones[doc.zones.length - 1];
|
|
@@ -2251,8 +2319,10 @@ var flattenZones = (zones) => {
|
|
|
2251
2319
|
}
|
|
2252
2320
|
return tree;
|
|
2253
2321
|
};
|
|
2322
|
+
var LEFT_LOOKBEHIND_ZONES = 1;
|
|
2254
2323
|
var RIGHT_REUSE_PROBE_ZONES = 2;
|
|
2255
2324
|
var RIGHT_REUSE_PROBE_EXTRA_ZONES = 1;
|
|
2325
|
+
var RIGHT_REUSE_PROBE_SIGNATURE_NODE_BUDGET = 4096;
|
|
2256
2326
|
var NODE_TAG_TEXT = 1;
|
|
2257
2327
|
var NODE_TAG_ESCAPE = 2;
|
|
2258
2328
|
var NODE_TAG_SEPARATOR = 3;
|
|
@@ -2261,9 +2331,20 @@ var NODE_TAG_RAW = 5;
|
|
|
2261
2331
|
var NODE_TAG_BLOCK = 6;
|
|
2262
2332
|
var ZONE_TAG = 7;
|
|
2263
2333
|
var zoneSignatureCache = /* @__PURE__ */ new WeakMap();
|
|
2334
|
+
var parseOptionsFingerprintCache = /* @__PURE__ */ new WeakMap();
|
|
2264
2335
|
var incrementalDebugSink;
|
|
2265
2336
|
var hashText = (value) => fnv1a(value);
|
|
2266
|
-
var
|
|
2337
|
+
var getCachedOptionsFingerprint = (doc) => parseOptionsFingerprintCache.get(doc);
|
|
2338
|
+
var setCachedOptionsFingerprint = (doc, fingerprint) => {
|
|
2339
|
+
parseOptionsFingerprintCache.set(doc, fingerprint);
|
|
2340
|
+
};
|
|
2341
|
+
var tryConsumeSignatureBudget = (budget) => {
|
|
2342
|
+
if (budget.remaining <= 0) return false;
|
|
2343
|
+
budget.remaining -= 1;
|
|
2344
|
+
return true;
|
|
2345
|
+
};
|
|
2346
|
+
var nodeSignature = (node, budget) => {
|
|
2347
|
+
if (budget && !tryConsumeSignatureBudget(budget)) return void 0;
|
|
2267
2348
|
if (node.type === "text") {
|
|
2268
2349
|
let hash = fnvInit();
|
|
2269
2350
|
hash = fnvFeedU32(hash, NODE_TAG_TEXT);
|
|
@@ -2286,7 +2367,9 @@ var nodeSignature = (node) => {
|
|
|
2286
2367
|
hash = fnvFeedU32(hash, NODE_TAG_INLINE);
|
|
2287
2368
|
hash = fnvFeedU32(hash, hashText(node.tag));
|
|
2288
2369
|
for (let i = 0; i < node.children.length; i++) {
|
|
2289
|
-
|
|
2370
|
+
const childHash = nodeSignature(node.children[i], budget);
|
|
2371
|
+
if (childHash === void 0) return void 0;
|
|
2372
|
+
hash = fnvFeedU32(hash, childHash);
|
|
2290
2373
|
}
|
|
2291
2374
|
return hash >>> 0;
|
|
2292
2375
|
}
|
|
@@ -2297,7 +2380,9 @@ var nodeSignature = (node) => {
|
|
|
2297
2380
|
hash = fnvFeedU32(hash, node.content.length);
|
|
2298
2381
|
hash = fnvFeedU32(hash, hashText(node.content));
|
|
2299
2382
|
for (let i = 0; i < node.args.length; i++) {
|
|
2300
|
-
|
|
2383
|
+
const argHash = nodeSignature(node.args[i], budget);
|
|
2384
|
+
if (argHash === void 0) return void 0;
|
|
2385
|
+
hash = fnvFeedU32(hash, argHash);
|
|
2301
2386
|
}
|
|
2302
2387
|
return hash >>> 0;
|
|
2303
2388
|
}
|
|
@@ -2306,26 +2391,36 @@ var nodeSignature = (node) => {
|
|
|
2306
2391
|
hash = fnvFeedU32(hash, NODE_TAG_BLOCK);
|
|
2307
2392
|
hash = fnvFeedU32(hash, hashText(node.tag));
|
|
2308
2393
|
for (let i = 0; i < node.args.length; i++) {
|
|
2309
|
-
|
|
2394
|
+
const argHash = nodeSignature(node.args[i], budget);
|
|
2395
|
+
if (argHash === void 0) return void 0;
|
|
2396
|
+
hash = fnvFeedU32(hash, argHash);
|
|
2310
2397
|
}
|
|
2311
2398
|
for (let i = 0; i < node.children.length; i++) {
|
|
2312
|
-
|
|
2399
|
+
const childHash = nodeSignature(node.children[i], budget);
|
|
2400
|
+
if (childHash === void 0) return void 0;
|
|
2401
|
+
hash = fnvFeedU32(hash, childHash);
|
|
2313
2402
|
}
|
|
2314
2403
|
return hash >>> 0;
|
|
2315
2404
|
}
|
|
2316
2405
|
return assertUnreachable(node);
|
|
2317
2406
|
};
|
|
2318
|
-
var zoneSignature = (zone) => {
|
|
2319
|
-
|
|
2320
|
-
|
|
2407
|
+
var zoneSignature = (zone, budget) => {
|
|
2408
|
+
if (!budget) {
|
|
2409
|
+
const cached = zoneSignatureCache.get(zone);
|
|
2410
|
+
if (cached !== void 0) return cached;
|
|
2411
|
+
}
|
|
2321
2412
|
let hash = fnvInit();
|
|
2322
2413
|
hash = fnvFeedU32(hash, ZONE_TAG);
|
|
2323
2414
|
hash = fnvFeedU32(hash, zone.endOffset - zone.startOffset);
|
|
2324
2415
|
for (let i = 0; i < zone.nodes.length; i++) {
|
|
2325
|
-
|
|
2416
|
+
const signature = nodeSignature(zone.nodes[i], budget);
|
|
2417
|
+
if (signature === void 0) return void 0;
|
|
2418
|
+
hash = fnvFeedU32(hash, signature);
|
|
2326
2419
|
}
|
|
2327
2420
|
const finalized = hash >>> 0;
|
|
2328
|
-
|
|
2421
|
+
if (!budget) {
|
|
2422
|
+
zoneSignatureCache.set(zone, finalized);
|
|
2423
|
+
}
|
|
2329
2424
|
return finalized;
|
|
2330
2425
|
};
|
|
2331
2426
|
var isSafeRightReuse = (oldRightZones, newSource, seamNewOffset, delta, tracker, parseOptions) => {
|
|
@@ -2347,13 +2442,21 @@ var isSafeRightReuse = (oldRightZones, newSource, seamNewOffset, delta, tracker,
|
|
|
2347
2442
|
);
|
|
2348
2443
|
const probeZones = buildZones(probeTree);
|
|
2349
2444
|
if (probeZones.length < probeZoneCount) return { ok: false, probeSliceBytes: probeLength };
|
|
2445
|
+
const signatureBudget = {
|
|
2446
|
+
remaining: RIGHT_REUSE_PROBE_SIGNATURE_NODE_BUDGET
|
|
2447
|
+
};
|
|
2350
2448
|
for (let i = 0; i < probeZoneCount; i++) {
|
|
2351
2449
|
const expected = oldRightZones[i];
|
|
2352
2450
|
const actual = probeZones[i];
|
|
2353
2451
|
if (actual.startOffset !== expected.startOffset + delta) return { ok: false, probeSliceBytes: probeLength };
|
|
2354
2452
|
if (actual.endOffset !== expected.endOffset + delta) return { ok: false, probeSliceBytes: probeLength };
|
|
2355
2453
|
if (actual.nodes.length !== expected.nodes.length) return { ok: false, probeSliceBytes: probeLength };
|
|
2356
|
-
|
|
2454
|
+
const actualSignature = zoneSignature(actual, signatureBudget);
|
|
2455
|
+
if (actualSignature === void 0) return { ok: false, probeSliceBytes: probeLength };
|
|
2456
|
+
const expectedSignature = zoneSignature(expected);
|
|
2457
|
+
if (expectedSignature === void 0 || actualSignature !== expectedSignature) {
|
|
2458
|
+
return { ok: false, probeSliceBytes: probeLength };
|
|
2459
|
+
}
|
|
2357
2460
|
}
|
|
2358
2461
|
return { ok: true, probeSliceBytes: probeLength };
|
|
2359
2462
|
};
|
|
@@ -2452,6 +2555,14 @@ var shiftZone = (zone, delta, tracker) => ({
|
|
|
2452
2555
|
endOffset: zone.endOffset + delta,
|
|
2453
2556
|
nodes: zone.nodes.map((node) => shiftNode(node, delta, tracker))
|
|
2454
2557
|
});
|
|
2558
|
+
var shiftZoneWithSignature = (zone, delta, tracker) => {
|
|
2559
|
+
const shifted = shiftZone(zone, delta, tracker);
|
|
2560
|
+
const signature = zoneSignature(zone);
|
|
2561
|
+
if (signature !== void 0) {
|
|
2562
|
+
zoneSignatureCache.set(shifted, signature);
|
|
2563
|
+
}
|
|
2564
|
+
return shifted;
|
|
2565
|
+
};
|
|
2455
2566
|
var findDirtyRange = (zones, edit) => {
|
|
2456
2567
|
let firstOverlap = -1;
|
|
2457
2568
|
let lastOverlap = -1;
|
|
@@ -2464,7 +2575,7 @@ var findDirtyRange = (zones, edit) => {
|
|
|
2464
2575
|
}
|
|
2465
2576
|
if (firstOverlap !== -1) {
|
|
2466
2577
|
return {
|
|
2467
|
-
from: Math.max(0, firstOverlap -
|
|
2578
|
+
from: Math.max(0, firstOverlap - LEFT_LOOKBEHIND_ZONES),
|
|
2468
2579
|
to: Math.min(zones.length - 1, lastOverlap + 1)
|
|
2469
2580
|
};
|
|
2470
2581
|
}
|
|
@@ -2476,10 +2587,48 @@ var findDirtyRange = (zones, edit) => {
|
|
|
2476
2587
|
}
|
|
2477
2588
|
}
|
|
2478
2589
|
return {
|
|
2479
|
-
from: Math.max(0, insertionIndex -
|
|
2590
|
+
from: Math.max(0, insertionIndex - LEFT_LOOKBEHIND_ZONES),
|
|
2480
2591
|
to: Math.min(zones.length - 1, insertionIndex)
|
|
2481
2592
|
};
|
|
2482
2593
|
};
|
|
2594
|
+
var reparseDirtyWindowUntilStable = (doc, dirtyFrom, dirtyTo, edit, delta, newSource, tracker, parseOptions, cumulativeBudget, cumulativeReparsedBytes) => {
|
|
2595
|
+
let nextDirtyTo = dirtyTo;
|
|
2596
|
+
let nextDirtyZones = [];
|
|
2597
|
+
let nextCumulativeReparsedBytes = cumulativeReparsedBytes;
|
|
2598
|
+
while (true) {
|
|
2599
|
+
const dirtyStartOld = doc.zones[dirtyFrom].startOffset;
|
|
2600
|
+
const dirtyEndOld = doc.zones[nextDirtyTo].endOffset;
|
|
2601
|
+
const dirtyStartNew = mapOldOffsetToNew(edit, delta, dirtyStartOld);
|
|
2602
|
+
const dirtyEndNew = mapOldOffsetToNew(edit, delta, dirtyEndOld);
|
|
2603
|
+
const reparsedWindowSize = dirtyEndNew - dirtyStartNew;
|
|
2604
|
+
nextCumulativeReparsedBytes += reparsedWindowSize;
|
|
2605
|
+
if (nextCumulativeReparsedBytes > cumulativeBudget) {
|
|
2606
|
+
return {
|
|
2607
|
+
budgetExceeded: true,
|
|
2608
|
+
dirtyTo: nextDirtyTo,
|
|
2609
|
+
dirtyZones: nextDirtyZones,
|
|
2610
|
+
cumulativeReparsedBytes: nextCumulativeReparsedBytes
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2613
|
+
const dirtyTree = parseWithPositions(
|
|
2614
|
+
newSource.slice(dirtyStartNew, dirtyEndNew),
|
|
2615
|
+
tracker,
|
|
2616
|
+
parseOptions,
|
|
2617
|
+
dirtyStartNew
|
|
2618
|
+
);
|
|
2619
|
+
nextDirtyZones = buildZones(dirtyTree);
|
|
2620
|
+
const reparsedEnd = nextDirtyZones.length > 0 ? nextDirtyZones[nextDirtyZones.length - 1].endOffset : dirtyStartNew;
|
|
2621
|
+
if (reparsedEnd === dirtyEndNew || nextDirtyTo === doc.zones.length - 1) {
|
|
2622
|
+
return {
|
|
2623
|
+
budgetExceeded: false,
|
|
2624
|
+
dirtyTo: nextDirtyTo,
|
|
2625
|
+
dirtyZones: nextDirtyZones,
|
|
2626
|
+
cumulativeReparsedBytes: nextCumulativeReparsedBytes
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
nextDirtyTo += 1;
|
|
2630
|
+
}
|
|
2631
|
+
};
|
|
2483
2632
|
var assertValidEdit = (doc, edit, newSource) => {
|
|
2484
2633
|
if (edit.startOffset < 0 || edit.oldEndOffset < edit.startOffset || edit.oldEndOffset > doc.source.length) {
|
|
2485
2634
|
throw createIncrementalEditError(
|
|
@@ -2506,16 +2655,21 @@ var parseIncremental = (source, options) => {
|
|
|
2506
2655
|
const tracker = buildPositionTracker(source);
|
|
2507
2656
|
const tree = parseWithPositions(source, tracker, options);
|
|
2508
2657
|
const zones = buildZones(tree);
|
|
2658
|
+
for (let i = 0; i < zones.length; i++) {
|
|
2659
|
+
zoneSignature(zones[i]);
|
|
2660
|
+
}
|
|
2509
2661
|
const parseOptions = cloneParseOptions(options);
|
|
2510
|
-
|
|
2662
|
+
const fingerprint = buildParseOptionsFingerprint(parseOptions);
|
|
2663
|
+
const doc = {
|
|
2511
2664
|
source,
|
|
2512
2665
|
tree,
|
|
2513
2666
|
zones,
|
|
2514
|
-
parseOptions
|
|
2515
|
-
optionsFingerprint: buildParseOptionsFingerprint(parseOptions)
|
|
2667
|
+
parseOptions
|
|
2516
2668
|
};
|
|
2669
|
+
setCachedOptionsFingerprint(doc, fingerprint);
|
|
2670
|
+
return doc;
|
|
2517
2671
|
};
|
|
2518
|
-
var
|
|
2672
|
+
var updateIncrementalInternal = (doc, edit, newSource, options, __internalObserver) => {
|
|
2519
2673
|
assertValidEdit(doc, edit, newSource);
|
|
2520
2674
|
let cumulativeReparsedBytes = 0;
|
|
2521
2675
|
let probeSliceBytes = 0;
|
|
@@ -2526,23 +2680,24 @@ var updateIncremental = (doc, edit, newSource, options, __internalObserver) => {
|
|
|
2526
2680
|
fellBackToFull
|
|
2527
2681
|
});
|
|
2528
2682
|
};
|
|
2529
|
-
const
|
|
2530
|
-
const
|
|
2531
|
-
const
|
|
2683
|
+
const previousOptionsFingerprint = getCachedOptionsFingerprint(doc) ?? buildParseOptionsFingerprint(doc.parseOptions);
|
|
2684
|
+
const nextOptionsFingerprint = options ? buildParseOptionsFingerprint(options) : previousOptionsFingerprint;
|
|
2685
|
+
const runtimeParseOptions = options ?? doc.parseOptions;
|
|
2686
|
+
const nextParseOptionsSnapshot = options ? cloneParseOptions(options) : doc.parseOptions;
|
|
2532
2687
|
if (previousOptionsFingerprint !== nextOptionsFingerprint) {
|
|
2533
|
-
const rebuilt = parseIncremental(newSource,
|
|
2688
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2534
2689
|
emitDebug(true);
|
|
2535
2690
|
__internalObserver?.("internal-full-rebuild");
|
|
2536
2691
|
return rebuilt;
|
|
2537
2692
|
}
|
|
2538
2693
|
if (doc.zones.length === 0) {
|
|
2539
|
-
const rebuilt = parseIncremental(newSource,
|
|
2694
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2540
2695
|
emitDebug(true);
|
|
2541
2696
|
__internalObserver?.("internal-full-rebuild");
|
|
2542
2697
|
return rebuilt;
|
|
2543
2698
|
}
|
|
2544
2699
|
if (hasUnsafeZoneCoverageTailGap(doc, edit)) {
|
|
2545
|
-
const rebuilt = parseIncremental(newSource,
|
|
2700
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2546
2701
|
emitDebug(true);
|
|
2547
2702
|
__internalObserver?.("internal-full-rebuild");
|
|
2548
2703
|
return rebuilt;
|
|
@@ -2551,35 +2706,30 @@ var updateIncremental = (doc, edit, newSource, options, __internalObserver) => {
|
|
|
2551
2706
|
const cumulativeBudget = Math.max(newSource.length * 2, 1024);
|
|
2552
2707
|
const delta = newSource.length - doc.source.length;
|
|
2553
2708
|
const dirty = findDirtyRange(doc.zones, edit);
|
|
2554
|
-
|
|
2709
|
+
let dirtyFrom = dirty.from;
|
|
2555
2710
|
let dirtyTo = dirty.to;
|
|
2556
2711
|
let dirtyZones = [];
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
);
|
|
2576
|
-
dirtyZones = buildZones(dirtyTree);
|
|
2577
|
-
const reparsedEnd = dirtyZones.length > 0 ? dirtyZones[dirtyZones.length - 1].endOffset : dirtyStartNew;
|
|
2578
|
-
if (reparsedEnd === dirtyEndNew || dirtyTo === doc.zones.length - 1) {
|
|
2579
|
-
break;
|
|
2580
|
-
}
|
|
2581
|
-
dirtyTo += 1;
|
|
2712
|
+
const firstReparse = reparseDirtyWindowUntilStable(
|
|
2713
|
+
doc,
|
|
2714
|
+
dirtyFrom,
|
|
2715
|
+
dirtyTo,
|
|
2716
|
+
edit,
|
|
2717
|
+
delta,
|
|
2718
|
+
newSource,
|
|
2719
|
+
newTracker,
|
|
2720
|
+
runtimeParseOptions,
|
|
2721
|
+
cumulativeBudget,
|
|
2722
|
+
cumulativeReparsedBytes
|
|
2723
|
+
);
|
|
2724
|
+
cumulativeReparsedBytes = firstReparse.cumulativeReparsedBytes;
|
|
2725
|
+
if (firstReparse.budgetExceeded) {
|
|
2726
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2727
|
+
emitDebug(true);
|
|
2728
|
+
__internalObserver?.("internal-full-rebuild");
|
|
2729
|
+
return rebuilt;
|
|
2582
2730
|
}
|
|
2731
|
+
dirtyTo = firstReparse.dirtyTo;
|
|
2732
|
+
dirtyZones = firstReparse.dirtyZones;
|
|
2583
2733
|
const leftZones = doc.zones.slice(0, dirtyFrom);
|
|
2584
2734
|
const oldRightZones = doc.zones.slice(dirtyTo + 1);
|
|
2585
2735
|
if (oldRightZones.length > 0) {
|
|
@@ -2591,34 +2741,34 @@ var updateIncremental = (doc, edit, newSource, options, __internalObserver) => {
|
|
|
2591
2741
|
seamNewOffset,
|
|
2592
2742
|
delta,
|
|
2593
2743
|
newTracker,
|
|
2594
|
-
|
|
2744
|
+
runtimeParseOptions
|
|
2595
2745
|
);
|
|
2596
2746
|
probeSliceBytes = rightReuseCheck.probeSliceBytes;
|
|
2597
2747
|
if (!rightReuseCheck.ok) {
|
|
2598
|
-
const rebuilt = parseIncremental(newSource,
|
|
2748
|
+
const rebuilt = parseIncremental(newSource, runtimeParseOptions);
|
|
2599
2749
|
emitDebug(true);
|
|
2600
2750
|
__internalObserver?.("internal-full-rebuild");
|
|
2601
2751
|
return rebuilt;
|
|
2602
2752
|
}
|
|
2603
2753
|
}
|
|
2604
|
-
const rightZones = oldRightZones.map((zone) =>
|
|
2754
|
+
const rightZones = oldRightZones.map((zone) => shiftZoneWithSignature(zone, delta, newTracker));
|
|
2605
2755
|
const zones = [...leftZones, ...dirtyZones, ...rightZones];
|
|
2606
2756
|
const updated = {
|
|
2607
2757
|
source: newSource,
|
|
2608
2758
|
zones,
|
|
2609
2759
|
tree: flattenZones(zones),
|
|
2610
|
-
parseOptions
|
|
2611
|
-
optionsFingerprint: nextOptionsFingerprint
|
|
2760
|
+
parseOptions: nextParseOptionsSnapshot
|
|
2612
2761
|
};
|
|
2762
|
+
setCachedOptionsFingerprint(updated, nextOptionsFingerprint);
|
|
2613
2763
|
emitDebug(false);
|
|
2614
2764
|
__internalObserver?.("incremental");
|
|
2615
2765
|
return updated;
|
|
2616
2766
|
};
|
|
2617
|
-
var
|
|
2767
|
+
var tryUpdateIncrementalInternal = (doc, edit, newSource, options, __internalObserver) => {
|
|
2618
2768
|
try {
|
|
2619
2769
|
return {
|
|
2620
2770
|
ok: true,
|
|
2621
|
-
value:
|
|
2771
|
+
value: updateIncrementalInternal(doc, edit, newSource, options, __internalObserver)
|
|
2622
2772
|
};
|
|
2623
2773
|
} catch (error) {
|
|
2624
2774
|
if (isIncrementalUpdateError(error)) {
|
|
@@ -2728,17 +2878,28 @@ var createIncrementalSession = (source, options, sessionOptions) => {
|
|
|
2728
2878
|
return rebuiltResult2;
|
|
2729
2879
|
}
|
|
2730
2880
|
const incrementalStart = now();
|
|
2731
|
-
let
|
|
2732
|
-
const result =
|
|
2733
|
-
|
|
2881
|
+
let mode;
|
|
2882
|
+
const result = tryUpdateIncrementalInternal(currentDoc, edit, newSource, nextOptions, (nextTelemetry) => {
|
|
2883
|
+
mode = nextTelemetry;
|
|
2734
2884
|
});
|
|
2735
2885
|
const incrementalElapsedMs = now() - incrementalStart;
|
|
2736
2886
|
recordBounded(incrementalDurations, incrementalElapsedMs);
|
|
2737
2887
|
if (result.ok) {
|
|
2738
2888
|
currentDoc = result.value;
|
|
2739
|
-
|
|
2889
|
+
const internalFullRebuild = mode === "internal-full-rebuild";
|
|
2890
|
+
recordBounded(fallbackMarks, internalFullRebuild ? 1 : 0);
|
|
2740
2891
|
maybeAdaptPolicy();
|
|
2741
|
-
|
|
2892
|
+
if (internalFullRebuild) {
|
|
2893
|
+
return {
|
|
2894
|
+
doc: currentDoc,
|
|
2895
|
+
mode: "full-fallback",
|
|
2896
|
+
fallbackReason: "INTERNAL_FULL_REBUILD"
|
|
2897
|
+
};
|
|
2898
|
+
}
|
|
2899
|
+
return {
|
|
2900
|
+
doc: currentDoc,
|
|
2901
|
+
mode: "incremental"
|
|
2902
|
+
};
|
|
2742
2903
|
}
|
|
2743
2904
|
recordBounded(fallbackMarks, 1);
|
|
2744
2905
|
const rebuiltResult = runRebuild(newSource, nextOptions, result.error.code);
|
|
@@ -2788,9 +2949,7 @@ export {
|
|
|
2788
2949
|
resetTokenIdSeed,
|
|
2789
2950
|
splitTokensByPipe,
|
|
2790
2951
|
stripRichText,
|
|
2791
|
-
tryUpdateIncremental,
|
|
2792
2952
|
unescapeInline,
|
|
2793
|
-
updateIncremental,
|
|
2794
2953
|
walkTokens,
|
|
2795
2954
|
withSyntax,
|
|
2796
2955
|
withTagNameConfig
|
package/package.json
CHANGED