mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 07:13:08 -05:00
Memoize node category with weak map
Fix horrendous performance of isInline etc.
This commit is contained in:
parent
5d24e3eb4d
commit
f46dee1255
5 changed files with 78 additions and 24 deletions
|
@ -47,6 +47,7 @@ var cantFocusEmptyTextNodes = isIElt11 || isWebKit;
|
||||||
var losesSelectionOnBlur = isIElt11;
|
var losesSelectionOnBlur = isIElt11;
|
||||||
|
|
||||||
var canObserveMutations = typeof MutationObserver !== 'undefined';
|
var canObserveMutations = typeof MutationObserver !== 'undefined';
|
||||||
|
var canWeakMap = typeof WeakMap !== 'undefined';
|
||||||
|
|
||||||
// Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space
|
// Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space
|
||||||
var notWS = /[^ \t\r\n]/;
|
var notWS = /[^ \t\r\n]/;
|
||||||
|
@ -201,25 +202,48 @@ function every ( nodeList, fn ) {
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
|
var UNKNOWN = 0;
|
||||||
|
var INLINE = 1;
|
||||||
|
var BLOCK = 2;
|
||||||
|
var CONTAINER = 3;
|
||||||
|
|
||||||
|
var nodeCategoryCache = canWeakMap ? new WeakMap() : null;
|
||||||
|
|
||||||
function isLeaf ( node ) {
|
function isLeaf ( node ) {
|
||||||
return node.nodeType === ELEMENT_NODE &&
|
return node.nodeType === ELEMENT_NODE && !!leafNodeNames[ node.nodeName ];
|
||||||
!!leafNodeNames[ node.nodeName ];
|
|
||||||
}
|
}
|
||||||
function isInline ( node ) {
|
function getNodeCategory ( node ) {
|
||||||
return inlineNodeNames.test( node.nodeName ) &&
|
if ( canWeakMap && nodeCategoryCache.has( node ) ) {
|
||||||
|
return nodeCategoryCache.get( node );
|
||||||
|
}
|
||||||
|
var type = node.nodeType;
|
||||||
|
var nodeCategory;
|
||||||
|
if ( type === TEXT_NODE ) {
|
||||||
|
nodeCategory = INLINE;
|
||||||
|
} else if ( type !== ELEMENT_NODE && type !== DOCUMENT_FRAGMENT_NODE ) {
|
||||||
|
nodeCategory = UNKNOWN;
|
||||||
|
} else if ( !every( node.childNodes, isInline ) ) {
|
||||||
// Malformed HTML can have block tags inside inline tags. Need to treat
|
// Malformed HTML can have block tags inside inline tags. Need to treat
|
||||||
// these as containers rather than inline. See #239.
|
// these as containers rather than inline. See #239.
|
||||||
( node.nodeType === TEXT_NODE || every( node.childNodes, isInline ) );
|
nodeCategory = CONTAINER;
|
||||||
|
} else if ( inlineNodeNames.test( node.nodeName ) ) {
|
||||||
|
nodeCategory = INLINE;
|
||||||
|
} else {
|
||||||
|
nodeCategory = BLOCK;
|
||||||
|
}
|
||||||
|
if ( canWeakMap ) {
|
||||||
|
nodeCategoryCache.set( node, nodeCategory );
|
||||||
|
}
|
||||||
|
return nodeCategory;
|
||||||
|
}
|
||||||
|
function isInline ( node ) {
|
||||||
|
return getNodeCategory( node ) === INLINE;
|
||||||
}
|
}
|
||||||
function isBlock ( node ) {
|
function isBlock ( node ) {
|
||||||
var type = node.nodeType;
|
return getNodeCategory( node ) === BLOCK;
|
||||||
return ( type === ELEMENT_NODE || type === DOCUMENT_FRAGMENT_NODE ) &&
|
|
||||||
!isInline( node ) && every( node.childNodes, isInline );
|
|
||||||
}
|
}
|
||||||
function isContainer ( node ) {
|
function isContainer ( node ) {
|
||||||
var type = node.nodeType;
|
return getNodeCategory( node ) === CONTAINER;
|
||||||
return ( type === ELEMENT_NODE || type === DOCUMENT_FRAGMENT_NODE ) &&
|
|
||||||
!isInline( node ) && !isBlock( node );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBlockWalker ( node, root ) {
|
function getBlockWalker ( node, root ) {
|
||||||
|
@ -3110,6 +3134,9 @@ proto._keyUpDetectChange = function ( event ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
proto._docWasChanged = function () {
|
proto._docWasChanged = function () {
|
||||||
|
if ( canWeakMap ) {
|
||||||
|
nodeCategoryCache = new WeakMap();
|
||||||
|
}
|
||||||
if ( this._ignoreAllChanges ) {
|
if ( this._ignoreAllChanges ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -43,6 +43,7 @@ var cantFocusEmptyTextNodes = isIElt11 || isWebKit;
|
||||||
var losesSelectionOnBlur = isIElt11;
|
var losesSelectionOnBlur = isIElt11;
|
||||||
|
|
||||||
var canObserveMutations = typeof MutationObserver !== 'undefined';
|
var canObserveMutations = typeof MutationObserver !== 'undefined';
|
||||||
|
var canWeakMap = typeof WeakMap !== 'undefined';
|
||||||
|
|
||||||
// Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space
|
// Use [^ \t\r\n] instead of \S so that nbsp does not count as white-space
|
||||||
var notWS = /[^ \t\r\n]/;
|
var notWS = /[^ \t\r\n]/;
|
||||||
|
|
|
@ -746,6 +746,9 @@ proto._keyUpDetectChange = function ( event ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
proto._docWasChanged = function () {
|
proto._docWasChanged = function () {
|
||||||
|
if ( canWeakMap ) {
|
||||||
|
nodeCategoryCache = new WeakMap();
|
||||||
|
}
|
||||||
if ( this._ignoreAllChanges ) {
|
if ( this._ignoreAllChanges ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,25 +22,48 @@ function every ( nodeList, fn ) {
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
|
var UNKNOWN = 0;
|
||||||
|
var INLINE = 1;
|
||||||
|
var BLOCK = 2;
|
||||||
|
var CONTAINER = 3;
|
||||||
|
|
||||||
|
var nodeCategoryCache = canWeakMap ? new WeakMap() : null;
|
||||||
|
|
||||||
function isLeaf ( node ) {
|
function isLeaf ( node ) {
|
||||||
return node.nodeType === ELEMENT_NODE &&
|
return node.nodeType === ELEMENT_NODE && !!leafNodeNames[ node.nodeName ];
|
||||||
!!leafNodeNames[ node.nodeName ];
|
|
||||||
}
|
}
|
||||||
function isInline ( node ) {
|
function getNodeCategory ( node ) {
|
||||||
return inlineNodeNames.test( node.nodeName ) &&
|
if ( canWeakMap && nodeCategoryCache.has( node ) ) {
|
||||||
|
return nodeCategoryCache.get( node );
|
||||||
|
}
|
||||||
|
var type = node.nodeType;
|
||||||
|
var nodeCategory;
|
||||||
|
if ( type === TEXT_NODE ) {
|
||||||
|
nodeCategory = INLINE;
|
||||||
|
} else if ( type !== ELEMENT_NODE && type !== DOCUMENT_FRAGMENT_NODE ) {
|
||||||
|
nodeCategory = UNKNOWN;
|
||||||
|
} else if ( !every( node.childNodes, isInline ) ) {
|
||||||
// Malformed HTML can have block tags inside inline tags. Need to treat
|
// Malformed HTML can have block tags inside inline tags. Need to treat
|
||||||
// these as containers rather than inline. See #239.
|
// these as containers rather than inline. See #239.
|
||||||
( node.nodeType === TEXT_NODE || every( node.childNodes, isInline ) );
|
nodeCategory = CONTAINER;
|
||||||
|
} else if ( inlineNodeNames.test( node.nodeName ) ) {
|
||||||
|
nodeCategory = INLINE;
|
||||||
|
} else {
|
||||||
|
nodeCategory = BLOCK;
|
||||||
|
}
|
||||||
|
if ( canWeakMap ) {
|
||||||
|
nodeCategoryCache.set( node, nodeCategory );
|
||||||
|
}
|
||||||
|
return nodeCategory;
|
||||||
|
}
|
||||||
|
function isInline ( node ) {
|
||||||
|
return getNodeCategory( node ) === INLINE;
|
||||||
}
|
}
|
||||||
function isBlock ( node ) {
|
function isBlock ( node ) {
|
||||||
var type = node.nodeType;
|
return getNodeCategory( node ) === BLOCK;
|
||||||
return ( type === ELEMENT_NODE || type === DOCUMENT_FRAGMENT_NODE ) &&
|
|
||||||
!isInline( node ) && every( node.childNodes, isInline );
|
|
||||||
}
|
}
|
||||||
function isContainer ( node ) {
|
function isContainer ( node ) {
|
||||||
var type = node.nodeType;
|
return getNodeCategory( node ) === CONTAINER;
|
||||||
return ( type === ELEMENT_NODE || type === DOCUMENT_FRAGMENT_NODE ) &&
|
|
||||||
!isInline( node ) && !isBlock( node );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBlockWalker ( node, root ) {
|
function getBlockWalker ( node, root ) {
|
||||||
|
|
Loading…
Reference in a new issue