aurelia-pal-nodejs
Advanced tools
Comparing version 1.0.0-alpha.3 to 1.0.0-alpha.4
@@ -8,11 +8,7 @@ /** | ||
*/ | ||
Element: { | ||
new (): Element; | ||
}; | ||
Element: typeof Element; | ||
/** | ||
* The global DOM SVGElement type. | ||
*/ | ||
SVGElement: { | ||
new (): SVGElement; | ||
}; | ||
SVGElement: typeof SVGElement; | ||
/** | ||
@@ -19,0 +15,0 @@ * A key representing a DOM boundary. |
export interface IGlobal extends Window { | ||
Element?: any; | ||
SVGElement?: any; | ||
XMLHttpRequest?: any; | ||
CustomEvent?: { | ||
new (eventType: string, options: Object): CustomEvent; | ||
}; | ||
MutationObserver: typeof MutationObserver; | ||
Element: typeof Element; | ||
SVGElement: typeof SVGElement; | ||
XMLHttpRequest: typeof XMLHttpRequest; | ||
CustomEvent: typeof CustomEvent; | ||
} |
@@ -5,5 +5,1 @@ /** | ||
export declare function initialize(): void; | ||
/** | ||
* Terminate any long-life timers | ||
*/ | ||
export declare function terminate(): void; |
"use strict"; | ||
const aurelia_pal_1 = require('aurelia-pal'); | ||
const nodejs_pal_builder_1 = require('./nodejs-pal-builder'); | ||
const mutation_observer_1 = require('./polyfills/mutation-observer'); | ||
let isInitialized = false; | ||
@@ -66,10 +65,3 @@ /** | ||
exports.initialize = initialize; | ||
/** | ||
* Terminate any long-life timers | ||
*/ | ||
function terminate() { | ||
mutation_observer_1.disposeObservers(); | ||
} | ||
exports.terminate = terminate; | ||
//# sourceMappingURL=index.js.map |
@@ -9,8 +9,4 @@ import { IDom } from './dom'; | ||
constructor(global: IGlobal); | ||
Element: { | ||
new (): Element; | ||
}; | ||
SVGElement: { | ||
new (): SVGElement; | ||
}; | ||
Element: typeof Element; | ||
SVGElement: typeof SVGElement; | ||
boundary: string; | ||
@@ -17,0 +13,0 @@ title: string; |
@@ -6,17 +6,62 @@ "use strict"; | ||
const jsdom_1 = require('jsdom'); | ||
const mutation_observer_1 = require('./polyfills/mutation-observer'); | ||
const mutation_observer_2 = require('./polyfills/mutation-observer'); | ||
let _patchedjsdom = false; | ||
function buildPal() { | ||
var _global = jsdom_1.jsdom(undefined, {}).defaultView; | ||
ensurePerformance(_global.window); | ||
ensureMutationObserver(_global.window); | ||
var _platform = new nodejs_platform_1.NodeJsPlatform(_global); | ||
var _dom = new nodejs_dom_1.NodeJsDom(_global); | ||
var _feature = new nodejs_feature_1.NodeJsFeature(_global); | ||
var global = jsdom_1.jsdom(undefined, {}).defaultView; | ||
if (!_patchedjsdom) { | ||
patchNotifyChange(global); | ||
_patchedjsdom = true; | ||
} | ||
ensurePerformance(global.window); | ||
ensureMutationObserver(global.window); | ||
var platform = new nodejs_platform_1.NodeJsPlatform(global); | ||
var dom = new nodejs_dom_1.NodeJsDom(global); | ||
var feature = new nodejs_feature_1.NodeJsFeature(global); | ||
return { | ||
global: _global, | ||
platform: _platform, | ||
dom: _dom, | ||
feature: _feature | ||
global: global, | ||
platform: platform, | ||
dom: dom, | ||
feature: feature | ||
}; | ||
} | ||
exports.buildPal = buildPal; | ||
let intersectSetter = function (proto, propertyName, intersect) { | ||
let old = Object.getOwnPropertyDescriptor(proto, propertyName); | ||
let oldSet = old.set; | ||
let newSet = function set(V) { | ||
oldSet.call(this, V); | ||
intersect(this); | ||
}; | ||
Object.defineProperty(proto, propertyName, { | ||
set: newSet, | ||
get: old.get, | ||
configurable: old.configurable, | ||
enumerable: old.enumerable | ||
}); | ||
}; | ||
let intersectMethod = function (proto, methodName, intersect) { | ||
let orig = proto[methodName]; | ||
proto[methodName] = function (...args) { | ||
var ret = orig.apply(this, args); | ||
intersect(this); | ||
return ret; | ||
}; | ||
}; | ||
function patchNotifyChange(window) { | ||
let notifyInstance = mutation_observer_2.MutationNotifier.getInstance(); | ||
let notify = function (node) { notifyInstance.notifyChanged(node); }; | ||
let node_proto = window._core.Node.prototype; | ||
intersectMethod(node_proto, "appendChild", notify); | ||
intersectMethod(node_proto, "insertBefore", notify); | ||
intersectMethod(node_proto, "removeChild", notify); | ||
intersectMethod(node_proto, "replaceChild", notify); | ||
intersectSetter(node_proto, "nodeValue", notify); | ||
intersectSetter(node_proto, "textContent", notify); | ||
let element_proto = window._core.Element.prototype; | ||
intersectMethod(element_proto, "setAttribute", notify); | ||
intersectMethod(element_proto, "removeAttribute", notify); | ||
intersectMethod(element_proto, "removeAttributeNode", notify); | ||
intersectMethod(element_proto, "removeAttributeNS", notify); | ||
} | ||
function ensurePerformance(window) { | ||
@@ -37,5 +82,7 @@ if (window.performance === undefined) { | ||
function ensureMutationObserver(window) { | ||
require('./polyfills/mutation-observer').polyfill(window); | ||
if (!window.MutationObserver) { | ||
window.MutationObserver = mutation_observer_1.MutationObserver; | ||
} | ||
} | ||
//# sourceMappingURL=nodejs-pal-builder.js.map |
@@ -51,3 +51,3 @@ import { IPlatform } from './platform'; | ||
*/ | ||
XMLHttpRequest: XMLHttpRequest; | ||
XMLHttpRequest: typeof XMLHttpRequest; | ||
} |
@@ -54,3 +54,3 @@ import { IPerformance } from './performance'; | ||
*/ | ||
XMLHttpRequest: XMLHttpRequest; | ||
XMLHttpRequest: typeof XMLHttpRequest; | ||
} |
@@ -1,4 +0,5 @@ | ||
export declare function polyfill(window: any): void; | ||
export declare function disposeObservers(): void; | ||
/// <reference types="node" /> | ||
export declare class Util { | ||
static counter: number; | ||
static expando: string; | ||
static clone($target: any, config: any): { | ||
@@ -60,2 +61,3 @@ node: any; | ||
private _disposed; | ||
private _notifyListener; | ||
constructor(listener: any); | ||
@@ -65,7 +67,7 @@ observe($target: any, config: any): void; | ||
disconnect(): void; | ||
_createMutationSearcher($target: any, config: any): (mutations: any) => void; | ||
_startMutationChecker(observer: any): void; | ||
_searchSubtree(mutations: any, $target: any, $oldstate: any, config: any): any; | ||
_findCharDataMutations(mutations: any, $target: any, $oldstate: any, filter: any): void; | ||
_findAttributeMutations(mutations: any, $target: any, $oldstate: any, filter: any): void; | ||
private createMutationSearcher($target, config); | ||
private scheduleMutationCheck(observer); | ||
private mutationChecker(observer); | ||
private searchSubtree(mutations, $target, $oldstate, config); | ||
private findAttributeMutations(mutations, $target, $oldstate, filter); | ||
} | ||
@@ -75,1 +77,8 @@ export declare class MutationRecord { | ||
} | ||
import { EventEmitter } from 'events'; | ||
export declare class MutationNotifier extends EventEmitter { | ||
private static _instance; | ||
static getInstance(): MutationNotifier; | ||
constructor(); | ||
notifyChanged(node: Node): void; | ||
} |
@@ -7,31 +7,2 @@ /* | ||
"use strict"; | ||
const jsdom_1 = require('jsdom'); | ||
let _dispose = false; | ||
function polyfill(window) { | ||
if (!window.MutationObserver) { | ||
window.MutationObserver = MutationObserver; | ||
} | ||
} | ||
exports.polyfill = polyfill; | ||
function disposeObservers() { | ||
_dispose = true; | ||
} | ||
exports.disposeObservers = disposeObservers; | ||
let dom = jsdom_1.jsdom(undefined, {}).defaultView; | ||
let document = dom.document; | ||
let counter = 1; | ||
let expando = 'mo_id'; | ||
let elmt = document.createElement('i'); | ||
elmt.style.top = "0"; | ||
let hasAttributeBug = elmt.attributes.style.value !== 'null'; | ||
document = null; | ||
dom = null; | ||
// GCC hack see http:// stackoverflow.com/a/23202438/1517919 | ||
const JSCompiler_renameProperty = a => a; | ||
const getAttributeWithStyleHack = (el, attr) => { | ||
// As with getAttributeSimple there is a potential warning for custom attribtues in IE7. | ||
return attr.name !== 'style' ? attr.value : el.style.cssText; | ||
}; | ||
const getAttributeSimple = (el, attr) => attr.value; | ||
const getAttributeValue = hasAttributeBug ? getAttributeSimple : getAttributeWithStyleHack; | ||
class Util { | ||
@@ -63,3 +34,3 @@ static clone($target, config) { | ||
if (!config.afilter || config.afilter[attr.name]) { | ||
memo[attr.name] = getAttributeValue($target, attr); | ||
memo[attr.name] = attr.value; | ||
} | ||
@@ -88,2 +59,3 @@ return memo; | ||
static indexOfCustomNode(set, $node, idx) { | ||
const JSCompiler_renameProperty = a => a; | ||
return this.indexOf(set, $node, idx, JSCompiler_renameProperty('node')); | ||
@@ -99,3 +71,3 @@ } | ||
try { | ||
return $ele.id || ($ele[expando] = $ele[expando] || counter++); | ||
return $ele.id || ($ele[this.expando] = $ele[this.expando] || this.counter++); | ||
} | ||
@@ -107,3 +79,3 @@ catch (e) { | ||
catch (shitie) { | ||
return counter++; | ||
return this.counter++; | ||
} | ||
@@ -159,2 +131,4 @@ } | ||
} | ||
Util.counter = 1; | ||
Util.expando = 'mo_id'; | ||
exports.Util = Util; | ||
@@ -168,5 +142,7 @@ class MutationObserver { | ||
this._disposed = false; | ||
this._notifyListener = null; | ||
this._watched = []; | ||
this._listener = listener; | ||
this._period = 30; | ||
this._notifyListener = () => { this.scheduleMutationCheck(this); }; | ||
} | ||
@@ -183,2 +159,3 @@ observe($target, config) { | ||
}; | ||
MutationNotifier.getInstance().on("changed", this._notifyListener); | ||
let watched = this._watched; | ||
@@ -202,8 +179,4 @@ // remove already observed target element from pool | ||
tar: $target, | ||
fn: this._createMutationSearcher($target, settings) | ||
fn: this.createMutationSearcher($target, settings) | ||
}); | ||
// reconnect if not connected | ||
if (!this._timeout) { | ||
this._startMutationChecker(this); | ||
} | ||
} | ||
@@ -220,2 +193,3 @@ takeRecords() { | ||
this._watched = []; // clear the stuff being observed | ||
MutationNotifier.getInstance().removeListener("changed", this._notifyListener); | ||
this._disposed = true; | ||
@@ -225,3 +199,3 @@ clearTimeout(this._timeout); // ready for garbage collection | ||
} | ||
_createMutationSearcher($target, config) { | ||
createMutationSearcher($target, config) { | ||
/** type {Elestuct} */ | ||
@@ -246,7 +220,7 @@ let $oldstate = Util.clone($target, config); // create the cloned datastructure | ||
if (config.attr && $oldstate.attr) { | ||
this._findAttributeMutations(mutations, $target, $oldstate.attr, config.afilter); | ||
this.findAttributeMutations(mutations, $target, $oldstate.attr, config.afilter); | ||
} | ||
// check childlist or subtree for mutations | ||
if (config.kids || config.descendents) { | ||
dirty = this._searchSubtree(mutations, $target, $oldstate, config); | ||
dirty = this.searchSubtree(mutations, $target, $oldstate, config); | ||
} | ||
@@ -260,16 +234,18 @@ // reclone data structure if theres changes | ||
} | ||
_startMutationChecker(observer) { | ||
const check = () => { | ||
let mutations = observer.takeRecords(); | ||
if (mutations.length) { | ||
// calling the listener with context is not spec but currently consistent with FF and WebKit | ||
observer._listener(mutations, observer); | ||
} | ||
/** @private */ | ||
if (observer._disposed == false && _dispose == false) | ||
observer._timeout = setTimeout(check, this._period); | ||
}; | ||
check(); | ||
scheduleMutationCheck(observer) { | ||
// Only schedule if there isn't already a timer. | ||
if (!observer._timeout) { | ||
observer._timeout = setTimeout(() => this.mutationChecker(observer), this._period); | ||
} | ||
} | ||
_searchSubtree(mutations, $target, $oldstate, config) { | ||
mutationChecker(observer) { | ||
// allow scheduling a new timer. | ||
observer._timeout = null; | ||
let mutations = observer.takeRecords(); | ||
if (mutations.length) { | ||
// calling the listener with context is not spec but currently consistent with FF and WebKit | ||
observer._listener(mutations, observer); | ||
} | ||
} | ||
searchSubtree(mutations, $target, $oldstate, config) { | ||
// Track if the tree is dirty and has to be recomputed (#14). | ||
@@ -311,3 +287,3 @@ let dirty; | ||
if (config.attr && oldstruct.attr) | ||
this._findAttributeMutations(mutations, $cur, oldstruct.attr, config.afilter); | ||
this.findAttributeMutations(mutations, $cur, oldstruct.attr, config.afilter); | ||
if (config.charData && $cur.nodeType === 3 && $cur.nodeValue !== oldstruct.charData) { | ||
@@ -362,3 +338,3 @@ mutations.push(new MutationRecord({ | ||
if (config.attr && oldstruct.attr) { | ||
this._findAttributeMutations(mutations, $cur, oldstruct.attr, config.afilter); | ||
this.findAttributeMutations(mutations, $cur, oldstruct.attr, config.afilter); | ||
} | ||
@@ -449,5 +425,3 @@ // check character data if node is a comment or textNode and it's being observed | ||
} | ||
_findCharDataMutations(mutations, $target, $oldstate, filter) { | ||
} | ||
_findAttributeMutations(mutations, $target, $oldstate, filter) { | ||
findAttributeMutations(mutations, $target, $oldstate, filter) { | ||
let checked = {}; | ||
@@ -462,3 +436,3 @@ let attributes = $target.attributes; | ||
if (!filter || Util.has(filter, name)) { | ||
if (getAttributeValue($target, attr) !== $oldstate[name]) { | ||
if (attr.value !== $oldstate[name]) { | ||
// The pushing is redundant but gzips very nicely | ||
@@ -510,3 +484,21 @@ mutations.push(new MutationRecord({ | ||
exports.MutationRecord = MutationRecord; | ||
const events_1 = require('events'); | ||
class MutationNotifier extends events_1.EventEmitter { | ||
constructor() { | ||
super(); | ||
this.setMaxListeners(100); | ||
} | ||
static getInstance() { | ||
if (!MutationNotifier._instance) { | ||
MutationNotifier._instance = new MutationNotifier(); | ||
} | ||
return MutationNotifier._instance; | ||
} | ||
notifyChanged(node) { | ||
this.emit("changed", node); | ||
} | ||
} | ||
MutationNotifier._instance = null; | ||
exports.MutationNotifier = MutationNotifier; | ||
//# sourceMappingURL=mutation-observer.js.map |
{ | ||
"name": "aurelia-pal-nodejs", | ||
"version": "1.0.0-alpha.3", | ||
"version": "1.0.0-alpha.4", | ||
"description": "The Node.js-specific implementation of Aurelia's platform abstraction layer.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -0,0 +0,0 @@ # aurelia-pal-nodejs |
@@ -8,3 +8,3 @@ /** | ||
*/ | ||
Element: { new (): Element }; | ||
Element: typeof Element; | ||
@@ -14,3 +14,3 @@ /** | ||
*/ | ||
SVGElement: { new (): SVGElement }; | ||
SVGElement: typeof SVGElement; | ||
/** | ||
@@ -17,0 +17,0 @@ * A key representing a DOM boundary. |
export interface IGlobal extends Window { | ||
Element?: any; | ||
SVGElement?: any; | ||
XMLHttpRequest?: any; | ||
CustomEvent?: { new (eventType: string, options: Object): CustomEvent }; | ||
MutationObserver: typeof MutationObserver; | ||
Element: typeof Element; | ||
SVGElement: typeof SVGElement; | ||
XMLHttpRequest: typeof XMLHttpRequest; | ||
CustomEvent: typeof CustomEvent; | ||
} |
import { initializePAL } from 'aurelia-pal'; | ||
import { buildPal } from './nodejs-pal-builder'; | ||
import { disposeObservers } from './polyfills/mutation-observer'; | ||
@@ -71,9 +70,2 @@ let isInitialized = false; | ||
}); | ||
} | ||
/** | ||
* Terminate any long-life timers | ||
*/ | ||
export function terminate() { | ||
disposeObservers(); | ||
} | ||
} |
@@ -11,8 +11,8 @@ import { IDom } from './dom'; | ||
this.Element = (<any>global).Element; | ||
this.SVGElement = (<any>global).SVGElement; | ||
this.Element = global.Element; | ||
this.SVGElement = global.SVGElement; | ||
} | ||
Element: { new (): Element }; | ||
SVGElement: { new (): SVGElement }; | ||
Element: typeof Element; | ||
SVGElement: typeof SVGElement; | ||
boundary: string = 'aurelia-dom-boundary'; | ||
@@ -19,0 +19,0 @@ title: string = ""; |
@@ -10,21 +10,76 @@ import { initializePAL } from 'aurelia-pal'; | ||
import { jsdom } from 'jsdom'; | ||
import { MutationObserver } from './polyfills/mutation-observer'; | ||
import { MutationNotifier } from './polyfills/mutation-observer'; | ||
let _patchedjsdom = false; | ||
export function buildPal(): { global: IGlobal, platform: IPlatform, dom: IDom, feature: IFeature } { | ||
var _global: IGlobal = jsdom(undefined, {}).defaultView; | ||
var global: IGlobal = <IGlobal>jsdom(undefined, {}).defaultView; | ||
ensurePerformance(_global.window); | ||
ensureMutationObserver(_global.window); | ||
if (!_patchedjsdom) { | ||
patchNotifyChange(global); | ||
_patchedjsdom = true; | ||
} | ||
var _platform = new NodeJsPlatform(_global); | ||
var _dom = new NodeJsDom(_global); | ||
var _feature = new NodeJsFeature(_global); | ||
ensurePerformance(global.window); | ||
ensureMutationObserver(global.window); | ||
var platform = new NodeJsPlatform(global); | ||
var dom = new NodeJsDom(global); | ||
var feature = new NodeJsFeature(global); | ||
return { | ||
global: _global, | ||
platform: _platform, | ||
dom: _dom, | ||
feature: _feature | ||
global: global, | ||
platform: platform, | ||
dom: dom, | ||
feature: feature | ||
}; | ||
} | ||
let intersectSetter = function (proto, propertyName: string, intersect: Function) { | ||
let old = Object.getOwnPropertyDescriptor(proto, propertyName); | ||
let oldSet = old.set; | ||
let newSet = function set(V) { | ||
oldSet.call(this, V); | ||
intersect(this); | ||
}; | ||
Object.defineProperty(proto, propertyName, { | ||
set: newSet, | ||
get: old.get, | ||
configurable: old.configurable, | ||
enumerable: old.enumerable | ||
}); | ||
}; | ||
let intersectMethod = function (proto, methodName: string, intersect: Function) { | ||
let orig = proto[methodName]; | ||
proto[methodName] = function (...args) { | ||
var ret = orig.apply(this, args); | ||
intersect(this); | ||
return ret; | ||
}; | ||
}; | ||
function patchNotifyChange(window: Window) { | ||
let notifyInstance = MutationNotifier.getInstance(); | ||
let notify = function (node: Node) { notifyInstance.notifyChanged(node); }; | ||
let node_proto = (<any>window)._core.Node.prototype; | ||
intersectMethod(node_proto, "appendChild", notify); | ||
intersectMethod(node_proto, "insertBefore", notify); | ||
intersectMethod(node_proto, "removeChild", notify); | ||
intersectMethod(node_proto, "replaceChild", notify); | ||
intersectSetter(node_proto, "nodeValue", notify); | ||
intersectSetter(node_proto, "textContent", notify); | ||
let element_proto = (<any>window)._core.Element.prototype; | ||
intersectMethod(element_proto, "setAttribute", notify); | ||
intersectMethod(element_proto, "removeAttribute", notify); | ||
intersectMethod(element_proto, "removeAttributeNode", notify); | ||
intersectMethod(element_proto, "removeAttributeNS", notify); | ||
} | ||
function ensurePerformance(window) { | ||
@@ -49,3 +104,5 @@ if (window.performance === undefined) { | ||
function ensureMutationObserver(window) { | ||
require('./polyfills/mutation-observer').polyfill(window); | ||
if (!window.MutationObserver) { | ||
window.MutationObserver = MutationObserver; | ||
} | ||
} |
@@ -68,3 +68,3 @@ import { IPlatform } from './platform'; | ||
*/ | ||
XMLHttpRequest: XMLHttpRequest; | ||
XMLHttpRequest: typeof XMLHttpRequest; | ||
} |
@@ -55,3 +55,3 @@ import { IPerformance } from './performance'; | ||
*/ | ||
XMLHttpRequest: XMLHttpRequest; | ||
XMLHttpRequest: typeof XMLHttpRequest; | ||
} |
@@ -7,40 +7,6 @@ /* | ||
import { jsdom } from 'jsdom'; | ||
export class Util { | ||
static counter = 1; | ||
static expando = 'mo_id'; | ||
let _dispose = false; | ||
export function polyfill(window) { | ||
if (!window.MutationObserver) { | ||
window.MutationObserver = MutationObserver; | ||
} | ||
} | ||
export function disposeObservers() { | ||
_dispose = true; | ||
} | ||
let dom = jsdom(undefined, {}).defaultView; | ||
let document = dom.document; | ||
let counter = 1; | ||
let expando = 'mo_id'; | ||
let elmt = <any>document.createElement('i'); | ||
elmt.style.top = "0"; | ||
let hasAttributeBug = elmt.attributes.style.value !== 'null'; | ||
document = null; | ||
dom = null; | ||
// GCC hack see http:// stackoverflow.com/a/23202438/1517919 | ||
const JSCompiler_renameProperty = a => a; | ||
const getAttributeWithStyleHack = (el, attr) => { | ||
// As with getAttributeSimple there is a potential warning for custom attribtues in IE7. | ||
return attr.name !== 'style' ? attr.value : el.style.cssText; | ||
}; | ||
const getAttributeSimple = (el, attr) => attr.value; | ||
const getAttributeValue = hasAttributeBug ? getAttributeSimple : getAttributeWithStyleHack; | ||
export class Util { | ||
static clone($target, config) { | ||
@@ -71,3 +37,3 @@ let recurse = true; // set true so childList we'll always check the first level | ||
if (!config.afilter || config.afilter[attr.name]) { | ||
memo[attr.name] = getAttributeValue($target, attr); | ||
memo[attr.name] = attr.value; | ||
} | ||
@@ -99,2 +65,3 @@ return memo; | ||
static indexOfCustomNode(set, $node, idx) { | ||
const JSCompiler_renameProperty = a => a; | ||
return this.indexOf(set, $node, idx, JSCompiler_renameProperty('node')); | ||
@@ -111,3 +78,3 @@ } | ||
try { | ||
return $ele.id || ($ele[expando] = $ele[expando] || counter++); | ||
return $ele.id || ($ele[this.expando] = $ele[this.expando] || this.counter++); | ||
} catch (e) { // ie <8 will throw if you set an unknown property on a text node | ||
@@ -117,3 +84,3 @@ try { | ||
} catch (shitie) { // when text node is removed: https://gist.github.com/megawac/8355978 :( | ||
return counter++; | ||
return this.counter++; | ||
} | ||
@@ -179,2 +146,3 @@ } | ||
private _disposed = false; | ||
private _notifyListener = null; | ||
@@ -185,2 +153,3 @@ constructor(listener) { | ||
this._period = 30; | ||
this._notifyListener = () => { this.scheduleMutationCheck(this); }; | ||
} | ||
@@ -201,2 +170,4 @@ | ||
MutationNotifier.getInstance().on("changed", this._notifyListener); | ||
let watched = this._watched; | ||
@@ -222,9 +193,4 @@ | ||
tar: $target, | ||
fn: this._createMutationSearcher($target, settings) | ||
fn: this.createMutationSearcher($target, settings) | ||
}); | ||
// reconnect if not connected | ||
if (!this._timeout) { | ||
this._startMutationChecker(this); | ||
} | ||
} | ||
@@ -245,2 +211,3 @@ | ||
this._watched = []; // clear the stuff being observed | ||
MutationNotifier.getInstance().removeListener("changed", this._notifyListener ); | ||
this._disposed = true; | ||
@@ -251,3 +218,3 @@ clearTimeout(this._timeout); // ready for garbage collection | ||
_createMutationSearcher($target, config) { | ||
private createMutationSearcher($target, config) { | ||
/** type {Elestuct} */ | ||
@@ -275,3 +242,3 @@ let $oldstate = Util.clone($target, config); // create the cloned datastructure | ||
if (config.attr && $oldstate.attr) { | ||
this._findAttributeMutations(mutations, $target, $oldstate.attr, config.afilter); | ||
this.findAttributeMutations(mutations, $target, $oldstate.attr, config.afilter); | ||
} | ||
@@ -281,3 +248,3 @@ | ||
if (config.kids || config.descendents) { | ||
dirty = this._searchSubtree(mutations, $target, $oldstate, config); | ||
dirty = this.searchSubtree(mutations, $target, $oldstate, config); | ||
} | ||
@@ -293,18 +260,22 @@ | ||
_startMutationChecker(observer) { | ||
const check = () => { | ||
let mutations = observer.takeRecords(); | ||
private scheduleMutationCheck(observer) { | ||
// Only schedule if there isn't already a timer. | ||
if (!observer._timeout) { | ||
observer._timeout = setTimeout(() => this.mutationChecker(observer), this._period); | ||
} | ||
} | ||
if (mutations.length) { // fire away | ||
// calling the listener with context is not spec but currently consistent with FF and WebKit | ||
observer._listener(mutations, observer); | ||
} | ||
/** @private */ | ||
if (observer._disposed == false && _dispose == false) | ||
observer._timeout = setTimeout(check, this._period); | ||
}; | ||
check(); | ||
private mutationChecker(observer) { | ||
// allow scheduling a new timer. | ||
observer._timeout = null; | ||
let mutations = observer.takeRecords(); | ||
if (mutations.length) { // fire away | ||
// calling the listener with context is not spec but currently consistent with FF and WebKit | ||
observer._listener(mutations, observer); | ||
} | ||
} | ||
_searchSubtree(mutations, $target, $oldstate, config) { | ||
private searchSubtree(mutations, $target, $oldstate, config) { | ||
// Track if the tree is dirty and has to be recomputed (#14). | ||
@@ -347,3 +318,3 @@ let dirty; | ||
// Alright we found the resorted nodes now check for other types of mutations | ||
if (config.attr && oldstruct.attr) this._findAttributeMutations(mutations, $cur, oldstruct.attr, config.afilter); | ||
if (config.attr && oldstruct.attr) this.findAttributeMutations(mutations, $cur, oldstruct.attr, config.afilter); | ||
if (config.charData && $cur.nodeType === 3 && $cur.nodeValue !== oldstruct.charData) { | ||
@@ -402,3 +373,3 @@ mutations.push(new MutationRecord({ | ||
if (config.attr && oldstruct.attr) {/* oldstruct.attr instead of textnode check */ | ||
this._findAttributeMutations(mutations, $cur, oldstruct.attr, config.afilter); | ||
this.findAttributeMutations(mutations, $cur, oldstruct.attr, config.afilter); | ||
} | ||
@@ -490,6 +461,3 @@ // check character data if node is a comment or textNode and it's being observed | ||
_findCharDataMutations(mutations, $target, $oldstate, filter) { | ||
} | ||
_findAttributeMutations(mutations, $target, $oldstate, filter) { | ||
private findAttributeMutations(mutations, $target, $oldstate, filter) { | ||
let checked = {}; | ||
@@ -504,3 +472,3 @@ let attributes = $target.attributes; | ||
if (!filter || Util.has(filter, name)) { | ||
if (getAttributeValue($target, attr) !== $oldstate[name]) { | ||
if (attr.value !== $oldstate[name]) { | ||
// The pushing is redundant but gzips very nicely | ||
@@ -550,1 +518,23 @@ mutations.push(new MutationRecord({ | ||
} | ||
import { EventEmitter } from 'events'; | ||
export class MutationNotifier extends EventEmitter { | ||
private static _instance: MutationNotifier = null; | ||
static getInstance() { | ||
if (!MutationNotifier._instance) { | ||
MutationNotifier._instance = new MutationNotifier(); | ||
} | ||
return MutationNotifier._instance; | ||
} | ||
constructor() { | ||
super(); | ||
this.setMaxListeners(100); | ||
} | ||
notifyChanged(node: Node) { | ||
this.emit("changed", node); | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
90914
2263