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.
		
		
		
		
		
			
		
			
				
	
	
		
			152 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			152 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
| import {DOCUMENT_FRAGMENT_NODE} from './shared/constants.js';
 | |
| import {defineProperties, getOwnPropertyDescriptors} from './shared/object.js';
 | |
| 
 | |
| import {Attr} from './interface/attr.js';
 | |
| import {CharacterData} from './interface/character-data.js';
 | |
| import {Element} from './interface/element.js';
 | |
| 
 | |
| import {ParentNode} from './mixin/parent-node.js';
 | |
| import {NonElementParentNode} from './mixin/non-element-parent-node.js';
 | |
| import {HTMLDocument} from './html/document.js';
 | |
| 
 | |
| import {
 | |
|   childNodesWM,
 | |
|   childrenWM,
 | |
|   querySelectorWM,
 | |
|   querySelectorAllWM,
 | |
|   get,
 | |
|   reset
 | |
| } from './shared/cache.js';
 | |
| 
 | |
| // Attr
 | |
| const {value: {
 | |
|   get: getAttributeValue,
 | |
|   set: setAttributeValue
 | |
| }} = getOwnPropertyDescriptors(Attr.prototype);
 | |
| 
 | |
| defineProperties(Attr.prototype, {
 | |
|   value: {
 | |
|     get: getAttributeValue,
 | |
|     set(value) {
 | |
|       reset(this.ownerElement);
 | |
|       setAttributeValue.call(this, value);
 | |
|     }
 | |
|   }
 | |
| });
 | |
| 
 | |
| 
 | |
| // CharacterData
 | |
| // TODO: is txtContent really necessary to patch here?
 | |
| const {remove: removeCharacterData} = CharacterData.prototype;
 | |
| defineProperties(CharacterData.prototype, {
 | |
|   remove: {value() {
 | |
|     reset(this.parentNode);
 | |
|     removeCharacterData.call(this);
 | |
|   }}
 | |
| });
 | |
| 
 | |
| 
 | |
| // Element
 | |
| const elementProtoDescriptors = {};
 | |
| for (const name of [
 | |
|   'remove',
 | |
|   'setAttribute',
 | |
|   'setAttributeNS',
 | |
|   'setAttributeNode',
 | |
|   'setAttributeNodeNS',
 | |
|   'removeAttribute',
 | |
|   'removeAttributeNS',
 | |
|   'removeAttributeNode'
 | |
| ]) {
 | |
|   const method = Element.prototype[name];
 | |
|   elementProtoDescriptors[name] = {
 | |
|     value() {
 | |
|       reset(this.parentNode);
 | |
|       return method.apply(this, arguments);
 | |
|     }
 | |
|   };
 | |
| }
 | |
| defineProperties(Element.prototype, elementProtoDescriptors);
 | |
| 
 | |
| 
 | |
| // ParentNode
 | |
| const {
 | |
|   childNodes: {get: getChildNodes},
 | |
|   children: {get: getChildren}
 | |
| } = getOwnPropertyDescriptors(ParentNode.prototype);
 | |
| 
 | |
| defineProperties(ParentNode.prototype, {
 | |
|   childNodes: {get() {
 | |
|     return get(childNodesWM, this, getChildNodes);
 | |
|   }},
 | |
|   children: {get() {
 | |
|     return get(childrenWM, this, getChildren);
 | |
|   }}
 | |
| });
 | |
| 
 | |
| const {
 | |
|   insertBefore,
 | |
|   querySelector,
 | |
|   querySelectorAll
 | |
| } = ParentNode.prototype;
 | |
| 
 | |
| const query = (wm, method, self, selectors) => {
 | |
|   if (!wm.has(self))
 | |
|     wm.set(self, new Map);
 | |
|   const map = wm.get(self);
 | |
|   if (map.has(selectors))
 | |
|     return map.get(selectors);
 | |
|   const result = method.call(self, selectors);
 | |
|   map.set(selectors, result);
 | |
|   return result;
 | |
| };
 | |
| 
 | |
| defineProperties(ParentNode.prototype, {
 | |
|   insertBefore: {value(node, before) {
 | |
|     reset(this);
 | |
|     if (node.nodeType === DOCUMENT_FRAGMENT_NODE)
 | |
|       reset(node);
 | |
|     return insertBefore.call(this, node, before);
 | |
|   }},
 | |
|   getElementsByClassName: {value(className) {
 | |
|     return this.querySelectorAll('.' + className);
 | |
|   }},
 | |
|   getElementsByTagName: {value(tagName) {
 | |
|     return this.querySelectorAll(tagName);
 | |
|   }},
 | |
|   querySelector: {value(selectors) {
 | |
|     return query(querySelectorWM, querySelector, this, selectors);
 | |
|   }},
 | |
|   querySelectorAll: {value(selectors) {
 | |
|     return query(querySelectorAllWM, querySelectorAll, this, selectors);
 | |
|   }}
 | |
| });
 | |
| 
 | |
| 
 | |
| // NonElementParentNode
 | |
| defineProperties(NonElementParentNode.prototype, {
 | |
|   getElementById: {value(id) {
 | |
|     return this.querySelector('#' + id);
 | |
|   }}
 | |
| });
 | |
| 
 | |
| 
 | |
| // HTMLDocument
 | |
| const {title: {
 | |
|   get: getTitle,
 | |
|   set: setTitle
 | |
| }} = getOwnPropertyDescriptors(HTMLDocument.prototype);
 | |
| 
 | |
| defineProperties(HTMLDocument.prototype, {
 | |
|   title: {
 | |
|     get: getTitle,
 | |
|     set(value) {
 | |
|       reset(this.head);
 | |
|       setTitle.call(this, value);
 | |
|     }
 | |
|   }
 | |
| });
 | |
| 
 | |
| 
 | |
| export * from './index.js';
 |