You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			2191 lines
		
	
	
		
			80 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			2191 lines
		
	
	
		
			80 KiB
		
	
	
	
		
			JavaScript
		
	
| "use strict";
 | |
| (self["webpackChunk_JUPYTERLAB_CORE_OUTPUT"] = self["webpackChunk_JUPYTERLAB_CORE_OUTPUT"] || []).push([[7997],{
 | |
| 
 | |
| /***/ 97997:
 | |
| /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
 | |
| 
 | |
| __webpack_require__.r(__webpack_exports__);
 | |
| /* harmony export */ __webpack_require__.d(__webpack_exports__, {
 | |
| /* harmony export */   DefaultBufferLength: () => (/* binding */ DefaultBufferLength),
 | |
| /* harmony export */   IterMode: () => (/* binding */ IterMode),
 | |
| /* harmony export */   MountedTree: () => (/* binding */ MountedTree),
 | |
| /* harmony export */   NodeProp: () => (/* binding */ NodeProp),
 | |
| /* harmony export */   NodeSet: () => (/* binding */ NodeSet),
 | |
| /* harmony export */   NodeType: () => (/* binding */ NodeType),
 | |
| /* harmony export */   NodeWeakMap: () => (/* binding */ NodeWeakMap),
 | |
| /* harmony export */   Parser: () => (/* binding */ Parser),
 | |
| /* harmony export */   Tree: () => (/* binding */ Tree),
 | |
| /* harmony export */   TreeBuffer: () => (/* binding */ TreeBuffer),
 | |
| /* harmony export */   TreeCursor: () => (/* binding */ TreeCursor),
 | |
| /* harmony export */   TreeFragment: () => (/* binding */ TreeFragment),
 | |
| /* harmony export */   parseMixed: () => (/* binding */ parseMixed)
 | |
| /* harmony export */ });
 | |
| /**
 | |
| The default maximum length of a `TreeBuffer` node.
 | |
| */
 | |
| const DefaultBufferLength = 1024;
 | |
| let nextPropID = 0;
 | |
| class Range {
 | |
|     constructor(from, to) {
 | |
|         this.from = from;
 | |
|         this.to = to;
 | |
|     }
 | |
| }
 | |
| /**
 | |
| Each [node type](#common.NodeType) or [individual tree](#common.Tree)
 | |
| can have metadata associated with it in props. Instances of this
 | |
| class represent prop names.
 | |
| */
 | |
| class NodeProp {
 | |
|     /**
 | |
|     Create a new node prop type.
 | |
|     */
 | |
|     constructor(config = {}) {
 | |
|         this.id = nextPropID++;
 | |
|         this.perNode = !!config.perNode;
 | |
|         this.deserialize = config.deserialize || (() => {
 | |
|             throw new Error("This node type doesn't define a deserialize function");
 | |
|         });
 | |
|     }
 | |
|     /**
 | |
|     This is meant to be used with
 | |
|     [`NodeSet.extend`](#common.NodeSet.extend) or
 | |
|     [`LRParser.configure`](#lr.ParserConfig.props) to compute
 | |
|     prop values for each node type in the set. Takes a [match
 | |
|     object](#common.NodeType^match) or function that returns undefined
 | |
|     if the node type doesn't get this prop, and the prop's value if
 | |
|     it does.
 | |
|     */
 | |
|     add(match) {
 | |
|         if (this.perNode)
 | |
|             throw new RangeError("Can't add per-node props to node types");
 | |
|         if (typeof match != "function")
 | |
|             match = NodeType.match(match);
 | |
|         return (type) => {
 | |
|             let result = match(type);
 | |
|             return result === undefined ? null : [this, result];
 | |
|         };
 | |
|     }
 | |
| }
 | |
| /**
 | |
| Prop that is used to describe matching delimiters. For opening
 | |
| delimiters, this holds an array of node names (written as a
 | |
| space-separated string when declaring this prop in a grammar)
 | |
| for the node types of closing delimiters that match it.
 | |
| */
 | |
| NodeProp.closedBy = new NodeProp({ deserialize: str => str.split(" ") });
 | |
| /**
 | |
| The inverse of [`closedBy`](#common.NodeProp^closedBy). This is
 | |
| attached to closing delimiters, holding an array of node names
 | |
| of types of matching opening delimiters.
 | |
| */
 | |
| NodeProp.openedBy = new NodeProp({ deserialize: str => str.split(" ") });
 | |
| /**
 | |
| Used to assign node types to groups (for example, all node
 | |
| types that represent an expression could be tagged with an
 | |
| `"Expression"` group).
 | |
| */
 | |
| NodeProp.group = new NodeProp({ deserialize: str => str.split(" ") });
 | |
| /**
 | |
| Attached to nodes to indicate these should be
 | |
| [displayed](https://codemirror.net/docs/ref/#language.syntaxTree)
 | |
| in a bidirectional text isolate, so that direction-neutral
 | |
| characters on their sides don't incorrectly get associated with
 | |
| surrounding text. You'll generally want to set this for nodes
 | |
| that contain arbitrary text, like strings and comments, and for
 | |
| nodes that appear _inside_ arbitrary text, like HTML tags. When
 | |
| not given a value, in a grammar declaration, defaults to
 | |
| `"auto"`.
 | |
| */
 | |
| NodeProp.isolate = new NodeProp({ deserialize: value => {
 | |
|         if (value && value != "rtl" && value != "ltr" && value != "auto")
 | |
|             throw new RangeError("Invalid value for isolate: " + value);
 | |
|         return value || "auto";
 | |
|     } });
 | |
| /**
 | |
| The hash of the [context](#lr.ContextTracker.constructor)
 | |
| that the node was parsed in, if any. Used to limit reuse of
 | |
| contextual nodes.
 | |
| */
 | |
| NodeProp.contextHash = new NodeProp({ perNode: true });
 | |
| /**
 | |
| The distance beyond the end of the node that the tokenizer
 | |
| looked ahead for any of the tokens inside the node. (The LR
 | |
| parser only stores this when it is larger than 25, for
 | |
| efficiency reasons.)
 | |
| */
 | |
| NodeProp.lookAhead = new NodeProp({ perNode: true });
 | |
| /**
 | |
| This per-node prop is used to replace a given node, or part of a
 | |
| node, with another tree. This is useful to include trees from
 | |
| different languages in mixed-language parsers.
 | |
| */
 | |
| NodeProp.mounted = new NodeProp({ perNode: true });
 | |
| /**
 | |
| A mounted tree, which can be [stored](#common.NodeProp^mounted) on
 | |
| a tree node to indicate that parts of its content are
 | |
| represented by another tree.
 | |
| */
 | |
| class MountedTree {
 | |
|     constructor(
 | |
|     /**
 | |
|     The inner tree.
 | |
|     */
 | |
|     tree, 
 | |
|     /**
 | |
|     If this is null, this tree replaces the entire node (it will
 | |
|     be included in the regular iteration instead of its host
 | |
|     node). If not, only the given ranges are considered to be
 | |
|     covered by this tree. This is used for trees that are mixed in
 | |
|     a way that isn't strictly hierarchical. Such mounted trees are
 | |
|     only entered by [`resolveInner`](#common.Tree.resolveInner)
 | |
|     and [`enter`](#common.SyntaxNode.enter).
 | |
|     */
 | |
|     overlay, 
 | |
|     /**
 | |
|     The parser used to create this subtree.
 | |
|     */
 | |
|     parser) {
 | |
|         this.tree = tree;
 | |
|         this.overlay = overlay;
 | |
|         this.parser = parser;
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     static get(tree) {
 | |
|         return tree && tree.props && tree.props[NodeProp.mounted.id];
 | |
|     }
 | |
| }
 | |
| const noProps = Object.create(null);
 | |
| /**
 | |
| Each node in a syntax tree has a node type associated with it.
 | |
| */
 | |
| class NodeType {
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     constructor(
 | |
|     /**
 | |
|     The name of the node type. Not necessarily unique, but if the
 | |
|     grammar was written properly, different node types with the
 | |
|     same name within a node set should play the same semantic
 | |
|     role.
 | |
|     */
 | |
|     name, 
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     props, 
 | |
|     /**
 | |
|     The id of this node in its set. Corresponds to the term ids
 | |
|     used in the parser.
 | |
|     */
 | |
|     id, 
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     flags = 0) {
 | |
|         this.name = name;
 | |
|         this.props = props;
 | |
|         this.id = id;
 | |
|         this.flags = flags;
 | |
|     }
 | |
|     /**
 | |
|     Define a node type.
 | |
|     */
 | |
|     static define(spec) {
 | |
|         let props = spec.props && spec.props.length ? Object.create(null) : noProps;
 | |
|         let flags = (spec.top ? 1 /* NodeFlag.Top */ : 0) | (spec.skipped ? 2 /* NodeFlag.Skipped */ : 0) |
 | |
|             (spec.error ? 4 /* NodeFlag.Error */ : 0) | (spec.name == null ? 8 /* NodeFlag.Anonymous */ : 0);
 | |
|         let type = new NodeType(spec.name || "", props, spec.id, flags);
 | |
|         if (spec.props)
 | |
|             for (let src of spec.props) {
 | |
|                 if (!Array.isArray(src))
 | |
|                     src = src(type);
 | |
|                 if (src) {
 | |
|                     if (src[0].perNode)
 | |
|                         throw new RangeError("Can't store a per-node prop on a node type");
 | |
|                     props[src[0].id] = src[1];
 | |
|                 }
 | |
|             }
 | |
|         return type;
 | |
|     }
 | |
|     /**
 | |
|     Retrieves a node prop for this type. Will return `undefined` if
 | |
|     the prop isn't present on this node.
 | |
|     */
 | |
|     prop(prop) { return this.props[prop.id]; }
 | |
|     /**
 | |
|     True when this is the top node of a grammar.
 | |
|     */
 | |
|     get isTop() { return (this.flags & 1 /* NodeFlag.Top */) > 0; }
 | |
|     /**
 | |
|     True when this node is produced by a skip rule.
 | |
|     */
 | |
|     get isSkipped() { return (this.flags & 2 /* NodeFlag.Skipped */) > 0; }
 | |
|     /**
 | |
|     Indicates whether this is an error node.
 | |
|     */
 | |
|     get isError() { return (this.flags & 4 /* NodeFlag.Error */) > 0; }
 | |
|     /**
 | |
|     When true, this node type doesn't correspond to a user-declared
 | |
|     named node, for example because it is used to cache repetition.
 | |
|     */
 | |
|     get isAnonymous() { return (this.flags & 8 /* NodeFlag.Anonymous */) > 0; }
 | |
|     /**
 | |
|     Returns true when this node's name or one of its
 | |
|     [groups](#common.NodeProp^group) matches the given string.
 | |
|     */
 | |
|     is(name) {
 | |
|         if (typeof name == 'string') {
 | |
|             if (this.name == name)
 | |
|                 return true;
 | |
|             let group = this.prop(NodeProp.group);
 | |
|             return group ? group.indexOf(name) > -1 : false;
 | |
|         }
 | |
|         return this.id == name;
 | |
|     }
 | |
|     /**
 | |
|     Create a function from node types to arbitrary values by
 | |
|     specifying an object whose property names are node or
 | |
|     [group](#common.NodeProp^group) names. Often useful with
 | |
|     [`NodeProp.add`](#common.NodeProp.add). You can put multiple
 | |
|     names, separated by spaces, in a single property name to map
 | |
|     multiple node names to a single value.
 | |
|     */
 | |
|     static match(map) {
 | |
|         let direct = Object.create(null);
 | |
|         for (let prop in map)
 | |
|             for (let name of prop.split(" "))
 | |
|                 direct[name] = map[prop];
 | |
|         return (node) => {
 | |
|             for (let groups = node.prop(NodeProp.group), i = -1; i < (groups ? groups.length : 0); i++) {
 | |
|                 let found = direct[i < 0 ? node.name : groups[i]];
 | |
|                 if (found)
 | |
|                     return found;
 | |
|             }
 | |
|         };
 | |
|     }
 | |
| }
 | |
| /**
 | |
| An empty dummy node type to use when no actual type is available.
 | |
| */
 | |
| NodeType.none = new NodeType("", Object.create(null), 0, 8 /* NodeFlag.Anonymous */);
 | |
| /**
 | |
| A node set holds a collection of node types. It is used to
 | |
| compactly represent trees by storing their type ids, rather than a
 | |
| full pointer to the type object, in a numeric array. Each parser
 | |
| [has](#lr.LRParser.nodeSet) a node set, and [tree
 | |
| buffers](#common.TreeBuffer) can only store collections of nodes
 | |
| from the same set. A set can have a maximum of 2**16 (65536) node
 | |
| types in it, so that the ids fit into 16-bit typed array slots.
 | |
| */
 | |
| class NodeSet {
 | |
|     /**
 | |
|     Create a set with the given types. The `id` property of each
 | |
|     type should correspond to its position within the array.
 | |
|     */
 | |
|     constructor(
 | |
|     /**
 | |
|     The node types in this set, by id.
 | |
|     */
 | |
|     types) {
 | |
|         this.types = types;
 | |
|         for (let i = 0; i < types.length; i++)
 | |
|             if (types[i].id != i)
 | |
|                 throw new RangeError("Node type ids should correspond to array positions when creating a node set");
 | |
|     }
 | |
|     /**
 | |
|     Create a copy of this set with some node properties added. The
 | |
|     arguments to this method can be created with
 | |
|     [`NodeProp.add`](#common.NodeProp.add).
 | |
|     */
 | |
|     extend(...props) {
 | |
|         let newTypes = [];
 | |
|         for (let type of this.types) {
 | |
|             let newProps = null;
 | |
|             for (let source of props) {
 | |
|                 let add = source(type);
 | |
|                 if (add) {
 | |
|                     if (!newProps)
 | |
|                         newProps = Object.assign({}, type.props);
 | |
|                     newProps[add[0].id] = add[1];
 | |
|                 }
 | |
|             }
 | |
|             newTypes.push(newProps ? new NodeType(type.name, newProps, type.id, type.flags) : type);
 | |
|         }
 | |
|         return new NodeSet(newTypes);
 | |
|     }
 | |
| }
 | |
| const CachedNode = new WeakMap(), CachedInnerNode = new WeakMap();
 | |
| /**
 | |
| Options that control iteration. Can be combined with the `|`
 | |
| operator to enable multiple ones.
 | |
| */
 | |
| var IterMode;
 | |
| (function (IterMode) {
 | |
|     /**
 | |
|     When enabled, iteration will only visit [`Tree`](#common.Tree)
 | |
|     objects, not nodes packed into
 | |
|     [`TreeBuffer`](#common.TreeBuffer)s.
 | |
|     */
 | |
|     IterMode[IterMode["ExcludeBuffers"] = 1] = "ExcludeBuffers";
 | |
|     /**
 | |
|     Enable this to make iteration include anonymous nodes (such as
 | |
|     the nodes that wrap repeated grammar constructs into a balanced
 | |
|     tree).
 | |
|     */
 | |
|     IterMode[IterMode["IncludeAnonymous"] = 2] = "IncludeAnonymous";
 | |
|     /**
 | |
|     By default, regular [mounted](#common.NodeProp^mounted) nodes
 | |
|     replace their base node in iteration. Enable this to ignore them
 | |
|     instead.
 | |
|     */
 | |
|     IterMode[IterMode["IgnoreMounts"] = 4] = "IgnoreMounts";
 | |
|     /**
 | |
|     This option only applies in
 | |
|     [`enter`](#common.SyntaxNode.enter)-style methods. It tells the
 | |
|     library to not enter mounted overlays if one covers the given
 | |
|     position.
 | |
|     */
 | |
|     IterMode[IterMode["IgnoreOverlays"] = 8] = "IgnoreOverlays";
 | |
| })(IterMode || (IterMode = {}));
 | |
| /**
 | |
| A piece of syntax tree. There are two ways to approach these
 | |
| trees: the way they are actually stored in memory, and the
 | |
| convenient way.
 | |
| 
 | |
| Syntax trees are stored as a tree of `Tree` and `TreeBuffer`
 | |
| objects. By packing detail information into `TreeBuffer` leaf
 | |
| nodes, the representation is made a lot more memory-efficient.
 | |
| 
 | |
| However, when you want to actually work with tree nodes, this
 | |
| representation is very awkward, so most client code will want to
 | |
| use the [`TreeCursor`](#common.TreeCursor) or
 | |
| [`SyntaxNode`](#common.SyntaxNode) interface instead, which provides
 | |
| a view on some part of this data structure, and can be used to
 | |
| move around to adjacent nodes.
 | |
| */
 | |
| class Tree {
 | |
|     /**
 | |
|     Construct a new tree. See also [`Tree.build`](#common.Tree^build).
 | |
|     */
 | |
|     constructor(
 | |
|     /**
 | |
|     The type of the top node.
 | |
|     */
 | |
|     type, 
 | |
|     /**
 | |
|     This node's child nodes.
 | |
|     */
 | |
|     children, 
 | |
|     /**
 | |
|     The positions (offsets relative to the start of this tree) of
 | |
|     the children.
 | |
|     */
 | |
|     positions, 
 | |
|     /**
 | |
|     The total length of this tree
 | |
|     */
 | |
|     length, 
 | |
|     /**
 | |
|     Per-node [node props](#common.NodeProp) to associate with this node.
 | |
|     */
 | |
|     props) {
 | |
|         this.type = type;
 | |
|         this.children = children;
 | |
|         this.positions = positions;
 | |
|         this.length = length;
 | |
|         /**
 | |
|         @internal
 | |
|         */
 | |
|         this.props = null;
 | |
|         if (props && props.length) {
 | |
|             this.props = Object.create(null);
 | |
|             for (let [prop, value] of props)
 | |
|                 this.props[typeof prop == "number" ? prop : prop.id] = value;
 | |
|         }
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     toString() {
 | |
|         let mounted = MountedTree.get(this);
 | |
|         if (mounted && !mounted.overlay)
 | |
|             return mounted.tree.toString();
 | |
|         let children = "";
 | |
|         for (let ch of this.children) {
 | |
|             let str = ch.toString();
 | |
|             if (str) {
 | |
|                 if (children)
 | |
|                     children += ",";
 | |
|                 children += str;
 | |
|             }
 | |
|         }
 | |
|         return !this.type.name ? children :
 | |
|             (/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) +
 | |
|                 (children.length ? "(" + children + ")" : "");
 | |
|     }
 | |
|     /**
 | |
|     Get a [tree cursor](#common.TreeCursor) positioned at the top of
 | |
|     the tree. Mode can be used to [control](#common.IterMode) which
 | |
|     nodes the cursor visits.
 | |
|     */
 | |
|     cursor(mode = 0) {
 | |
|         return new TreeCursor(this.topNode, mode);
 | |
|     }
 | |
|     /**
 | |
|     Get a [tree cursor](#common.TreeCursor) pointing into this tree
 | |
|     at the given position and side (see
 | |
|     [`moveTo`](#common.TreeCursor.moveTo).
 | |
|     */
 | |
|     cursorAt(pos, side = 0, mode = 0) {
 | |
|         let scope = CachedNode.get(this) || this.topNode;
 | |
|         let cursor = new TreeCursor(scope);
 | |
|         cursor.moveTo(pos, side);
 | |
|         CachedNode.set(this, cursor._tree);
 | |
|         return cursor;
 | |
|     }
 | |
|     /**
 | |
|     Get a [syntax node](#common.SyntaxNode) object for the top of the
 | |
|     tree.
 | |
|     */
 | |
|     get topNode() {
 | |
|         return new TreeNode(this, 0, 0, null);
 | |
|     }
 | |
|     /**
 | |
|     Get the [syntax node](#common.SyntaxNode) at the given position.
 | |
|     If `side` is -1, this will move into nodes that end at the
 | |
|     position. If 1, it'll move into nodes that start at the
 | |
|     position. With 0, it'll only enter nodes that cover the position
 | |
|     from both sides.
 | |
|     
 | |
|     Note that this will not enter
 | |
|     [overlays](#common.MountedTree.overlay), and you often want
 | |
|     [`resolveInner`](#common.Tree.resolveInner) instead.
 | |
|     */
 | |
|     resolve(pos, side = 0) {
 | |
|         let node = resolveNode(CachedNode.get(this) || this.topNode, pos, side, false);
 | |
|         CachedNode.set(this, node);
 | |
|         return node;
 | |
|     }
 | |
|     /**
 | |
|     Like [`resolve`](#common.Tree.resolve), but will enter
 | |
|     [overlaid](#common.MountedTree.overlay) nodes, producing a syntax node
 | |
|     pointing into the innermost overlaid tree at the given position
 | |
|     (with parent links going through all parent structure, including
 | |
|     the host trees).
 | |
|     */
 | |
|     resolveInner(pos, side = 0) {
 | |
|         let node = resolveNode(CachedInnerNode.get(this) || this.topNode, pos, side, true);
 | |
|         CachedInnerNode.set(this, node);
 | |
|         return node;
 | |
|     }
 | |
|     /**
 | |
|     In some situations, it can be useful to iterate through all
 | |
|     nodes around a position, including those in overlays that don't
 | |
|     directly cover the position. This method gives you an iterator
 | |
|     that will produce all nodes, from small to big, around the given
 | |
|     position.
 | |
|     */
 | |
|     resolveStack(pos, side = 0) {
 | |
|         return stackIterator(this, pos, side);
 | |
|     }
 | |
|     /**
 | |
|     Iterate over the tree and its children, calling `enter` for any
 | |
|     node that touches the `from`/`to` region (if given) before
 | |
|     running over such a node's children, and `leave` (if given) when
 | |
|     leaving the node. When `enter` returns `false`, that node will
 | |
|     not have its children iterated over (or `leave` called).
 | |
|     */
 | |
|     iterate(spec) {
 | |
|         let { enter, leave, from = 0, to = this.length } = spec;
 | |
|         let mode = spec.mode || 0, anon = (mode & IterMode.IncludeAnonymous) > 0;
 | |
|         for (let c = this.cursor(mode | IterMode.IncludeAnonymous);;) {
 | |
|             let entered = false;
 | |
|             if (c.from <= to && c.to >= from && (!anon && c.type.isAnonymous || enter(c) !== false)) {
 | |
|                 if (c.firstChild())
 | |
|                     continue;
 | |
|                 entered = true;
 | |
|             }
 | |
|             for (;;) {
 | |
|                 if (entered && leave && (anon || !c.type.isAnonymous))
 | |
|                     leave(c);
 | |
|                 if (c.nextSibling())
 | |
|                     break;
 | |
|                 if (!c.parent())
 | |
|                     return;
 | |
|                 entered = true;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     /**
 | |
|     Get the value of the given [node prop](#common.NodeProp) for this
 | |
|     node. Works with both per-node and per-type props.
 | |
|     */
 | |
|     prop(prop) {
 | |
|         return !prop.perNode ? this.type.prop(prop) : this.props ? this.props[prop.id] : undefined;
 | |
|     }
 | |
|     /**
 | |
|     Returns the node's [per-node props](#common.NodeProp.perNode) in a
 | |
|     format that can be passed to the [`Tree`](#common.Tree)
 | |
|     constructor.
 | |
|     */
 | |
|     get propValues() {
 | |
|         let result = [];
 | |
|         if (this.props)
 | |
|             for (let id in this.props)
 | |
|                 result.push([+id, this.props[id]]);
 | |
|         return result;
 | |
|     }
 | |
|     /**
 | |
|     Balance the direct children of this tree, producing a copy of
 | |
|     which may have children grouped into subtrees with type
 | |
|     [`NodeType.none`](#common.NodeType^none).
 | |
|     */
 | |
|     balance(config = {}) {
 | |
|         return this.children.length <= 8 /* Balance.BranchFactor */ ? this :
 | |
|             balanceRange(NodeType.none, this.children, this.positions, 0, this.children.length, 0, this.length, (children, positions, length) => new Tree(this.type, children, positions, length, this.propValues), config.makeTree || ((children, positions, length) => new Tree(NodeType.none, children, positions, length)));
 | |
|     }
 | |
|     /**
 | |
|     Build a tree from a postfix-ordered buffer of node information,
 | |
|     or a cursor over such a buffer.
 | |
|     */
 | |
|     static build(data) { return buildTree(data); }
 | |
| }
 | |
| /**
 | |
| The empty tree
 | |
| */
 | |
| Tree.empty = new Tree(NodeType.none, [], [], 0);
 | |
| class FlatBufferCursor {
 | |
|     constructor(buffer, index) {
 | |
|         this.buffer = buffer;
 | |
|         this.index = index;
 | |
|     }
 | |
|     get id() { return this.buffer[this.index - 4]; }
 | |
|     get start() { return this.buffer[this.index - 3]; }
 | |
|     get end() { return this.buffer[this.index - 2]; }
 | |
|     get size() { return this.buffer[this.index - 1]; }
 | |
|     get pos() { return this.index; }
 | |
|     next() { this.index -= 4; }
 | |
|     fork() { return new FlatBufferCursor(this.buffer, this.index); }
 | |
| }
 | |
| /**
 | |
| Tree buffers contain (type, start, end, endIndex) quads for each
 | |
| node. In such a buffer, nodes are stored in prefix order (parents
 | |
| before children, with the endIndex of the parent indicating which
 | |
| children belong to it).
 | |
| */
 | |
| class TreeBuffer {
 | |
|     /**
 | |
|     Create a tree buffer.
 | |
|     */
 | |
|     constructor(
 | |
|     /**
 | |
|     The buffer's content.
 | |
|     */
 | |
|     buffer, 
 | |
|     /**
 | |
|     The total length of the group of nodes in the buffer.
 | |
|     */
 | |
|     length, 
 | |
|     /**
 | |
|     The node set used in this buffer.
 | |
|     */
 | |
|     set) {
 | |
|         this.buffer = buffer;
 | |
|         this.length = length;
 | |
|         this.set = set;
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     get type() { return NodeType.none; }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     toString() {
 | |
|         let result = [];
 | |
|         for (let index = 0; index < this.buffer.length;) {
 | |
|             result.push(this.childString(index));
 | |
|             index = this.buffer[index + 3];
 | |
|         }
 | |
|         return result.join(",");
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     childString(index) {
 | |
|         let id = this.buffer[index], endIndex = this.buffer[index + 3];
 | |
|         let type = this.set.types[id], result = type.name;
 | |
|         if (/\W/.test(result) && !type.isError)
 | |
|             result = JSON.stringify(result);
 | |
|         index += 4;
 | |
|         if (endIndex == index)
 | |
|             return result;
 | |
|         let children = [];
 | |
|         while (index < endIndex) {
 | |
|             children.push(this.childString(index));
 | |
|             index = this.buffer[index + 3];
 | |
|         }
 | |
|         return result + "(" + children.join(",") + ")";
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     findChild(startIndex, endIndex, dir, pos, side) {
 | |
|         let { buffer } = this, pick = -1;
 | |
|         for (let i = startIndex; i != endIndex; i = buffer[i + 3]) {
 | |
|             if (checkSide(side, pos, buffer[i + 1], buffer[i + 2])) {
 | |
|                 pick = i;
 | |
|                 if (dir > 0)
 | |
|                     break;
 | |
|             }
 | |
|         }
 | |
|         return pick;
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     slice(startI, endI, from) {
 | |
|         let b = this.buffer;
 | |
|         let copy = new Uint16Array(endI - startI), len = 0;
 | |
|         for (let i = startI, j = 0; i < endI;) {
 | |
|             copy[j++] = b[i++];
 | |
|             copy[j++] = b[i++] - from;
 | |
|             let to = copy[j++] = b[i++] - from;
 | |
|             copy[j++] = b[i++] - startI;
 | |
|             len = Math.max(len, to);
 | |
|         }
 | |
|         return new TreeBuffer(copy, len, this.set);
 | |
|     }
 | |
| }
 | |
| function checkSide(side, pos, from, to) {
 | |
|     switch (side) {
 | |
|         case -2 /* Side.Before */: return from < pos;
 | |
|         case -1 /* Side.AtOrBefore */: return to >= pos && from < pos;
 | |
|         case 0 /* Side.Around */: return from < pos && to > pos;
 | |
|         case 1 /* Side.AtOrAfter */: return from <= pos && to > pos;
 | |
|         case 2 /* Side.After */: return to > pos;
 | |
|         case 4 /* Side.DontCare */: return true;
 | |
|     }
 | |
| }
 | |
| function resolveNode(node, pos, side, overlays) {
 | |
|     var _a;
 | |
|     // Move up to a node that actually holds the position, if possible
 | |
|     while (node.from == node.to ||
 | |
|         (side < 1 ? node.from >= pos : node.from > pos) ||
 | |
|         (side > -1 ? node.to <= pos : node.to < pos)) {
 | |
|         let parent = !overlays && node instanceof TreeNode && node.index < 0 ? null : node.parent;
 | |
|         if (!parent)
 | |
|             return node;
 | |
|         node = parent;
 | |
|     }
 | |
|     let mode = overlays ? 0 : IterMode.IgnoreOverlays;
 | |
|     // Must go up out of overlays when those do not overlap with pos
 | |
|     if (overlays)
 | |
|         for (let scan = node, parent = scan.parent; parent; scan = parent, parent = scan.parent) {
 | |
|             if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side, mode)) === null || _a === void 0 ? void 0 : _a.from) != scan.from)
 | |
|                 node = parent;
 | |
|         }
 | |
|     for (;;) {
 | |
|         let inner = node.enter(pos, side, mode);
 | |
|         if (!inner)
 | |
|             return node;
 | |
|         node = inner;
 | |
|     }
 | |
| }
 | |
| class BaseNode {
 | |
|     cursor(mode = 0) { return new TreeCursor(this, mode); }
 | |
|     getChild(type, before = null, after = null) {
 | |
|         let r = getChildren(this, type, before, after);
 | |
|         return r.length ? r[0] : null;
 | |
|     }
 | |
|     getChildren(type, before = null, after = null) {
 | |
|         return getChildren(this, type, before, after);
 | |
|     }
 | |
|     resolve(pos, side = 0) {
 | |
|         return resolveNode(this, pos, side, false);
 | |
|     }
 | |
|     resolveInner(pos, side = 0) {
 | |
|         return resolveNode(this, pos, side, true);
 | |
|     }
 | |
|     matchContext(context) {
 | |
|         return matchNodeContext(this, context);
 | |
|     }
 | |
|     enterUnfinishedNodesBefore(pos) {
 | |
|         let scan = this.childBefore(pos), node = this;
 | |
|         while (scan) {
 | |
|             let last = scan.lastChild;
 | |
|             if (!last || last.to != scan.to)
 | |
|                 break;
 | |
|             if (last.type.isError && last.from == last.to) {
 | |
|                 node = scan;
 | |
|                 scan = last.prevSibling;
 | |
|             }
 | |
|             else {
 | |
|                 scan = last;
 | |
|             }
 | |
|         }
 | |
|         return node;
 | |
|     }
 | |
|     get node() { return this; }
 | |
|     get next() { return this.parent; }
 | |
| }
 | |
| class TreeNode extends BaseNode {
 | |
|     constructor(_tree, from, 
 | |
|     // Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
 | |
|     index, _parent) {
 | |
|         super();
 | |
|         this._tree = _tree;
 | |
|         this.from = from;
 | |
|         this.index = index;
 | |
|         this._parent = _parent;
 | |
|     }
 | |
|     get type() { return this._tree.type; }
 | |
|     get name() { return this._tree.type.name; }
 | |
|     get to() { return this.from + this._tree.length; }
 | |
|     nextChild(i, dir, pos, side, mode = 0) {
 | |
|         for (let parent = this;;) {
 | |
|             for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) {
 | |
|                 let next = children[i], start = positions[i] + parent.from;
 | |
|                 if (!checkSide(side, pos, start, start + next.length))
 | |
|                     continue;
 | |
|                 if (next instanceof TreeBuffer) {
 | |
|                     if (mode & IterMode.ExcludeBuffers)
 | |
|                         continue;
 | |
|                     let index = next.findChild(0, next.buffer.length, dir, pos - start, side);
 | |
|                     if (index > -1)
 | |
|                         return new BufferNode(new BufferContext(parent, next, i, start), null, index);
 | |
|                 }
 | |
|                 else if ((mode & IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
 | |
|                     let mounted;
 | |
|                     if (!(mode & IterMode.IgnoreMounts) && (mounted = MountedTree.get(next)) && !mounted.overlay)
 | |
|                         return new TreeNode(mounted.tree, start, i, parent);
 | |
|                     let inner = new TreeNode(next, start, i, parent);
 | |
|                     return (mode & IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
 | |
|                         : inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side);
 | |
|                 }
 | |
|             }
 | |
|             if ((mode & IterMode.IncludeAnonymous) || !parent.type.isAnonymous)
 | |
|                 return null;
 | |
|             if (parent.index >= 0)
 | |
|                 i = parent.index + dir;
 | |
|             else
 | |
|                 i = dir < 0 ? -1 : parent._parent._tree.children.length;
 | |
|             parent = parent._parent;
 | |
|             if (!parent)
 | |
|                 return null;
 | |
|         }
 | |
|     }
 | |
|     get firstChild() { return this.nextChild(0, 1, 0, 4 /* Side.DontCare */); }
 | |
|     get lastChild() { return this.nextChild(this._tree.children.length - 1, -1, 0, 4 /* Side.DontCare */); }
 | |
|     childAfter(pos) { return this.nextChild(0, 1, pos, 2 /* Side.After */); }
 | |
|     childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Side.Before */); }
 | |
|     enter(pos, side, mode = 0) {
 | |
|         let mounted;
 | |
|         if (!(mode & IterMode.IgnoreOverlays) && (mounted = MountedTree.get(this._tree)) && mounted.overlay) {
 | |
|             let rPos = pos - this.from;
 | |
|             for (let { from, to } of mounted.overlay) {
 | |
|                 if ((side > 0 ? from <= rPos : from < rPos) &&
 | |
|                     (side < 0 ? to >= rPos : to > rPos))
 | |
|                     return new TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this);
 | |
|             }
 | |
|         }
 | |
|         return this.nextChild(0, 1, pos, side, mode);
 | |
|     }
 | |
|     nextSignificantParent() {
 | |
|         let val = this;
 | |
|         while (val.type.isAnonymous && val._parent)
 | |
|             val = val._parent;
 | |
|         return val;
 | |
|     }
 | |
|     get parent() {
 | |
|         return this._parent ? this._parent.nextSignificantParent() : null;
 | |
|     }
 | |
|     get nextSibling() {
 | |
|         return this._parent && this.index >= 0 ? this._parent.nextChild(this.index + 1, 1, 0, 4 /* Side.DontCare */) : null;
 | |
|     }
 | |
|     get prevSibling() {
 | |
|         return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* Side.DontCare */) : null;
 | |
|     }
 | |
|     get tree() { return this._tree; }
 | |
|     toTree() { return this._tree; }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     toString() { return this._tree.toString(); }
 | |
| }
 | |
| function getChildren(node, type, before, after) {
 | |
|     let cur = node.cursor(), result = [];
 | |
|     if (!cur.firstChild())
 | |
|         return result;
 | |
|     if (before != null)
 | |
|         for (let found = false; !found;) {
 | |
|             found = cur.type.is(before);
 | |
|             if (!cur.nextSibling())
 | |
|                 return result;
 | |
|         }
 | |
|     for (;;) {
 | |
|         if (after != null && cur.type.is(after))
 | |
|             return result;
 | |
|         if (cur.type.is(type))
 | |
|             result.push(cur.node);
 | |
|         if (!cur.nextSibling())
 | |
|             return after == null ? result : [];
 | |
|     }
 | |
| }
 | |
| function matchNodeContext(node, context, i = context.length - 1) {
 | |
|     for (let p = node.parent; i >= 0; p = p.parent) {
 | |
|         if (!p)
 | |
|             return false;
 | |
|         if (!p.type.isAnonymous) {
 | |
|             if (context[i] && context[i] != p.name)
 | |
|                 return false;
 | |
|             i--;
 | |
|         }
 | |
|     }
 | |
|     return true;
 | |
| }
 | |
| class BufferContext {
 | |
|     constructor(parent, buffer, index, start) {
 | |
|         this.parent = parent;
 | |
|         this.buffer = buffer;
 | |
|         this.index = index;
 | |
|         this.start = start;
 | |
|     }
 | |
| }
 | |
| class BufferNode extends BaseNode {
 | |
|     get name() { return this.type.name; }
 | |
|     get from() { return this.context.start + this.context.buffer.buffer[this.index + 1]; }
 | |
|     get to() { return this.context.start + this.context.buffer.buffer[this.index + 2]; }
 | |
|     constructor(context, _parent, index) {
 | |
|         super();
 | |
|         this.context = context;
 | |
|         this._parent = _parent;
 | |
|         this.index = index;
 | |
|         this.type = context.buffer.set.types[context.buffer.buffer[index]];
 | |
|     }
 | |
|     child(dir, pos, side) {
 | |
|         let { buffer } = this.context;
 | |
|         let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.context.start, side);
 | |
|         return index < 0 ? null : new BufferNode(this.context, this, index);
 | |
|     }
 | |
|     get firstChild() { return this.child(1, 0, 4 /* Side.DontCare */); }
 | |
|     get lastChild() { return this.child(-1, 0, 4 /* Side.DontCare */); }
 | |
|     childAfter(pos) { return this.child(1, pos, 2 /* Side.After */); }
 | |
|     childBefore(pos) { return this.child(-1, pos, -2 /* Side.Before */); }
 | |
|     enter(pos, side, mode = 0) {
 | |
|         if (mode & IterMode.ExcludeBuffers)
 | |
|             return null;
 | |
|         let { buffer } = this.context;
 | |
|         let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side);
 | |
|         return index < 0 ? null : new BufferNode(this.context, this, index);
 | |
|     }
 | |
|     get parent() {
 | |
|         return this._parent || this.context.parent.nextSignificantParent();
 | |
|     }
 | |
|     externalSibling(dir) {
 | |
|         return this._parent ? null : this.context.parent.nextChild(this.context.index + dir, dir, 0, 4 /* Side.DontCare */);
 | |
|     }
 | |
|     get nextSibling() {
 | |
|         let { buffer } = this.context;
 | |
|         let after = buffer.buffer[this.index + 3];
 | |
|         if (after < (this._parent ? buffer.buffer[this._parent.index + 3] : buffer.buffer.length))
 | |
|             return new BufferNode(this.context, this._parent, after);
 | |
|         return this.externalSibling(1);
 | |
|     }
 | |
|     get prevSibling() {
 | |
|         let { buffer } = this.context;
 | |
|         let parentStart = this._parent ? this._parent.index + 4 : 0;
 | |
|         if (this.index == parentStart)
 | |
|             return this.externalSibling(-1);
 | |
|         return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* Side.DontCare */));
 | |
|     }
 | |
|     get tree() { return null; }
 | |
|     toTree() {
 | |
|         let children = [], positions = [];
 | |
|         let { buffer } = this.context;
 | |
|         let startI = this.index + 4, endI = buffer.buffer[this.index + 3];
 | |
|         if (endI > startI) {
 | |
|             let from = buffer.buffer[this.index + 1];
 | |
|             children.push(buffer.slice(startI, endI, from));
 | |
|             positions.push(0);
 | |
|         }
 | |
|         return new Tree(this.type, children, positions, this.to - this.from);
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     toString() { return this.context.buffer.childString(this.index); }
 | |
| }
 | |
| function iterStack(heads) {
 | |
|     if (!heads.length)
 | |
|         return null;
 | |
|     let pick = 0, picked = heads[0];
 | |
|     for (let i = 1; i < heads.length; i++) {
 | |
|         let node = heads[i];
 | |
|         if (node.from > picked.from || node.to < picked.to) {
 | |
|             picked = node;
 | |
|             pick = i;
 | |
|         }
 | |
|     }
 | |
|     let next = picked instanceof TreeNode && picked.index < 0 ? null : picked.parent;
 | |
|     let newHeads = heads.slice();
 | |
|     if (next)
 | |
|         newHeads[pick] = next;
 | |
|     else
 | |
|         newHeads.splice(pick, 1);
 | |
|     return new StackIterator(newHeads, picked);
 | |
| }
 | |
| class StackIterator {
 | |
|     constructor(heads, node) {
 | |
|         this.heads = heads;
 | |
|         this.node = node;
 | |
|     }
 | |
|     get next() { return iterStack(this.heads); }
 | |
| }
 | |
| function stackIterator(tree, pos, side) {
 | |
|     let inner = tree.resolveInner(pos, side), layers = null;
 | |
|     for (let scan = inner instanceof TreeNode ? inner : inner.context.parent; scan; scan = scan.parent) {
 | |
|         if (scan.index < 0) { // This is an overlay root
 | |
|             let parent = scan.parent;
 | |
|             (layers || (layers = [inner])).push(parent.resolve(pos, side));
 | |
|             scan = parent;
 | |
|         }
 | |
|         else {
 | |
|             let mount = MountedTree.get(scan.tree);
 | |
|             // Relevant overlay branching off
 | |
|             if (mount && mount.overlay && mount.overlay[0].from <= pos && mount.overlay[mount.overlay.length - 1].to >= pos) {
 | |
|                 let root = new TreeNode(mount.tree, mount.overlay[0].from + scan.from, -1, scan);
 | |
|                 (layers || (layers = [inner])).push(resolveNode(root, pos, side, false));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return layers ? iterStack(layers) : inner;
 | |
| }
 | |
| /**
 | |
| A tree cursor object focuses on a given node in a syntax tree, and
 | |
| allows you to move to adjacent nodes.
 | |
| */
 | |
| class TreeCursor {
 | |
|     /**
 | |
|     Shorthand for `.type.name`.
 | |
|     */
 | |
|     get name() { return this.type.name; }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     constructor(node, 
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     mode = 0) {
 | |
|         this.mode = mode;
 | |
|         /**
 | |
|         @internal
 | |
|         */
 | |
|         this.buffer = null;
 | |
|         this.stack = [];
 | |
|         /**
 | |
|         @internal
 | |
|         */
 | |
|         this.index = 0;
 | |
|         this.bufferNode = null;
 | |
|         if (node instanceof TreeNode) {
 | |
|             this.yieldNode(node);
 | |
|         }
 | |
|         else {
 | |
|             this._tree = node.context.parent;
 | |
|             this.buffer = node.context;
 | |
|             for (let n = node._parent; n; n = n._parent)
 | |
|                 this.stack.unshift(n.index);
 | |
|             this.bufferNode = node;
 | |
|             this.yieldBuf(node.index);
 | |
|         }
 | |
|     }
 | |
|     yieldNode(node) {
 | |
|         if (!node)
 | |
|             return false;
 | |
|         this._tree = node;
 | |
|         this.type = node.type;
 | |
|         this.from = node.from;
 | |
|         this.to = node.to;
 | |
|         return true;
 | |
|     }
 | |
|     yieldBuf(index, type) {
 | |
|         this.index = index;
 | |
|         let { start, buffer } = this.buffer;
 | |
|         this.type = type || buffer.set.types[buffer.buffer[index]];
 | |
|         this.from = start + buffer.buffer[index + 1];
 | |
|         this.to = start + buffer.buffer[index + 2];
 | |
|         return true;
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     yield(node) {
 | |
|         if (!node)
 | |
|             return false;
 | |
|         if (node instanceof TreeNode) {
 | |
|             this.buffer = null;
 | |
|             return this.yieldNode(node);
 | |
|         }
 | |
|         this.buffer = node.context;
 | |
|         return this.yieldBuf(node.index, node.type);
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     toString() {
 | |
|         return this.buffer ? this.buffer.buffer.childString(this.index) : this._tree.toString();
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     enterChild(dir, pos, side) {
 | |
|         if (!this.buffer)
 | |
|             return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode));
 | |
|         let { buffer } = this.buffer;
 | |
|         let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.buffer.start, side);
 | |
|         if (index < 0)
 | |
|             return false;
 | |
|         this.stack.push(this.index);
 | |
|         return this.yieldBuf(index);
 | |
|     }
 | |
|     /**
 | |
|     Move the cursor to this node's first child. When this returns
 | |
|     false, the node has no child, and the cursor has not been moved.
 | |
|     */
 | |
|     firstChild() { return this.enterChild(1, 0, 4 /* Side.DontCare */); }
 | |
|     /**
 | |
|     Move the cursor to this node's last child.
 | |
|     */
 | |
|     lastChild() { return this.enterChild(-1, 0, 4 /* Side.DontCare */); }
 | |
|     /**
 | |
|     Move the cursor to the first child that ends after `pos`.
 | |
|     */
 | |
|     childAfter(pos) { return this.enterChild(1, pos, 2 /* Side.After */); }
 | |
|     /**
 | |
|     Move to the last child that starts before `pos`.
 | |
|     */
 | |
|     childBefore(pos) { return this.enterChild(-1, pos, -2 /* Side.Before */); }
 | |
|     /**
 | |
|     Move the cursor to the child around `pos`. If side is -1 the
 | |
|     child may end at that position, when 1 it may start there. This
 | |
|     will also enter [overlaid](#common.MountedTree.overlay)
 | |
|     [mounted](#common.NodeProp^mounted) trees unless `overlays` is
 | |
|     set to false.
 | |
|     */
 | |
|     enter(pos, side, mode = this.mode) {
 | |
|         if (!this.buffer)
 | |
|             return this.yield(this._tree.enter(pos, side, mode));
 | |
|         return mode & IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side);
 | |
|     }
 | |
|     /**
 | |
|     Move to the node's parent node, if this isn't the top node.
 | |
|     */
 | |
|     parent() {
 | |
|         if (!this.buffer)
 | |
|             return this.yieldNode((this.mode & IterMode.IncludeAnonymous) ? this._tree._parent : this._tree.parent);
 | |
|         if (this.stack.length)
 | |
|             return this.yieldBuf(this.stack.pop());
 | |
|         let parent = (this.mode & IterMode.IncludeAnonymous) ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
 | |
|         this.buffer = null;
 | |
|         return this.yieldNode(parent);
 | |
|     }
 | |
|     /**
 | |
|     @internal
 | |
|     */
 | |
|     sibling(dir) {
 | |
|         if (!this.buffer)
 | |
|             return !this._tree._parent ? false
 | |
|                 : this.yield(this._tree.index < 0 ? null
 | |
|                     : this._tree._parent.nextChild(this._tree.index + dir, dir, 0, 4 /* Side.DontCare */, this.mode));
 | |
|         let { buffer } = this.buffer, d = this.stack.length - 1;
 | |
|         if (dir < 0) {
 | |
|             let parentStart = d < 0 ? 0 : this.stack[d] + 4;
 | |
|             if (this.index != parentStart)
 | |
|                 return this.yieldBuf(buffer.findChild(parentStart, this.index, -1, 0, 4 /* Side.DontCare */));
 | |
|         }
 | |
|         else {
 | |
|             let after = buffer.buffer[this.index + 3];
 | |
|             if (after < (d < 0 ? buffer.buffer.length : buffer.buffer[this.stack[d] + 3]))
 | |
|                 return this.yieldBuf(after);
 | |
|         }
 | |
|         return d < 0 ? this.yield(this.buffer.parent.nextChild(this.buffer.index + dir, dir, 0, 4 /* Side.DontCare */, this.mode)) : false;
 | |
|     }
 | |
|     /**
 | |
|     Move to this node's next sibling, if any.
 | |
|     */
 | |
|     nextSibling() { return this.sibling(1); }
 | |
|     /**
 | |
|     Move to this node's previous sibling, if any.
 | |
|     */
 | |
|     prevSibling() { return this.sibling(-1); }
 | |
|     atLastNode(dir) {
 | |
|         let index, parent, { buffer } = this;
 | |
|         if (buffer) {
 | |
|             if (dir > 0) {
 | |
|                 if (this.index < buffer.buffer.buffer.length)
 | |
|                     return false;
 | |
|             }
 | |
|             else {
 | |
|                 for (let i = 0; i < this.index; i++)
 | |
|                     if (buffer.buffer.buffer[i + 3] < this.index)
 | |
|                         return false;
 | |
|             }
 | |
|             ({ index, parent } = buffer);
 | |
|         }
 | |
|         else {
 | |
|             ({ index, _parent: parent } = this._tree);
 | |
|         }
 | |
|         for (; parent; { index, _parent: parent } = parent) {
 | |
|             if (index > -1)
 | |
|                 for (let i = index + dir, e = dir < 0 ? -1 : parent._tree.children.length; i != e; i += dir) {
 | |
|                     let child = parent._tree.children[i];
 | |
|                     if ((this.mode & IterMode.IncludeAnonymous) ||
 | |
|                         child instanceof TreeBuffer ||
 | |
|                         !child.type.isAnonymous ||
 | |
|                         hasChild(child))
 | |
|                         return false;
 | |
|                 }
 | |
|         }
 | |
|         return true;
 | |
|     }
 | |
|     move(dir, enter) {
 | |
|         if (enter && this.enterChild(dir, 0, 4 /* Side.DontCare */))
 | |
|             return true;
 | |
|         for (;;) {
 | |
|             if (this.sibling(dir))
 | |
|                 return true;
 | |
|             if (this.atLastNode(dir) || !this.parent())
 | |
|                 return false;
 | |
|         }
 | |
|     }
 | |
|     /**
 | |
|     Move to the next node in a
 | |
|     [pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR)
 | |
|     traversal, going from a node to its first child or, if the
 | |
|     current node is empty or `enter` is false, its next sibling or
 | |
|     the next sibling of the first parent node that has one.
 | |
|     */
 | |
|     next(enter = true) { return this.move(1, enter); }
 | |
|     /**
 | |
|     Move to the next node in a last-to-first pre-order traveral. A
 | |
|     node is followed by its last child or, if it has none, its
 | |
|     previous sibling or the previous sibling of the first parent
 | |
|     node that has one.
 | |
|     */
 | |
|     prev(enter = true) { return this.move(-1, enter); }
 | |
|     /**
 | |
|     Move the cursor to the innermost node that covers `pos`. If
 | |
|     `side` is -1, it will enter nodes that end at `pos`. If it is 1,
 | |
|     it will enter nodes that start at `pos`.
 | |
|     */
 | |
|     moveTo(pos, side = 0) {
 | |
|         // Move up to a node that actually holds the position, if possible
 | |
|         while (this.from == this.to ||
 | |
|             (side < 1 ? this.from >= pos : this.from > pos) ||
 | |
|             (side > -1 ? this.to <= pos : this.to < pos))
 | |
|             if (!this.parent())
 | |
|                 break;
 | |
|         // Then scan down into child nodes as far as possible
 | |
|         while (this.enterChild(1, pos, side)) { }
 | |
|         return this;
 | |
|     }
 | |
|     /**
 | |
|     Get a [syntax node](#common.SyntaxNode) at the cursor's current
 | |
|     position.
 | |
|     */
 | |
|     get node() {
 | |
|         if (!this.buffer)
 | |
|             return this._tree;
 | |
|         let cache = this.bufferNode, result = null, depth = 0;
 | |
|         if (cache && cache.context == this.buffer) {
 | |
|             scan: for (let index = this.index, d = this.stack.length; d >= 0;) {
 | |
|                 for (let c = cache; c; c = c._parent)
 | |
|                     if (c.index == index) {
 | |
|                         if (index == this.index)
 | |
|                             return c;
 | |
|                         result = c;
 | |
|                         depth = d + 1;
 | |
|                         break scan;
 | |
|                     }
 | |
|                 index = this.stack[--d];
 | |
|             }
 | |
|         }
 | |
|         for (let i = depth; i < this.stack.length; i++)
 | |
|             result = new BufferNode(this.buffer, result, this.stack[i]);
 | |
|         return this.bufferNode = new BufferNode(this.buffer, result, this.index);
 | |
|     }
 | |
|     /**
 | |
|     Get the [tree](#common.Tree) that represents the current node, if
 | |
|     any. Will return null when the node is in a [tree
 | |
|     buffer](#common.TreeBuffer).
 | |
|     */
 | |
|     get tree() {
 | |
|         return this.buffer ? null : this._tree._tree;
 | |
|     }
 | |
|     /**
 | |
|     Iterate over the current node and all its descendants, calling
 | |
|     `enter` when entering a node and `leave`, if given, when leaving
 | |
|     one. When `enter` returns `false`, any children of that node are
 | |
|     skipped, and `leave` isn't called for it.
 | |
|     */
 | |
|     iterate(enter, leave) {
 | |
|         for (let depth = 0;;) {
 | |
|             let mustLeave = false;
 | |
|             if (this.type.isAnonymous || enter(this) !== false) {
 | |
|                 if (this.firstChild()) {
 | |
|                     depth++;
 | |
|                     continue;
 | |
|                 }
 | |
|                 if (!this.type.isAnonymous)
 | |
|                     mustLeave = true;
 | |
|             }
 | |
|             for (;;) {
 | |
|                 if (mustLeave && leave)
 | |
|                     leave(this);
 | |
|                 mustLeave = this.type.isAnonymous;
 | |
|                 if (this.nextSibling())
 | |
|                     break;
 | |
|                 if (!depth)
 | |
|                     return;
 | |
|                 this.parent();
 | |
|                 depth--;
 | |
|                 mustLeave = true;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     /**
 | |
|     Test whether the current node matches a given context—a sequence
 | |
|     of direct parent node names. Empty strings in the context array
 | |
|     are treated as wildcards.
 | |
|     */
 | |
|     matchContext(context) {
 | |
|         if (!this.buffer)
 | |
|             return matchNodeContext(this.node, context);
 | |
|         let { buffer } = this.buffer, { types } = buffer.set;
 | |
|         for (let i = context.length - 1, d = this.stack.length - 1; i >= 0; d--) {
 | |
|             if (d < 0)
 | |
|                 return matchNodeContext(this.node, context, i);
 | |
|             let type = types[buffer.buffer[this.stack[d]]];
 | |
|             if (!type.isAnonymous) {
 | |
|                 if (context[i] && context[i] != type.name)
 | |
|                     return false;
 | |
|                 i--;
 | |
|             }
 | |
|         }
 | |
|         return true;
 | |
|     }
 | |
| }
 | |
| function hasChild(tree) {
 | |
|     return tree.children.some(ch => ch instanceof TreeBuffer || !ch.type.isAnonymous || hasChild(ch));
 | |
| }
 | |
| function buildTree(data) {
 | |
|     var _a;
 | |
|     let { buffer, nodeSet, maxBufferLength = DefaultBufferLength, reused = [], minRepeatType = nodeSet.types.length } = data;
 | |
|     let cursor = Array.isArray(buffer) ? new FlatBufferCursor(buffer, buffer.length) : buffer;
 | |
|     let types = nodeSet.types;
 | |
|     let contextHash = 0, lookAhead = 0;
 | |
|     function takeNode(parentStart, minPos, children, positions, inRepeat, depth) {
 | |
|         let { id, start, end, size } = cursor;
 | |
|         let lookAheadAtStart = lookAhead;
 | |
|         while (size < 0) {
 | |
|             cursor.next();
 | |
|             if (size == -1 /* SpecialRecord.Reuse */) {
 | |
|                 let node = reused[id];
 | |
|                 children.push(node);
 | |
|                 positions.push(start - parentStart);
 | |
|                 return;
 | |
|             }
 | |
|             else if (size == -3 /* SpecialRecord.ContextChange */) { // Context change
 | |
|                 contextHash = id;
 | |
|                 return;
 | |
|             }
 | |
|             else if (size == -4 /* SpecialRecord.LookAhead */) {
 | |
|                 lookAhead = id;
 | |
|                 return;
 | |
|             }
 | |
|             else {
 | |
|                 throw new RangeError(`Unrecognized record size: ${size}`);
 | |
|             }
 | |
|         }
 | |
|         let type = types[id], node, buffer;
 | |
|         let startPos = start - parentStart;
 | |
|         if (end - start <= maxBufferLength && (buffer = findBufferSize(cursor.pos - minPos, inRepeat))) {
 | |
|             // Small enough for a buffer, and no reused nodes inside
 | |
|             let data = new Uint16Array(buffer.size - buffer.skip);
 | |
|             let endPos = cursor.pos - buffer.size, index = data.length;
 | |
|             while (cursor.pos > endPos)
 | |
|                 index = copyToBuffer(buffer.start, data, index);
 | |
|             node = new TreeBuffer(data, end - buffer.start, nodeSet);
 | |
|             startPos = buffer.start - parentStart;
 | |
|         }
 | |
|         else { // Make it a node
 | |
|             let endPos = cursor.pos - size;
 | |
|             cursor.next();
 | |
|             let localChildren = [], localPositions = [];
 | |
|             let localInRepeat = id >= minRepeatType ? id : -1;
 | |
|             let lastGroup = 0, lastEnd = end;
 | |
|             while (cursor.pos > endPos) {
 | |
|                 if (localInRepeat >= 0 && cursor.id == localInRepeat && cursor.size >= 0) {
 | |
|                     if (cursor.end <= lastEnd - maxBufferLength) {
 | |
|                         makeRepeatLeaf(localChildren, localPositions, start, lastGroup, cursor.end, lastEnd, localInRepeat, lookAheadAtStart);
 | |
|                         lastGroup = localChildren.length;
 | |
|                         lastEnd = cursor.end;
 | |
|                     }
 | |
|                     cursor.next();
 | |
|                 }
 | |
|                 else if (depth > 2500 /* CutOff.Depth */) {
 | |
|                     takeFlatNode(start, endPos, localChildren, localPositions);
 | |
|                 }
 | |
|                 else {
 | |
|                     takeNode(start, endPos, localChildren, localPositions, localInRepeat, depth + 1);
 | |
|                 }
 | |
|             }
 | |
|             if (localInRepeat >= 0 && lastGroup > 0 && lastGroup < localChildren.length)
 | |
|                 makeRepeatLeaf(localChildren, localPositions, start, lastGroup, start, lastEnd, localInRepeat, lookAheadAtStart);
 | |
|             localChildren.reverse();
 | |
|             localPositions.reverse();
 | |
|             if (localInRepeat > -1 && lastGroup > 0) {
 | |
|                 let make = makeBalanced(type);
 | |
|                 node = balanceRange(type, localChildren, localPositions, 0, localChildren.length, 0, end - start, make, make);
 | |
|             }
 | |
|             else {
 | |
|                 node = makeTree(type, localChildren, localPositions, end - start, lookAheadAtStart - end);
 | |
|             }
 | |
|         }
 | |
|         children.push(node);
 | |
|         positions.push(startPos);
 | |
|     }
 | |
|     function takeFlatNode(parentStart, minPos, children, positions) {
 | |
|         let nodes = []; // Temporary, inverted array of leaf nodes found, with absolute positions
 | |
|         let nodeCount = 0, stopAt = -1;
 | |
|         while (cursor.pos > minPos) {
 | |
|             let { id, start, end, size } = cursor;
 | |
|             if (size > 4) { // Not a leaf
 | |
|                 cursor.next();
 | |
|             }
 | |
|             else if (stopAt > -1 && start < stopAt) {
 | |
|                 break;
 | |
|             }
 | |
|             else {
 | |
|                 if (stopAt < 0)
 | |
|                     stopAt = end - maxBufferLength;
 | |
|                 nodes.push(id, start, end);
 | |
|                 nodeCount++;
 | |
|                 cursor.next();
 | |
|             }
 | |
|         }
 | |
|         if (nodeCount) {
 | |
|             let buffer = new Uint16Array(nodeCount * 4);
 | |
|             let start = nodes[nodes.length - 2];
 | |
|             for (let i = nodes.length - 3, j = 0; i >= 0; i -= 3) {
 | |
|                 buffer[j++] = nodes[i];
 | |
|                 buffer[j++] = nodes[i + 1] - start;
 | |
|                 buffer[j++] = nodes[i + 2] - start;
 | |
|                 buffer[j++] = j;
 | |
|             }
 | |
|             children.push(new TreeBuffer(buffer, nodes[2] - start, nodeSet));
 | |
|             positions.push(start - parentStart);
 | |
|         }
 | |
|     }
 | |
|     function makeBalanced(type) {
 | |
|         return (children, positions, length) => {
 | |
|             let lookAhead = 0, lastI = children.length - 1, last, lookAheadProp;
 | |
|             if (lastI >= 0 && (last = children[lastI]) instanceof Tree) {
 | |
|                 if (!lastI && last.type == type && last.length == length)
 | |
|                     return last;
 | |
|                 if (lookAheadProp = last.prop(NodeProp.lookAhead))
 | |
|                     lookAhead = positions[lastI] + last.length + lookAheadProp;
 | |
|             }
 | |
|             return makeTree(type, children, positions, length, lookAhead);
 | |
|         };
 | |
|     }
 | |
|     function makeRepeatLeaf(children, positions, base, i, from, to, type, lookAhead) {
 | |
|         let localChildren = [], localPositions = [];
 | |
|         while (children.length > i) {
 | |
|             localChildren.push(children.pop());
 | |
|             localPositions.push(positions.pop() + base - from);
 | |
|         }
 | |
|         children.push(makeTree(nodeSet.types[type], localChildren, localPositions, to - from, lookAhead - to));
 | |
|         positions.push(from - base);
 | |
|     }
 | |
|     function makeTree(type, children, positions, length, lookAhead = 0, props) {
 | |
|         if (contextHash) {
 | |
|             let pair = [NodeProp.contextHash, contextHash];
 | |
|             props = props ? [pair].concat(props) : [pair];
 | |
|         }
 | |
|         if (lookAhead > 25) {
 | |
|             let pair = [NodeProp.lookAhead, lookAhead];
 | |
|             props = props ? [pair].concat(props) : [pair];
 | |
|         }
 | |
|         return new Tree(type, children, positions, length, props);
 | |
|     }
 | |
|     function findBufferSize(maxSize, inRepeat) {
 | |
|         // Scan through the buffer to find previous siblings that fit
 | |
|         // together in a TreeBuffer, and don't contain any reused nodes
 | |
|         // (which can't be stored in a buffer).
 | |
|         // If `inRepeat` is > -1, ignore node boundaries of that type for
 | |
|         // nesting, but make sure the end falls either at the start
 | |
|         // (`maxSize`) or before such a node.
 | |
|         let fork = cursor.fork();
 | |
|         let size = 0, start = 0, skip = 0, minStart = fork.end - maxBufferLength;
 | |
|         let result = { size: 0, start: 0, skip: 0 };
 | |
|         scan: for (let minPos = fork.pos - maxSize; fork.pos > minPos;) {
 | |
|             let nodeSize = fork.size;
 | |
|             // Pretend nested repeat nodes of the same type don't exist
 | |
|             if (fork.id == inRepeat && nodeSize >= 0) {
 | |
|                 // Except that we store the current state as a valid return
 | |
|                 // value.
 | |
|                 result.size = size;
 | |
|                 result.start = start;
 | |
|                 result.skip = skip;
 | |
|                 skip += 4;
 | |
|                 size += 4;
 | |
|                 fork.next();
 | |
|                 continue;
 | |
|             }
 | |
|             let startPos = fork.pos - nodeSize;
 | |
|             if (nodeSize < 0 || startPos < minPos || fork.start < minStart)
 | |
|                 break;
 | |
|             let localSkipped = fork.id >= minRepeatType ? 4 : 0;
 | |
|             let nodeStart = fork.start;
 | |
|             fork.next();
 | |
|             while (fork.pos > startPos) {
 | |
|                 if (fork.size < 0) {
 | |
|                     if (fork.size == -3 /* SpecialRecord.ContextChange */)
 | |
|                         localSkipped += 4;
 | |
|                     else
 | |
|                         break scan;
 | |
|                 }
 | |
|                 else if (fork.id >= minRepeatType) {
 | |
|                     localSkipped += 4;
 | |
|                 }
 | |
|                 fork.next();
 | |
|             }
 | |
|             start = nodeStart;
 | |
|             size += nodeSize;
 | |
|             skip += localSkipped;
 | |
|         }
 | |
|         if (inRepeat < 0 || size == maxSize) {
 | |
|             result.size = size;
 | |
|             result.start = start;
 | |
|             result.skip = skip;
 | |
|         }
 | |
|         return result.size > 4 ? result : undefined;
 | |
|     }
 | |
|     function copyToBuffer(bufferStart, buffer, index) {
 | |
|         let { id, start, end, size } = cursor;
 | |
|         cursor.next();
 | |
|         if (size >= 0 && id < minRepeatType) {
 | |
|             let startIndex = index;
 | |
|             if (size > 4) {
 | |
|                 let endPos = cursor.pos - (size - 4);
 | |
|                 while (cursor.pos > endPos)
 | |
|                     index = copyToBuffer(bufferStart, buffer, index);
 | |
|             }
 | |
|             buffer[--index] = startIndex;
 | |
|             buffer[--index] = end - bufferStart;
 | |
|             buffer[--index] = start - bufferStart;
 | |
|             buffer[--index] = id;
 | |
|         }
 | |
|         else if (size == -3 /* SpecialRecord.ContextChange */) {
 | |
|             contextHash = id;
 | |
|         }
 | |
|         else if (size == -4 /* SpecialRecord.LookAhead */) {
 | |
|             lookAhead = id;
 | |
|         }
 | |
|         return index;
 | |
|     }
 | |
|     let children = [], positions = [];
 | |
|     while (cursor.pos > 0)
 | |
|         takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1, 0);
 | |
|     let length = (_a = data.length) !== null && _a !== void 0 ? _a : (children.length ? positions[0] + children[0].length : 0);
 | |
|     return new Tree(types[data.topID], children.reverse(), positions.reverse(), length);
 | |
| }
 | |
| const nodeSizeCache = new WeakMap;
 | |
| function nodeSize(balanceType, node) {
 | |
|     if (!balanceType.isAnonymous || node instanceof TreeBuffer || node.type != balanceType)
 | |
|         return 1;
 | |
|     let size = nodeSizeCache.get(node);
 | |
|     if (size == null) {
 | |
|         size = 1;
 | |
|         for (let child of node.children) {
 | |
|             if (child.type != balanceType || !(child instanceof Tree)) {
 | |
|                 size = 1;
 | |
|                 break;
 | |
|             }
 | |
|             size += nodeSize(balanceType, child);
 | |
|         }
 | |
|         nodeSizeCache.set(node, size);
 | |
|     }
 | |
|     return size;
 | |
| }
 | |
| function balanceRange(
 | |
| // The type the balanced tree's inner nodes.
 | |
| balanceType, 
 | |
| // The direct children and their positions
 | |
| children, positions, 
 | |
| // The index range in children/positions to use
 | |
| from, to, 
 | |
| // The start position of the nodes, relative to their parent.
 | |
| start, 
 | |
| // Length of the outer node
 | |
| length, 
 | |
| // Function to build the top node of the balanced tree
 | |
| mkTop, 
 | |
| // Function to build internal nodes for the balanced tree
 | |
| mkTree) {
 | |
|     let total = 0;
 | |
|     for (let i = from; i < to; i++)
 | |
|         total += nodeSize(balanceType, children[i]);
 | |
|     let maxChild = Math.ceil((total * 1.5) / 8 /* Balance.BranchFactor */);
 | |
|     let localChildren = [], localPositions = [];
 | |
|     function divide(children, positions, from, to, offset) {
 | |
|         for (let i = from; i < to;) {
 | |
|             let groupFrom = i, groupStart = positions[i], groupSize = nodeSize(balanceType, children[i]);
 | |
|             i++;
 | |
|             for (; i < to; i++) {
 | |
|                 let nextSize = nodeSize(balanceType, children[i]);
 | |
|                 if (groupSize + nextSize >= maxChild)
 | |
|                     break;
 | |
|                 groupSize += nextSize;
 | |
|             }
 | |
|             if (i == groupFrom + 1) {
 | |
|                 if (groupSize > maxChild) {
 | |
|                     let only = children[groupFrom]; // Only trees can have a size > 1
 | |
|                     divide(only.children, only.positions, 0, only.children.length, positions[groupFrom] + offset);
 | |
|                     continue;
 | |
|                 }
 | |
|                 localChildren.push(children[groupFrom]);
 | |
|             }
 | |
|             else {
 | |
|                 let length = positions[i - 1] + children[i - 1].length - groupStart;
 | |
|                 localChildren.push(balanceRange(balanceType, children, positions, groupFrom, i, groupStart, length, null, mkTree));
 | |
|             }
 | |
|             localPositions.push(groupStart + offset - start);
 | |
|         }
 | |
|     }
 | |
|     divide(children, positions, from, to, 0);
 | |
|     return (mkTop || mkTree)(localChildren, localPositions, length);
 | |
| }
 | |
| /**
 | |
| Provides a way to associate values with pieces of trees. As long
 | |
| as that part of the tree is reused, the associated values can be
 | |
| retrieved from an updated tree.
 | |
| */
 | |
| class NodeWeakMap {
 | |
|     constructor() {
 | |
|         this.map = new WeakMap();
 | |
|     }
 | |
|     setBuffer(buffer, index, value) {
 | |
|         let inner = this.map.get(buffer);
 | |
|         if (!inner)
 | |
|             this.map.set(buffer, inner = new Map);
 | |
|         inner.set(index, value);
 | |
|     }
 | |
|     getBuffer(buffer, index) {
 | |
|         let inner = this.map.get(buffer);
 | |
|         return inner && inner.get(index);
 | |
|     }
 | |
|     /**
 | |
|     Set the value for this syntax node.
 | |
|     */
 | |
|     set(node, value) {
 | |
|         if (node instanceof BufferNode)
 | |
|             this.setBuffer(node.context.buffer, node.index, value);
 | |
|         else if (node instanceof TreeNode)
 | |
|             this.map.set(node.tree, value);
 | |
|     }
 | |
|     /**
 | |
|     Retrieve value for this syntax node, if it exists in the map.
 | |
|     */
 | |
|     get(node) {
 | |
|         return node instanceof BufferNode ? this.getBuffer(node.context.buffer, node.index)
 | |
|             : node instanceof TreeNode ? this.map.get(node.tree) : undefined;
 | |
|     }
 | |
|     /**
 | |
|     Set the value for the node that a cursor currently points to.
 | |
|     */
 | |
|     cursorSet(cursor, value) {
 | |
|         if (cursor.buffer)
 | |
|             this.setBuffer(cursor.buffer.buffer, cursor.index, value);
 | |
|         else
 | |
|             this.map.set(cursor.tree, value);
 | |
|     }
 | |
|     /**
 | |
|     Retrieve the value for the node that a cursor currently points
 | |
|     to.
 | |
|     */
 | |
|     cursorGet(cursor) {
 | |
|         return cursor.buffer ? this.getBuffer(cursor.buffer.buffer, cursor.index) : this.map.get(cursor.tree);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
| Tree fragments are used during [incremental
 | |
| parsing](#common.Parser.startParse) to track parts of old trees
 | |
| that can be reused in a new parse. An array of fragments is used
 | |
| to track regions of an old tree whose nodes might be reused in new
 | |
| parses. Use the static
 | |
| [`applyChanges`](#common.TreeFragment^applyChanges) method to
 | |
| update fragments for document changes.
 | |
| */
 | |
| class TreeFragment {
 | |
|     /**
 | |
|     Construct a tree fragment. You'll usually want to use
 | |
|     [`addTree`](#common.TreeFragment^addTree) and
 | |
|     [`applyChanges`](#common.TreeFragment^applyChanges) instead of
 | |
|     calling this directly.
 | |
|     */
 | |
|     constructor(
 | |
|     /**
 | |
|     The start of the unchanged range pointed to by this fragment.
 | |
|     This refers to an offset in the _updated_ document (as opposed
 | |
|     to the original tree).
 | |
|     */
 | |
|     from, 
 | |
|     /**
 | |
|     The end of the unchanged range.
 | |
|     */
 | |
|     to, 
 | |
|     /**
 | |
|     The tree that this fragment is based on.
 | |
|     */
 | |
|     tree, 
 | |
|     /**
 | |
|     The offset between the fragment's tree and the document that
 | |
|     this fragment can be used against. Add this when going from
 | |
|     document to tree positions, subtract it to go from tree to
 | |
|     document positions.
 | |
|     */
 | |
|     offset, openStart = false, openEnd = false) {
 | |
|         this.from = from;
 | |
|         this.to = to;
 | |
|         this.tree = tree;
 | |
|         this.offset = offset;
 | |
|         this.open = (openStart ? 1 /* Open.Start */ : 0) | (openEnd ? 2 /* Open.End */ : 0);
 | |
|     }
 | |
|     /**
 | |
|     Whether the start of the fragment represents the start of a
 | |
|     parse, or the end of a change. (In the second case, it may not
 | |
|     be safe to reuse some nodes at the start, depending on the
 | |
|     parsing algorithm.)
 | |
|     */
 | |
|     get openStart() { return (this.open & 1 /* Open.Start */) > 0; }
 | |
|     /**
 | |
|     Whether the end of the fragment represents the end of a
 | |
|     full-document parse, or the start of a change.
 | |
|     */
 | |
|     get openEnd() { return (this.open & 2 /* Open.End */) > 0; }
 | |
|     /**
 | |
|     Create a set of fragments from a freshly parsed tree, or update
 | |
|     an existing set of fragments by replacing the ones that overlap
 | |
|     with a tree with content from the new tree. When `partial` is
 | |
|     true, the parse is treated as incomplete, and the resulting
 | |
|     fragment has [`openEnd`](#common.TreeFragment.openEnd) set to
 | |
|     true.
 | |
|     */
 | |
|     static addTree(tree, fragments = [], partial = false) {
 | |
|         let result = [new TreeFragment(0, tree.length, tree, 0, false, partial)];
 | |
|         for (let f of fragments)
 | |
|             if (f.to > tree.length)
 | |
|                 result.push(f);
 | |
|         return result;
 | |
|     }
 | |
|     /**
 | |
|     Apply a set of edits to an array of fragments, removing or
 | |
|     splitting fragments as necessary to remove edited ranges, and
 | |
|     adjusting offsets for fragments that moved.
 | |
|     */
 | |
|     static applyChanges(fragments, changes, minGap = 128) {
 | |
|         if (!changes.length)
 | |
|             return fragments;
 | |
|         let result = [];
 | |
|         let fI = 1, nextF = fragments.length ? fragments[0] : null;
 | |
|         for (let cI = 0, pos = 0, off = 0;; cI++) {
 | |
|             let nextC = cI < changes.length ? changes[cI] : null;
 | |
|             let nextPos = nextC ? nextC.fromA : 1e9;
 | |
|             if (nextPos - pos >= minGap)
 | |
|                 while (nextF && nextF.from < nextPos) {
 | |
|                     let cut = nextF;
 | |
|                     if (pos >= cut.from || nextPos <= cut.to || off) {
 | |
|                         let fFrom = Math.max(cut.from, pos) - off, fTo = Math.min(cut.to, nextPos) - off;
 | |
|                         cut = fFrom >= fTo ? null : new TreeFragment(fFrom, fTo, cut.tree, cut.offset + off, cI > 0, !!nextC);
 | |
|                     }
 | |
|                     if (cut)
 | |
|                         result.push(cut);
 | |
|                     if (nextF.to > nextPos)
 | |
|                         break;
 | |
|                     nextF = fI < fragments.length ? fragments[fI++] : null;
 | |
|                 }
 | |
|             if (!nextC)
 | |
|                 break;
 | |
|             pos = nextC.toA;
 | |
|             off = nextC.toA - nextC.toB;
 | |
|         }
 | |
|         return result;
 | |
|     }
 | |
| }
 | |
| /**
 | |
| A superclass that parsers should extend.
 | |
| */
 | |
| class Parser {
 | |
|     /**
 | |
|     Start a parse, returning a [partial parse](#common.PartialParse)
 | |
|     object. [`fragments`](#common.TreeFragment) can be passed in to
 | |
|     make the parse incremental.
 | |
|     
 | |
|     By default, the entire input is parsed. You can pass `ranges`,
 | |
|     which should be a sorted array of non-empty, non-overlapping
 | |
|     ranges, to parse only those ranges. The tree returned in that
 | |
|     case will start at `ranges[0].from`.
 | |
|     */
 | |
|     startParse(input, fragments, ranges) {
 | |
|         if (typeof input == "string")
 | |
|             input = new StringInput(input);
 | |
|         ranges = !ranges ? [new Range(0, input.length)] : ranges.length ? ranges.map(r => new Range(r.from, r.to)) : [new Range(0, 0)];
 | |
|         return this.createParse(input, fragments || [], ranges);
 | |
|     }
 | |
|     /**
 | |
|     Run a full parse, returning the resulting tree.
 | |
|     */
 | |
|     parse(input, fragments, ranges) {
 | |
|         let parse = this.startParse(input, fragments, ranges);
 | |
|         for (;;) {
 | |
|             let done = parse.advance();
 | |
|             if (done)
 | |
|                 return done;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| class StringInput {
 | |
|     constructor(string) {
 | |
|         this.string = string;
 | |
|     }
 | |
|     get length() { return this.string.length; }
 | |
|     chunk(from) { return this.string.slice(from); }
 | |
|     get lineChunks() { return false; }
 | |
|     read(from, to) { return this.string.slice(from, to); }
 | |
| }
 | |
| 
 | |
| /**
 | |
| Create a parse wrapper that, after the inner parse completes,
 | |
| scans its tree for mixed language regions with the `nest`
 | |
| function, runs the resulting [inner parses](#common.NestedParse),
 | |
| and then [mounts](#common.NodeProp^mounted) their results onto the
 | |
| tree.
 | |
| */
 | |
| function parseMixed(nest) {
 | |
|     return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges);
 | |
| }
 | |
| class InnerParse {
 | |
|     constructor(parser, parse, overlay, target, from) {
 | |
|         this.parser = parser;
 | |
|         this.parse = parse;
 | |
|         this.overlay = overlay;
 | |
|         this.target = target;
 | |
|         this.from = from;
 | |
|     }
 | |
| }
 | |
| function checkRanges(ranges) {
 | |
|     if (!ranges.length || ranges.some(r => r.from >= r.to))
 | |
|         throw new RangeError("Invalid inner parse ranges given: " + JSON.stringify(ranges));
 | |
| }
 | |
| class ActiveOverlay {
 | |
|     constructor(parser, predicate, mounts, index, start, target, prev) {
 | |
|         this.parser = parser;
 | |
|         this.predicate = predicate;
 | |
|         this.mounts = mounts;
 | |
|         this.index = index;
 | |
|         this.start = start;
 | |
|         this.target = target;
 | |
|         this.prev = prev;
 | |
|         this.depth = 0;
 | |
|         this.ranges = [];
 | |
|     }
 | |
| }
 | |
| const stoppedInner = new NodeProp({ perNode: true });
 | |
| class MixedParse {
 | |
|     constructor(base, nest, input, fragments, ranges) {
 | |
|         this.nest = nest;
 | |
|         this.input = input;
 | |
|         this.fragments = fragments;
 | |
|         this.ranges = ranges;
 | |
|         this.inner = [];
 | |
|         this.innerDone = 0;
 | |
|         this.baseTree = null;
 | |
|         this.stoppedAt = null;
 | |
|         this.baseParse = base;
 | |
|     }
 | |
|     advance() {
 | |
|         if (this.baseParse) {
 | |
|             let done = this.baseParse.advance();
 | |
|             if (!done)
 | |
|                 return null;
 | |
|             this.baseParse = null;
 | |
|             this.baseTree = done;
 | |
|             this.startInner();
 | |
|             if (this.stoppedAt != null)
 | |
|                 for (let inner of this.inner)
 | |
|                     inner.parse.stopAt(this.stoppedAt);
 | |
|         }
 | |
|         if (this.innerDone == this.inner.length) {
 | |
|             let result = this.baseTree;
 | |
|             if (this.stoppedAt != null)
 | |
|                 result = new Tree(result.type, result.children, result.positions, result.length, result.propValues.concat([[stoppedInner, this.stoppedAt]]));
 | |
|             return result;
 | |
|         }
 | |
|         let inner = this.inner[this.innerDone], done = inner.parse.advance();
 | |
|         if (done) {
 | |
|             this.innerDone++;
 | |
|             // This is a somewhat dodgy but super helpful hack where we
 | |
|             // patch up nodes created by the inner parse (and thus
 | |
|             // presumably not aliased anywhere else) to hold the information
 | |
|             // about the inner parse.
 | |
|             let props = Object.assign(Object.create(null), inner.target.props);
 | |
|             props[NodeProp.mounted.id] = new MountedTree(done, inner.overlay, inner.parser);
 | |
|             inner.target.props = props;
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
|     get parsedPos() {
 | |
|         if (this.baseParse)
 | |
|             return 0;
 | |
|         let pos = this.input.length;
 | |
|         for (let i = this.innerDone; i < this.inner.length; i++) {
 | |
|             if (this.inner[i].from < pos)
 | |
|                 pos = Math.min(pos, this.inner[i].parse.parsedPos);
 | |
|         }
 | |
|         return pos;
 | |
|     }
 | |
|     stopAt(pos) {
 | |
|         this.stoppedAt = pos;
 | |
|         if (this.baseParse)
 | |
|             this.baseParse.stopAt(pos);
 | |
|         else
 | |
|             for (let i = this.innerDone; i < this.inner.length; i++)
 | |
|                 this.inner[i].parse.stopAt(pos);
 | |
|     }
 | |
|     startInner() {
 | |
|         let fragmentCursor = new FragmentCursor(this.fragments);
 | |
|         let overlay = null;
 | |
|         let covered = null;
 | |
|         let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), IterMode.IncludeAnonymous | IterMode.IgnoreMounts);
 | |
|         scan: for (let nest, isCovered;;) {
 | |
|             let enter = true, range;
 | |
|             if (this.stoppedAt != null && cursor.from >= this.stoppedAt) {
 | |
|                 enter = false;
 | |
|             }
 | |
|             else if (fragmentCursor.hasNode(cursor)) {
 | |
|                 if (overlay) {
 | |
|                     let match = overlay.mounts.find(m => m.frag.from <= cursor.from && m.frag.to >= cursor.to && m.mount.overlay);
 | |
|                     if (match)
 | |
|                         for (let r of match.mount.overlay) {
 | |
|                             let from = r.from + match.pos, to = r.to + match.pos;
 | |
|                             if (from >= cursor.from && to <= cursor.to && !overlay.ranges.some(r => r.from < to && r.to > from))
 | |
|                                 overlay.ranges.push({ from, to });
 | |
|                         }
 | |
|                 }
 | |
|                 enter = false;
 | |
|             }
 | |
|             else if (covered && (isCovered = checkCover(covered.ranges, cursor.from, cursor.to))) {
 | |
|                 enter = isCovered != 2 /* Cover.Full */;
 | |
|             }
 | |
|             else if (!cursor.type.isAnonymous && (nest = this.nest(cursor, this.input)) &&
 | |
|                 (cursor.from < cursor.to || !nest.overlay)) {
 | |
|                 if (!cursor.tree)
 | |
|                     materialize(cursor);
 | |
|                 let oldMounts = fragmentCursor.findMounts(cursor.from, nest.parser);
 | |
|                 if (typeof nest.overlay == "function") {
 | |
|                     overlay = new ActiveOverlay(nest.parser, nest.overlay, oldMounts, this.inner.length, cursor.from, cursor.tree, overlay);
 | |
|                 }
 | |
|                 else {
 | |
|                     let ranges = punchRanges(this.ranges, nest.overlay ||
 | |
|                         (cursor.from < cursor.to ? [new Range(cursor.from, cursor.to)] : []));
 | |
|                     if (ranges.length)
 | |
|                         checkRanges(ranges);
 | |
|                     if (ranges.length || !nest.overlay)
 | |
|                         this.inner.push(new InnerParse(nest.parser, ranges.length ? nest.parser.startParse(this.input, enterFragments(oldMounts, ranges), ranges)
 | |
|                             : nest.parser.startParse(""), nest.overlay ? nest.overlay.map(r => new Range(r.from - cursor.from, r.to - cursor.from)) : null, cursor.tree, ranges.length ? ranges[0].from : cursor.from));
 | |
|                     if (!nest.overlay)
 | |
|                         enter = false;
 | |
|                     else if (ranges.length)
 | |
|                         covered = { ranges, depth: 0, prev: covered };
 | |
|                 }
 | |
|             }
 | |
|             else if (overlay && (range = overlay.predicate(cursor))) {
 | |
|                 if (range === true)
 | |
|                     range = new Range(cursor.from, cursor.to);
 | |
|                 if (range.from < range.to)
 | |
|                     overlay.ranges.push(range);
 | |
|             }
 | |
|             if (enter && cursor.firstChild()) {
 | |
|                 if (overlay)
 | |
|                     overlay.depth++;
 | |
|                 if (covered)
 | |
|                     covered.depth++;
 | |
|             }
 | |
|             else {
 | |
|                 for (;;) {
 | |
|                     if (cursor.nextSibling())
 | |
|                         break;
 | |
|                     if (!cursor.parent())
 | |
|                         break scan;
 | |
|                     if (overlay && !--overlay.depth) {
 | |
|                         let ranges = punchRanges(this.ranges, overlay.ranges);
 | |
|                         if (ranges.length) {
 | |
|                             checkRanges(ranges);
 | |
|                             this.inner.splice(overlay.index, 0, new InnerParse(overlay.parser, overlay.parser.startParse(this.input, enterFragments(overlay.mounts, ranges), ranges), overlay.ranges.map(r => new Range(r.from - overlay.start, r.to - overlay.start)), overlay.target, ranges[0].from));
 | |
|                         }
 | |
|                         overlay = overlay.prev;
 | |
|                     }
 | |
|                     if (covered && !--covered.depth)
 | |
|                         covered = covered.prev;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| function checkCover(covered, from, to) {
 | |
|     for (let range of covered) {
 | |
|         if (range.from >= to)
 | |
|             break;
 | |
|         if (range.to > from)
 | |
|             return range.from <= from && range.to >= to ? 2 /* Cover.Full */ : 1 /* Cover.Partial */;
 | |
|     }
 | |
|     return 0 /* Cover.None */;
 | |
| }
 | |
| // Take a piece of buffer and convert it into a stand-alone
 | |
| // TreeBuffer.
 | |
| function sliceBuf(buf, startI, endI, nodes, positions, off) {
 | |
|     if (startI < endI) {
 | |
|         let from = buf.buffer[startI + 1];
 | |
|         nodes.push(buf.slice(startI, endI, from));
 | |
|         positions.push(from - off);
 | |
|     }
 | |
| }
 | |
| // This function takes a node that's in a buffer, and converts it, and
 | |
| // its parent buffer nodes, into a Tree. This is again acting on the
 | |
| // assumption that the trees and buffers have been constructed by the
 | |
| // parse that was ran via the mix parser, and thus aren't shared with
 | |
| // any other code, making violations of the immutability safe.
 | |
| function materialize(cursor) {
 | |
|     let { node } = cursor, stack = [];
 | |
|     let buffer = node.context.buffer;
 | |
|     // Scan up to the nearest tree
 | |
|     do {
 | |
|         stack.push(cursor.index);
 | |
|         cursor.parent();
 | |
|     } while (!cursor.tree);
 | |
|     // Find the index of the buffer in that tree
 | |
|     let base = cursor.tree, i = base.children.indexOf(buffer);
 | |
|     let buf = base.children[i], b = buf.buffer, newStack = [i];
 | |
|     // Split a level in the buffer, putting the nodes before and after
 | |
|     // the child that contains `node` into new buffers.
 | |
|     function split(startI, endI, type, innerOffset, length, stackPos) {
 | |
|         let targetI = stack[stackPos];
 | |
|         let children = [], positions = [];
 | |
|         sliceBuf(buf, startI, targetI, children, positions, innerOffset);
 | |
|         let from = b[targetI + 1], to = b[targetI + 2];
 | |
|         newStack.push(children.length);
 | |
|         let child = stackPos
 | |
|             ? split(targetI + 4, b[targetI + 3], buf.set.types[b[targetI]], from, to - from, stackPos - 1)
 | |
|             : node.toTree();
 | |
|         children.push(child);
 | |
|         positions.push(from - innerOffset);
 | |
|         sliceBuf(buf, b[targetI + 3], endI, children, positions, innerOffset);
 | |
|         return new Tree(type, children, positions, length);
 | |
|     }
 | |
|     base.children[i] = split(0, b.length, NodeType.none, 0, buf.length, stack.length - 1);
 | |
|     // Move the cursor back to the target node
 | |
|     for (let index of newStack) {
 | |
|         let tree = cursor.tree.children[index], pos = cursor.tree.positions[index];
 | |
|         cursor.yield(new TreeNode(tree, pos + cursor.from, index, cursor._tree));
 | |
|     }
 | |
| }
 | |
| class StructureCursor {
 | |
|     constructor(root, offset) {
 | |
|         this.offset = offset;
 | |
|         this.done = false;
 | |
|         this.cursor = root.cursor(IterMode.IncludeAnonymous | IterMode.IgnoreMounts);
 | |
|     }
 | |
|     // Move to the first node (in pre-order) that starts at or after `pos`.
 | |
|     moveTo(pos) {
 | |
|         let { cursor } = this, p = pos - this.offset;
 | |
|         while (!this.done && cursor.from < p) {
 | |
|             if (cursor.to >= pos && cursor.enter(p, 1, IterMode.IgnoreOverlays | IterMode.ExcludeBuffers)) ;
 | |
|             else if (!cursor.next(false))
 | |
|                 this.done = true;
 | |
|         }
 | |
|     }
 | |
|     hasNode(cursor) {
 | |
|         this.moveTo(cursor.from);
 | |
|         if (!this.done && this.cursor.from + this.offset == cursor.from && this.cursor.tree) {
 | |
|             for (let tree = this.cursor.tree;;) {
 | |
|                 if (tree == cursor.tree)
 | |
|                     return true;
 | |
|                 if (tree.children.length && tree.positions[0] == 0 && tree.children[0] instanceof Tree)
 | |
|                     tree = tree.children[0];
 | |
|                 else
 | |
|                     break;
 | |
|             }
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| }
 | |
| class FragmentCursor {
 | |
|     constructor(fragments) {
 | |
|         var _a;
 | |
|         this.fragments = fragments;
 | |
|         this.curTo = 0;
 | |
|         this.fragI = 0;
 | |
|         if (fragments.length) {
 | |
|             let first = this.curFrag = fragments[0];
 | |
|             this.curTo = (_a = first.tree.prop(stoppedInner)) !== null && _a !== void 0 ? _a : first.to;
 | |
|             this.inner = new StructureCursor(first.tree, -first.offset);
 | |
|         }
 | |
|         else {
 | |
|             this.curFrag = this.inner = null;
 | |
|         }
 | |
|     }
 | |
|     hasNode(node) {
 | |
|         while (this.curFrag && node.from >= this.curTo)
 | |
|             this.nextFrag();
 | |
|         return this.curFrag && this.curFrag.from <= node.from && this.curTo >= node.to && this.inner.hasNode(node);
 | |
|     }
 | |
|     nextFrag() {
 | |
|         var _a;
 | |
|         this.fragI++;
 | |
|         if (this.fragI == this.fragments.length) {
 | |
|             this.curFrag = this.inner = null;
 | |
|         }
 | |
|         else {
 | |
|             let frag = this.curFrag = this.fragments[this.fragI];
 | |
|             this.curTo = (_a = frag.tree.prop(stoppedInner)) !== null && _a !== void 0 ? _a : frag.to;
 | |
|             this.inner = new StructureCursor(frag.tree, -frag.offset);
 | |
|         }
 | |
|     }
 | |
|     findMounts(pos, parser) {
 | |
|         var _a;
 | |
|         let result = [];
 | |
|         if (this.inner) {
 | |
|             this.inner.cursor.moveTo(pos, 1);
 | |
|             for (let pos = this.inner.cursor.node; pos; pos = pos.parent) {
 | |
|                 let mount = (_a = pos.tree) === null || _a === void 0 ? void 0 : _a.prop(NodeProp.mounted);
 | |
|                 if (mount && mount.parser == parser) {
 | |
|                     for (let i = this.fragI; i < this.fragments.length; i++) {
 | |
|                         let frag = this.fragments[i];
 | |
|                         if (frag.from >= pos.to)
 | |
|                             break;
 | |
|                         if (frag.tree == this.curFrag.tree)
 | |
|                             result.push({
 | |
|                                 frag,
 | |
|                                 pos: pos.from - frag.offset,
 | |
|                                 mount
 | |
|                             });
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return result;
 | |
|     }
 | |
| }
 | |
| function punchRanges(outer, ranges) {
 | |
|     let copy = null, current = ranges;
 | |
|     for (let i = 1, j = 0; i < outer.length; i++) {
 | |
|         let gapFrom = outer[i - 1].to, gapTo = outer[i].from;
 | |
|         for (; j < current.length; j++) {
 | |
|             let r = current[j];
 | |
|             if (r.from >= gapTo)
 | |
|                 break;
 | |
|             if (r.to <= gapFrom)
 | |
|                 continue;
 | |
|             if (!copy)
 | |
|                 current = copy = ranges.slice();
 | |
|             if (r.from < gapFrom) {
 | |
|                 copy[j] = new Range(r.from, gapFrom);
 | |
|                 if (r.to > gapTo)
 | |
|                     copy.splice(j + 1, 0, new Range(gapTo, r.to));
 | |
|             }
 | |
|             else if (r.to > gapTo) {
 | |
|                 copy[j--] = new Range(gapTo, r.to);
 | |
|             }
 | |
|             else {
 | |
|                 copy.splice(j--, 1);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return current;
 | |
| }
 | |
| function findCoverChanges(a, b, from, to) {
 | |
|     let iA = 0, iB = 0, inA = false, inB = false, pos = -1e9;
 | |
|     let result = [];
 | |
|     for (;;) {
 | |
|         let nextA = iA == a.length ? 1e9 : inA ? a[iA].to : a[iA].from;
 | |
|         let nextB = iB == b.length ? 1e9 : inB ? b[iB].to : b[iB].from;
 | |
|         if (inA != inB) {
 | |
|             let start = Math.max(pos, from), end = Math.min(nextA, nextB, to);
 | |
|             if (start < end)
 | |
|                 result.push(new Range(start, end));
 | |
|         }
 | |
|         pos = Math.min(nextA, nextB);
 | |
|         if (pos == 1e9)
 | |
|             break;
 | |
|         if (nextA == pos) {
 | |
|             if (!inA)
 | |
|                 inA = true;
 | |
|             else {
 | |
|                 inA = false;
 | |
|                 iA++;
 | |
|             }
 | |
|         }
 | |
|         if (nextB == pos) {
 | |
|             if (!inB)
 | |
|                 inB = true;
 | |
|             else {
 | |
|                 inB = false;
 | |
|                 iB++;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return result;
 | |
| }
 | |
| // Given a number of fragments for the outer tree, and a set of ranges
 | |
| // to parse, find fragments for inner trees mounted around those
 | |
| // ranges, if any.
 | |
| function enterFragments(mounts, ranges) {
 | |
|     let result = [];
 | |
|     for (let { pos, mount, frag } of mounts) {
 | |
|         let startPos = pos + (mount.overlay ? mount.overlay[0].from : 0), endPos = startPos + mount.tree.length;
 | |
|         let from = Math.max(frag.from, startPos), to = Math.min(frag.to, endPos);
 | |
|         if (mount.overlay) {
 | |
|             let overlay = mount.overlay.map(r => new Range(r.from + pos, r.to + pos));
 | |
|             let changes = findCoverChanges(ranges, overlay, from, to);
 | |
|             for (let i = 0, pos = from;; i++) {
 | |
|                 let last = i == changes.length, end = last ? to : changes[i].from;
 | |
|                 if (end > pos)
 | |
|                     result.push(new TreeFragment(pos, end, mount.tree, -startPos, frag.from >= pos || frag.openStart, frag.to <= end || frag.openEnd));
 | |
|                 if (last)
 | |
|                     break;
 | |
|                 pos = changes[i].to;
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             result.push(new TreeFragment(from, to, mount.tree, -startPos, frag.from >= startPos || frag.openStart, frag.to <= endPos || frag.openEnd));
 | |
|         }
 | |
|     }
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /***/ })
 | |
| 
 | |
| }]);
 | |
| //# sourceMappingURL=7997.1469ff294f8b64fd26ec.js.map?v=1469ff294f8b64fd26ec
 |