PageSourceSearch

https://econmentoring.org/wp-content/plugins/oxyextras/components/assets/inert.js?ver=1.0.0

js econmentoring.org collected 2026-09-24 11:48:22 UTC 27,344 bytes, 739 lines download raw bytes

1/**
2 * This work is licensed under the W3C Software and Document License
3 * (http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document).
4 */
5
6 (function() {
7    // Return early if we're not running inside of the browser.
8    if (typeof window === 'undefined') {
9      return;
10    }
11  
12    // Convenience function for converting NodeLists.
13    /** @type {typeof Array.prototype.slice} */
14    const slice = Array.prototype.slice;
15  
16    /**
17     * IE has a non-standard name for "matches".
18     * @type {typeof Element.prototype.matches}
19     */
20    const matches =
21        Element.prototype.matches || Element.prototype.msMatchesSelector;
22  
23    /** @type {string} */
24    const _focusableElementsString = ['a[href]',
25                                      'area[href]',
26                                      'input:not([disabled])',
27                                      'select:not([disabled])',
28                                      'textarea:not([disabled])',
29                                      'button:not([disabled])',
30                                      'details',
31                                      'summary',
32                                      'iframe',
33                                      'object',
34                                      'embed',
35                                      '[contenteditable]'].join(',');
36  
37    /**
38     * `InertRoot` manages a single inert subtree, i.e. a DOM subtree whose root element has an `inert`
39     * attribute.
40     *
41     * Its main functions are:
42     *
43     * - to create and maintain a set of managed `InertNode`s, including when mutations occur in the
44     *   subtree. The `makeSubtreeUnfocusable()` method handles collecting `InertNode`s via registering
45     *   each focusable node in the subtree with the singleton `InertManager` which manages all known
46     *   focusable nodes within inert subtrees. `InertManager` ensures that a single `InertNode`
47     *   instance exists for each focusable node which has at least one inert root as an ancestor.
48     *
49     * - to notify all managed `InertNode`s when this subtree stops being inert (i.e. when the `inert`
50     *   attribute is removed from the root node). This is handled in the destructor, which calls the
51     *   `deregister` method on `InertManager` for each managed inert node.
52     */
53    class InertRoot {
54      /**
55       * @param {!Element} rootElement The Element at the root of the inert subtree.
56       * @param {!InertManager} inertManager The global singleton InertManager object.
57       */
58      constructor(rootElement, inertManager) {
59        /** @type {!InertManager} */
60        this._inertManager = inertManager;
61  
62        /** @type {!Element} */
63        this._rootElement = rootElement;
64  
65        /**
66         * @type {!Set<!InertNode>}
67         * All managed focusable nodes in this InertRoot's subtree.
68         */
69        this._managedNodes = new Set();
70  
71        // Make the subtree hidden from assistive technology
72        if (this._rootElement.hasAttribute('aria-hidden')) {
73          /** @type {?string} */
74          this._savedAriaHidden = this._rootElement.getAttribute('aria-hidden');
75        } else {
76          this._savedAriaHidden = null;
77        }
78        this._rootElement.setAttribute('aria-hidden', 'true');
79  
80        // Make all focusable elements in the subtree unfocusable and add them to _managedNodes
81        this._makeSubtreeUnfocusable(this._rootElement);
82  
83        // Watch for:
84        // - any additions in the subtree: make them unfocusable too
85        // - any removals from the subtree: remove them from this inert root's managed nodes
86        // - attribute changes: if `tabindex` is added, or removed from an intrinsically focusable
87        //   element, make that node a managed node.
88        this._observer = new MutationObserver(this._onMutation.bind(this));
89        this._observer.observe(this._rootElement, {attributes: true, childList: true, subtree: true});
90      }
91  
92      /**
93       * Call this whenever this object is about to become obsolete.  This unwinds all of the state
94       * stored in this object and updates the state of all of the managed nodes.
95       */
96      destructor() {
97        this._observer.disconnect();
98  
99        if (this._rootElement) {
100          if (this._savedAriaHidden !== null) {
101            this._rootElement.setAttribute('aria-hidden', this._savedAriaHidden);
102          } else {
103            this._rootElement.removeAttribute('aria-hidden');
104          }
105        }
106  
107        this._managedNodes.forEach(function(inertNode) {
108          this._unmanageNode(inertNode.node);
109        }, this);
110  
111        // Note we cast the nulls to the ANY type here because:
112        // 1) We want the class properties to be declared as non-null, or else we
113        //    need even more casts throughout this code. All bets are off if an
114        //    instance has been destroyed and a method is called.
115        // 2) We don't want to cast "this", because we want type-aware optimizations
116        //    to know which properties we're setting.
117        this._observer = /** @type {?} */ (null);
118        this._rootElement = /** @type {?} */ (null);
119        this._managedNodes = /** @type {?} */ (null);
120        this._inertManager = /** @type {?} */ (null);
121      }
122  
123      /**
124       * @return {!Set<!InertNode>} A copy of this InertRoot's managed nodes set.
125       */
126      get managedNodes() {
127        return new Set(this._managedNodes);
128      }
129  
130      /** @return {boolean} */
131      get hasSavedAriaHidden() {
132        return this._savedAriaHidden !== null;
133      }
134  
135      /** @param {?string} ariaHidden */
136      set savedAriaHidden(ariaHidden) {
137        this._savedAriaHidden = ariaHidden;
138      }
139  
140      /** @return {?string} */
141      get savedAriaHidden() {
142        return this._savedAriaHidden;
143      }
144  
145      /**
146       * @param {!Node} startNode
147       */
148      _makeSubtreeUnfocusable(startNode) {
149        composedTreeWalk(startNode, (node) => this._visitNode(node));
150  
151        let activeElement = document.activeElement;
152  
153        if (!document.body.contains(startNode)) {
154          // startNode may be in shadow DOM, so find its nearest shadowRoot to get the activeElement.
155          let node = startNode;
156          /** @type {!ShadowRoot|undefined} */
157          let root = undefined;
158          while (node) {
159            if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
160              root = /** @type {!ShadowRoot} */ (node);
161              break;
162            }
163            node = node.parentNode;
164          }
165          if (root) {
166            activeElement = root.activeElement;
167          }
168        }
169        if (startNode.contains(activeElement)) {
170          activeElement.blur();
171          // In IE11, if an element is already focused, and then set to tabindex=-1
172          // calling blur() will not actually move the focus.
173          // To work around this we call focus() on the body instead.
174          if (activeElement === document.activeElement) {
175            document.body.focus();
176          }
177        }
178      }
179  
180      /**
181       * @param {!Node} node
182       */
183      _visitNode(node) {
184        if (node.nodeType !== Node.ELEMENT_NODE) {
185          return;
186        }
187        const element = /** @type {!Element} */ (node);
188  
189        // If a descendant inert root becomes un-inert, its descendants will still be inert because of
190        // this inert root, so all of its managed nodes need to be adopted by this InertRoot.
191        if (element !== this._rootElement && element.hasAttribute('inert')) {
192          this._adoptInertRoot(element);
193        }
194  
195        if (matches.call(element, _focusableElementsString) || element.hasAttribute('tabindex')) {
196          this._manageNode(element);
197        }
198      }
199  
200      /**
201       * Register the given node with this InertRoot and with InertManager.
202       * @param {!Node} node
203       */
204      _manageNode(node) {
205        const inertNode = this._inertManager.register(node, this);
206        this._managedNodes.add(inertNode);
207      }
208  
209      /**
210       * Unregister the given node with this InertRoot and with InertManager.
211       * @param {!Node} node
212       */
213      _unmanageNode(node) {
214        const inertNode = this._inertManager.deregister(node, this);
215        if (inertNode) {
216          this._managedNodes.delete(inertNode);
217        }
218      }
219  
220      /**
221       * Unregister the entire subtree starting at `startNode`.
222       * @param {!Node} startNode
223       */
224      _unmanageSubtree(startNode) {
225        composedTreeWalk(startNode, (node) => this._unmanageNode(node));
226      }
227  
228      /**
229       * If a descendant node is found with an `inert` attribute, adopt its managed nodes.
230       * @param {!Element} node
231       */
232      _adoptInertRoot(node) {
233        let inertSubroot = this._inertManager.getInertRoot(node);
234  
235        // During initialisation this inert root may not have been registered yet,
236        // so register it now if need be.
237        if (!inertSubroot) {
238          this._inertManager.setInert(node, true);
239          inertSubroot = this._inertManager.getInertRoot(node);
240        }
241  
242        inertSubroot.managedNodes.forEach(function(savedInertNode) {
243          this._manageNode(savedInertNode.node);
244        }, this);
245      }
246  
247      /**
248       * Callback used when mutation observer detects subtree additions, removals, or attribute changes.
249       * @param {!Array<!MutationRecord>} records
250       * @param {!MutationObserver} self
251       */
252      _onMutation(records, self) {
253        records.forEach(function(record) {
vendor: 2,097 bytes, lines 254-297
254          const target = /** @type {!Element} */ (record.target);
255          if (record.type === 'childList') {
256            // Manage added nodes
257            slice.call(record.addedNodes).forEach(function(node) {
258              this._makeSubtreeUnfocusable(node);
259            }, this);
260  
261            // Un-manage removed nodes
262            slice.call(record.removedNodes).forEach(function(node) {
263              this._unmanageSubtree(node);
264            }, this);
265          } else if (record.type === 'attributes') {
266            if (record.attributeName === 'tabindex') {
267              // Re-initialise inert node if tabindex changes
268              this._manageNode(target);
269            } else if (target !== this._rootElement &&
270                      record.attributeName === 'inert' &&
271                      target.hasAttribute('inert')) {
272              // If a new inert root is added, adopt its managed nodes and make sure it knows about the
273              // already managed nodes from this inert subroot.
274              this._adoptInertRoot(target);
275              const inertSubroot = this._inertManager.getInertRoot(target);
276              this._managedNodes.forEach(function(managedNode) {
277                if (target.contains(managedNode.node)) {
278                  inertSubroot._manageNode(managedNode.node);
279                }
280              });
281            }
282          }
283        }, this);
284      }
285    }
286  
287    /**
288     * `InertNode` initialises and manages a single inert node.
289     * A node is inert if it is a descendant of one or more inert root elements.
290     *
291     * On construction, `InertNode` saves the existing `tabindex` value for the node, if any, and
292     * either removes the `tabindex` attribute or sets it to `-1`, depending on whether the element
293     * is intrinsically focusable or not.
294     *
295     * `InertNode` maintains a set of `InertRoot`s which are descendants of this `InertNode`. When an
296     * `InertRoot` is destroyed, and calls `InertManager.deregister()`, the `InertManager` notifies the
297     * `InertNode` via `removeInertRoot()`, which in turn destroys the `InertN
297ode` if no `InertRoot`s
298     * remain in the set. On destruction, `InertNode` reinstates the stored `tabindex` if one exists,
299     * or removes the `tabindex` attribute if the element is intrinsically focusable.
300     */
301    class InertNode {
302      /**
303       * @param {!Node} node A focusable element to be made inert.
304       * @param {!InertRoot} inertRoot The inert root element associated with this inert node.
305       */
306      constructor(node, inertRoot) {
307        /** @type {!Node} */
308        this._node = node;
309  
310        /** @type {boolean} */
311        this._overrodeFocusMethod = false;
312  
313        /**
314         * @type {!Set<!InertRoot>} The set of descendant inert roots.
315         *    If and only if this set becomes empty, this node is no longer inert.
316         */
317        this._inertRoots = new Set([inertRoot]);
318  
319        /** @type {?number} */
320        this._savedTabIndex = null;
321  
322        /** @type {boolean} */
323        this._destroyed = false;
324  
325        // Save any prior tabindex info and make this node untabbable
326        this.ensureUntabbable();
327      }
328  
329      /**
330       * Call this whenever this object is about to become obsolete.
331       * This makes the managed node focusable again and deletes all of the previously stored state.
332       */
333      destructor() {
334        this._throwIfDestroyed();
335  
336        if (this._node && this._node.nodeType === Node.ELEMENT_NODE) {
337          const element = /** @type {!Element} */ (this._node);
338          if (this._savedTabIndex !== null) {
339            element.setAttribute('tabindex', this._savedTabIndex);
340          } else {
341            element.removeAttribute('tabindex');
342          }
343  
344          // Use `delete` to restore native focus method.
345          if (this._overrodeFocusMethod) {
346            delete element.focus;
347          }
348        }
349  
350        // See note in InertRoot.destructor for why we cast these nulls to ANY.
351        this._node = /** @type {?} */ (null);
352        this._inertRoots = /** @type {?} */ (null);
353        this._destroyed = true;
354      }
355  
356      /**
357       * @type {boolean} Whether this object is obsolete because the managed node is no longer inert.
358       * If the object has been destroyed, any attempt to access it will cause an exception.
359       */
360      get destroyed() {
361        return /** @type {!InertNode} */ (this)._destroyed;
362      }
363  
364      /**
365       * Throw if user tries to access destroyed InertNode.
366       */
367      _throwIfDestroyed() {
368        if (this.destroyed) {
369          throw new Error('Trying to access destroyed InertNode');
370        }
371      }
372  
373      /** @return {boolean} */
374      get hasSavedTabIndex() {
375        return this._savedTabIndex !== null;
376      }
377  
378      /** @return {!Node} */
379      get node() {
380        this._throwIfDestroyed();
381        return this._node;
382      }
383  
384      /** @param {?number} tabIndex */
385      set savedTabIndex(tabIndex) {
386        this._throwIfDestroyed();
387        this._savedTabIndex = tabIndex;
388      }
389  
390      /** @return {?number} */
391      get savedTabIndex() {
392        this._throwIfDestroyed();
393        return this._savedTabIndex;
394      }
395  
396      /** Save the existing tabindex value and make the node untabbable and unfocusable */
397      ensureUntabbable() {
398        if (this.node.nodeType !== Node.ELEMENT_NODE) {
399          return;
400        }
401        const element = /** @type {!Element} */ (this.node);
402        if (matches.call(element, _focusableElementsString)) {
403          if (/** @type {!HTMLElement} */ (element).tabIndex === -1 &&
404              this.hasSavedTabIndex) {
405            return;
406          }
407  
408          if (element.hasAttribute('tabindex')) {
409            this._savedTabIndex = /** @type {!HTMLElement} */ (element).tabIndex;
410          }
411          element.setAttribute('tabindex', '-1');
412          if (element.nodeType === Node.ELEMENT_NODE) {
413            element.focus = function() {};
414            this._overrodeFocusMethod = true;
415          }
416        } else if (element.hasAttribute('tabindex')) {
417          this._savedTabIndex = /** @type {!HTMLElement} */ (element).tabIndex;
418          element.removeAttribute('tabindex');
419        }
420      }
421  
422      /**
423       * Add another inert root to this inert node's set of managing inert roots.
424       * @param {!InertRoot} inertRoot
425       */
426      addInertRoot(inertRoot) {
427        this._throwIfDestroyed();
428        this._inertRoots.add(inertRoot);
429      }
430  
431      /**
432       * Remove the given inert root from this inert node's set of managing inert roots.
433       * If the set of managing inert roots becomes empty, this node is no longer inert,
434       * so the object should be destroyed.
435       * @param {!InertRoot} inertRoot
436       */
437      removeInertRoot(inertRoot) {
438        this._throwIfDestroyed();
439        this._inertRoots.delete(inertRoot);
440        if (this._inertRoots.size === 0) {
441          this.destructor();
442        }
443      }
444    }
445  
446    /**
447     * InertManager is a per-document singleton object which manages all inert roots and nodes.
448     *
449     * When an element becomes an inert root by having an `inert` attribute set and/or its `inert`
450     * property set to `true`, the `setInert` method creates an `InertRoot` object for the element.
451     * The `InertRoot` in turn registers itself as managing all of the element's focusable descendant
452     * nodes via the `register()` method. The `InertManager` ensures that a single `InertNode` instance
453     * is created for each such node, via the `_managedNodes` map.
454     */
455    class InertManager {
456      /**
457       * @param {!Document} document
458       */
459      constructor(document) {
460        if (!document) {
461          throw new Error('Missing required argument; InertManager needs to wrap a document.');
462        }
463  
464        /** @type {!Document} */
465        this._document = document;
466  
467        /**
468         * All managed nodes known to this InertManager. In a map to allow looking up by Node.
469         * @type {!Map<!Node, !InertNode>}
470         */
471        this._managedNodes = new Map();
472  
473        /**
474         * All inert roots known to this InertManager. In a map to allow looking up by Node.
475         * @type {!Map<!Node, !InertRoot>}
476         */
477        this._inertRoots = new Map();
478  
479        /**
480         * Observer for mutations on `document.body`.
481         * @type {!MutationObserver}
482         */
483        this._observer = new MutationObserver(this._watchForInert.bind(this));
484  
485        // Add inert style.
486        addInertStyle(document.head || document.body || document.documentElement);
487  
488        // Wait for document to be loaded.
489        if (document.readyState === 'loading') {
490          document.addEventListener('DOMContentLoaded', this._onDocumentLoaded.bind(this));
491        } else {
492          this._onDocumentLoaded();
493        }
494      }
495  
496      /**
497       * Set whether the given element should be an inert root or not.
498       * @param {!Element} root
499       * @param {boolean} inert
500       */
501      setInert(root, inert) {
502        if (inert) {
503          if (this._inertRoots.has(root)) { // element is already inert
504            return;
505          }
506  
507          const inertRoot = new InertRoot(root, this);
508          root.setAttribute('inert', '');
509          this._inertRoots.set(root, inertRoot);
510          // If not contained in the document, it must be in a shadowRoot.
511          // Ensure inert styles are added there.
512          if (!this._document.body.contains(root)) {
513            let parent = root.parentNode;
514            while (parent) {
515              if (parent.nodeType === 11) {
516                addInertStyle(parent);
517              }
518              parent = parent.parentNode;
519            }
520          }
521        } else {
522          if (!this._inertRoots.has(root)) { // element is already non-inert
523            return;
524          }
525  
526          const inertRoot = this._inertRoots.get(root);
527          inertRoot.destructor();
528          this._inertRoots.delete(root);
529          root.removeAttribute('inert');
530        }
531      }
532  
533      /**
534       * Get the InertRoot object corresponding to the given inert root element, if any.
535       * @param {!Node} element
536       * @return {!InertRoot|undefined}
537       */
538      getInertRoot(element) {
539        return this._inertRoots.get(element);
540      }
541  
542      /**
543       * Register the given InertRoot as managing the given node.
544       * In the case where the node has a previously existing inert root, this inert root will
545       * be added to its set of inert roots.
546       * @param {!Node} node
547       * @param {!InertRoot} inertRoot
548       * @return {!InertNode} inertNode
549       */
550      register(node, inertRoot) {
551        let inertNode = this._managedNodes.get(node);
552        if (inertNode !== undefined) { // node was already in an inert subtree
553          inertNode.addInertRoot(inertRoot);
554        } else {
555          inertNode = new InertNode(node, inertRoot);
556        }
557  
558        this._managedNodes.set(node, inertNode);
559  
560        return inertNode;
561      }
562  
563      /**
564       * De-register the given InertRoot as managing the given inert node.
565       * Removes the inert root from the InertNode's set of managing inert roots, and remove the inert
566       * node from the InertManager's set of managed nodes if it is destroyed.
567       * If the node is not currently managed, this is essentially a no-op.
568       * @param {!Node} node
569       * @param {!InertRoot} inertRoot
570       * @return {?InertNode} The potentially destroyed InertNode associated with this node, if any.
571       */
572      deregister(node, inertRoot) {
573        const inertNode = this._managedNodes.get(node);
574        if (!inertNode) {
575          return null;
576        }
577  
578        inertNode.removeInertRoot(inertRoot);
579        if (inertNode.destroyed) {
580          this._managedNodes.delete(node);
581        }
582  
583        return inertNode;
584      }
585  
586      /**
587       * Callback used when document has finished loading.
588       */
589      _onDocumentLoaded() {
590        // Find all inert roots in document and make them actually inert.
591        const inertElements = slice.call(this._document.querySelectorAll('[inert]'));
592        inertElements.forEach(function(inertElement) {
593          this.setInert(inertElement, true);
594        }, this);
595  
596        // Comment this out to use programmatic API only.
597        this._observer.observe(this._document.body || this._document.documentElement, {attributes: true, subtree: true, childList: true});
598      }
599  
600      /**
601       * Callback used when mutation observer detects attribute changes.
602       * @param {!Array<!MutationRecord>} records
603       * @param {!MutationObserver} self
604       */
605      _watchForInert(records, self) {
606        const _this = this;
607        records.forEach(function(record) {
608          switch (record.type) {
609          case 'childList':
610            slice.call(record.addedNodes).forEach(function(node) {
611              if (node.nodeType !== Node.ELEMENT_NODE) {
612                return;
613              }
614              const inertElements = slice.call(node.querySelectorAll('[inert]'));
615              if (matches.call(node, '[inert]')) {
616                inertElements.unshift(node);
617              }
618              inertElements.forEach(function(inertElement) {
619                this.setInert(inertElement, true);
620              }, _this);
621            }, _this);
622            break;
623          case 'attributes':
624            if (record.attributeName !== 'inert') {
625              return;
626            }
627            const target = /** @type {!Element} */ (record.target);
628            const inert = target.hasAttribute('inert');
629            _this.setInert(target, inert);
630            break;
631          }
632        }, this);
633      }
634    }
635  
636    /**
637     * Recursively walk the composed tree from |node|.
638     * @param {!Node} node
639     * @param {(function (!Element))=} callback Callback to be called for each element traversed,
640     *     before descending into child nodes.
641     * @param {?ShadowRoot=} shadowRootAncestor The nearest ShadowRoot ancestor, if any.
642     */
643    function composedTreeWalk(node, callback, shadowRootAncestor) {
644      if (node.nodeType == Node.ELEMENT_NODE) {
645        const element = /** @type {!Element} */ (node);
646        if (callback) {
647          callback(element);
648        }
649  
650        // Descend into node:
651        // If it has a ShadowRoot, ignore all child elements - these will be picked
652        // up by the <content> or <shadow> elements. Descend straight into the
653        // ShadowRoot.
654        const shadowRoot = /** @type {
654!HTMLElement} */ (element).shadowRoot;
655        if (shadowRoot) {
656          composedTreeWalk(shadowRoot, callback, shadowRoot);
657          return;
658        }
659  
660        // If it is a <content> element, descend into distributed elements - these
661        // are elements from outside the shadow root which are rendered inside the
662        // shadow DOM.
663        if (element.localName == 'content') {
664          const content = /** @type {!HTMLContentElement} */ (element);
665          // Verifies if ShadowDom v0 is supported.
666          const distributedNodes = content.getDistributedNodes ?
667            content.getDistributedNodes() : [];
668          for (let i = 0; i < distributedNodes.length; i++) {
669            composedTreeWalk(distributedNodes[i], callback, shadowRootAncestor);
670          }
671          return;
672        }
673  
674        // If it is a <slot> element, descend into assigned nodes - these
675        // are elements from outside the shadow root which are rendered inside the
676        // shadow DOM.
677        if (element.localName == 'slot') {
678          const slot = /** @type {!HTMLSlotElement} */ (element);
679          // Verify if ShadowDom v1 is supported.
680          const distributedNodes = slot.assignedNodes ?
681            slot.assignedNodes({flatten: true}) : [];
682          for (let i = 0; i < distributedNodes.length; i++) {
683            composedTreeWalk(distributedNodes[i], callback, shadowRootAncestor);
684          }
685          return;
686        }
687      }
688  
689      // If it is neither the parent of a ShadowRoot, a <content> element, a <slot>
690      // element, nor a <shadow> element recurse normally.
691      let child = node.firstChild;
692      while (child != null) {
693        composedTreeWalk(child, callback, shadowRootAncestor);
694        child = child.nextSibling;
695      }
696    }
697  
698    /**
699     * Adds a style element to the node containing the inert specific styles
700     * @param {!Node} node
701     */
702    function addInertStyle(node) {
703      if (node.querySelector('style#inert-style, link#inert-style')) {
704        return;
705      }
706      const style = document.createElement('style');
707      style.setAttribute('id', 'inert-style');
708      style.textContent = '\n'+
709                          '[inert] {\n' +
710                          '  pointer-events: none;\n' +
711                          '  cursor: default;\n' +
712                          '}\n' +
713                          '\n' +
714                          '[inert], [inert] * {\n' +
715                          '  -webkit-user-select: none;\n' +
716                          '  -moz-user-select: none;\n' +
717                          '  -ms-user-select: none;\n' +
718                          '  user-select: none;\n' +
719                          '}\n';
720      node.appendChild(style);
721    }
722  
723    if (!Element.prototype.hasOwnProperty('inert')) {
724      /** @type {!InertManager} */
725      const inertManager = new InertManager(document);
726      
727      Object.defineProperty(Element.prototype, 'inert', {
728        enumerable: true,
729        /** @this {!Element} */
730        get: function() {
731          return this.hasAttribute('inert');
732        },
733        /** @this {!Element} */
734        set: function(inert) {
735          inertManager.setInert(this, inert);
736        },
737      });
738    }
739  })();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.