Comparing version 1.0.1 to 1.0.2
@@ -63,3 +63,3 @@ !(function() { | ||
tasks.delete(promise); | ||
try { resolve(fn()); } | ||
try { resolve(ctx ? fn.call(ctx) : fn()); } | ||
catch (e) { reject(e); } | ||
@@ -66,0 +66,0 @@ }, ctx); |
@@ -10,3 +10,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
root["fastdom"] = factory(root["fastdom"]); | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_2__) { | ||
return /******/ (function(modules) { // webpackBootstrap | ||
@@ -60,4 +60,4 @@ /******/ // The module cache | ||
var strictdom = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"strictdom\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())); | ||
var fastdom = __webpack_require__(1); | ||
var strictdom = __webpack_require__(1); | ||
var fastdom = __webpack_require__(2); | ||
@@ -112,5 +112,848 @@ /** | ||
/* 1 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var __WEBPACK_AMD_DEFINE_RESULT__;!(function() { | ||
'use strict'; | ||
var debug = 0 ? console.log.bind(console, '[strictdom]') : function() {}; | ||
/** | ||
* Crude webkit test. | ||
* | ||
* @type {Boolean} | ||
*/ | ||
var isWebkit = !!window.webkitURL; | ||
/** | ||
* List of properties observed. | ||
* | ||
* @type {Object} | ||
*/ | ||
var properties = { | ||
prototype: { | ||
Document: { | ||
execCommand: Mutate, | ||
elementFromPoint: Measure, | ||
elementsFromPoint: Measure, | ||
scrollingElement: Measure | ||
}, | ||
Node: { | ||
appendChild: { | ||
type: Mutate, | ||
test: function(dom, parent, args) { | ||
var attached = isAttached(parent) || isAttached(args[0]); | ||
if (attached && dom.not('mutate')) throw error(3, this.name); | ||
} | ||
}, | ||
insertBefore: { | ||
type: Mutate, | ||
test: function(dom, parent, args) { | ||
var attached = isAttached(parent) || isAttached(args[0]); | ||
if (attached && dom.not('mutate')) throw error(3, this.name); | ||
} | ||
}, | ||
removeChild: { | ||
type: Mutate, | ||
test: function(dom, parent, args) { | ||
var attached = isAttached(parent) || isAttached(args[0]); | ||
if (attached && dom.not('mutate')) throw error(3, this.name); | ||
} | ||
}, | ||
textContent: Mutate | ||
}, | ||
Element: { | ||
scrollIntoView: Mutate, | ||
scrollBy: Mutate, | ||
scrollTo: Mutate, | ||
getClientRects: Measure, | ||
getBoundingClientRect: Measure, | ||
clientLeft: Measure, | ||
clientWidth: Measure, | ||
clientHeight: Measure, | ||
scrollLeft: Accessor, | ||
scrollTop: Accessor, | ||
scrollWidth: Measure, | ||
scrollHeight: Measure, | ||
innerHTML: Mutate, | ||
outerHTML: Mutate, | ||
insertAdjacentHTML: Mutate, | ||
remove: Mutate, | ||
setAttribute: Mutate, | ||
removeAttribute: Mutate, | ||
className: Mutate, | ||
classList: ClassList | ||
}, | ||
HTMLElement: { | ||
offsetLeft: Measure, | ||
offsetTop: Measure, | ||
offsetWidth: Measure, | ||
offsetHeight: Measure, | ||
offsetParent: Measure, | ||
innerText: Accessor, | ||
outerText: Accessor, | ||
focus: Measure, | ||
blur: Measure, | ||
style: Style, | ||
// `element.dataset` is hard to wrap. | ||
// We could use `Proxy` but it's not | ||
// supported in Chrome yet. Not too | ||
// concerned as `data-` attributes are | ||
// not often associated with render. | ||
// dataset: DATASET | ||
}, | ||
CharacterData: { | ||
remove: Mutate, | ||
data: Mutate | ||
}, | ||
Range: { | ||
getClientRects: Measure, | ||
getBoundingClientRect: Measure | ||
}, | ||
MouseEvent: { | ||
layerX: Measure, | ||
layerY: Measure, | ||
offsetX: Measure, | ||
offsetY: Measure | ||
}, | ||
HTMLButtonElement: { | ||
reportValidity: Measure | ||
}, | ||
HTMLDialogElement: { | ||
showModal: Mutate | ||
}, | ||
HTMLFieldSetElement: { | ||
reportValidity: Measure | ||
}, | ||
HTMLImageElement: { | ||
width: Accessor, | ||
height: Accessor, | ||
x: Measure, | ||
y: Measure | ||
}, | ||
HTMLInputElement: { | ||
reportValidity: Measure | ||
}, | ||
HTMLKeygenElement: { | ||
reportValidity: Measure | ||
}, | ||
SVGSVGElement: { | ||
currentScale: Accessor | ||
} | ||
}, | ||
instance: { | ||
window: { | ||
getComputedStyle: { | ||
type: Measure, | ||
/** | ||
* Throws when the Element is in attached | ||
* and strictdom is not in the 'measure' phase. | ||
* | ||
* @param {StrictDom} strictdom | ||
* @param {Window} win | ||
* @param {Object} args | ||
*/ | ||
test: function(strictdom, win, args) { | ||
if (isAttached(args[0]) && strictdom.not('measure')) { | ||
throw error(2, 'getComputedStyle'); | ||
} | ||
} | ||
}, | ||
innerWidth: { | ||
type: isWebkit ? Value : Measure, | ||
/** | ||
* Throws when the window is nested (in <iframe>) | ||
* and StrictDom is not in the 'measure' phase. | ||
* | ||
* @param {StrictDom} strictdom | ||
*/ | ||
test: function(strictdom) { | ||
var inIframe = window !== window.top; | ||
if (inIframe && strictdom.not('measure')) { | ||
throw error(2, '`.innerWidth` (in iframe)'); | ||
} | ||
} | ||
}, | ||
innerHeight: { | ||
type: isWebkit ? Value : Measure, | ||
/** | ||
* Throws when the window is nested (in <iframe>) | ||
* and StrictDom is not in the 'measure' phase. | ||
* | ||
* @param {StrictDom} strictdom | ||
*/ | ||
test: function(strictdom) { | ||
var inIframe = window !== window.top; | ||
if (inIframe && strictdom.not('measure')) { | ||
throw error(2, '`.innerHeight` (in iframe)'); | ||
} | ||
} | ||
}, | ||
scrollX: isWebkit ? Value : Measure, | ||
scrollY: isWebkit ? Value : Measure, | ||
scrollBy: Mutate, | ||
scrollTo: Mutate, | ||
scroll: Mutate, | ||
} | ||
} | ||
}; | ||
/** | ||
* The master controller for all properties. | ||
* | ||
* @param {Window} win | ||
*/ | ||
function StrictDom(win) { | ||
this.properties = []; | ||
this._phase = null; | ||
this.win = win; | ||
this.createPrototypeProperties(); | ||
this.createInstanceProperties(); | ||
} | ||
StrictDom.prototype = { | ||
/** | ||
* Set the current phase. | ||
* @param {[type]} value [description] | ||
* @return {[type]} [description] | ||
*/ | ||
phase: function(type, task) { | ||
if (!arguments.length) return this._phase; | ||
if (!this.knownPhase(type)) throw error(4, type); | ||
var previous = this._phase; | ||
this._phase = type; | ||
if (typeof task != 'function') return; | ||
var result = task(); | ||
this._phase = previous; | ||
return result; | ||
}, | ||
knownPhase: function(value) { | ||
return !!~['measure', 'mutate', null].indexOf(value); | ||
}, | ||
is: function(value) { | ||
return this._phase === value; | ||
}, | ||
not: function(value) { | ||
return !this.is(value); | ||
}, | ||
/** | ||
* Enable strict mode. | ||
* | ||
* @public | ||
*/ | ||
enable: function() { | ||
if (this.enabled) return; | ||
debug('enable'); | ||
var i = this.properties.length; | ||
while (i--) this.properties[i].enable(); | ||
this.enabled = true; | ||
}, | ||
/** | ||
* Disable strict mode. | ||
* | ||
* @public | ||
*/ | ||
disable: function() { | ||
if (!this.enabled) return; | ||
debug('disable'); | ||
var i = this.properties.length; | ||
while (i--) this.properties[i].disable(); | ||
this.enabled = false; | ||
this.phase(null); | ||
}, | ||
/** | ||
* Create wrappers for each of | ||
* of the prototype properties. | ||
* | ||
* @private | ||
*/ | ||
createPrototypeProperties: function() { | ||
debug('create prototype properties'); | ||
var props = properties.prototype; | ||
for (var key in props) { | ||
for (var name in props[key]) { | ||
var object = this.win[key] && this.win[key].prototype; | ||
if (!object || !object.hasOwnProperty(name)) continue; | ||
this.properties.push(this.create(object, name, props[key][name])); | ||
} | ||
} | ||
}, | ||
/** | ||
* Create wrappers for each of | ||
* of the instance properties. | ||
* | ||
* @private | ||
*/ | ||
createInstanceProperties: function() { | ||
debug('create instance properties'); | ||
var props = properties.instance; | ||
for (var key in props) { | ||
for (var name in props[key]) { | ||
var object = this.win[key]; | ||
if (!object || !object.hasOwnProperty(name)) continue; | ||
this.properties.push(this.create(object, name, props[key][name])); | ||
} | ||
} | ||
}, | ||
/** | ||
* Create a wrapped `Property` that | ||
* can be individually enabled/disabled. | ||
* | ||
* @param {Object} object - the parent object (eg. Node.prototype) | ||
* @param {String} name - the property name (eg. 'appendChild') | ||
* @param {(constructor|Object)} config - from the above property definition | ||
* @return {Property} | ||
*/ | ||
create: function(object, name, config) { | ||
debug('create', name); | ||
var Constructor = config.type || config; | ||
return new Constructor(object, name, config, this); | ||
} | ||
}; | ||
/** | ||
* Create a new `Property`. | ||
* | ||
* A wrapper around a property that observes | ||
* usage, throwing errors when used in the | ||
* incorrect phase. | ||
* | ||
* @param {Object} object - the parent object (eg. Node.prototype) | ||
* @param {[type]} name - the property name (eg. 'appendChild') | ||
* @param {(constructor|Object)} config - from the above definition | ||
* @param {StrictDom} strictdom - injected as a dependency | ||
*/ | ||
function Property(object, name, config, strictdom) { | ||
debug('Property', name, config); | ||
this.strictdom = strictdom; | ||
this.object = object; | ||
this.name = name; | ||
var descriptor = this.getDescriptor(); | ||
// defaults can be overriden from config | ||
if (typeof config == 'object') Object.assign(this, config); | ||
this.descriptors = { | ||
unwrapped: descriptor, | ||
wrapped: this.wrap(descriptor) | ||
}; | ||
} | ||
Property.prototype = { | ||
/** | ||
* Get the property's descriptor. | ||
* | ||
* @return {Object} | ||
* @private | ||
*/ | ||
getDescriptor: function() { | ||
debug('get descriptor', this.name); | ||
return Object.getOwnPropertyDescriptor(this.object, this.name); | ||
}, | ||
/** | ||
* Enable observation by replacing the | ||
* current descriptor with the wrapped one. | ||
* | ||
* @private | ||
*/ | ||
enable: function() { | ||
debug('enable', this.name); | ||
Object.defineProperty(this.object, this.name, this.descriptors.wrapped); | ||
}, | ||
/** | ||
* Disable observation by replacing the | ||
* current descriptor with the original one. | ||
* | ||
* @private | ||
*/ | ||
disable: function() { | ||
debug('disable', this.name); | ||
Object.defineProperty(this.object, this.name, this.descriptors.unwrapped); | ||
}, | ||
// to be overwritten by subclass | ||
wrap: function() {} | ||
}; | ||
/** | ||
* A wrapper for properties that measure | ||
* geometry data from the DOM. | ||
* | ||
* Once a `Measure` property is enabled | ||
* it can only be used when StrictDom | ||
* is in the 'measure' phase, else it | ||
* will throw. | ||
* | ||
* @constructor | ||
* @extends Property | ||
*/ | ||
function Measure() { | ||
Property.apply(this, arguments); | ||
} | ||
Measure.prototype = extend(Property, { | ||
/** | ||
* Return a wrapped descriptor. | ||
* | ||
* @param {Object} descriptor | ||
* @return {Object} | ||
*/ | ||
wrap: function(descriptor) { | ||
debug('wrap measure', this.name); | ||
var clone = Object.assign({}, descriptor); | ||
var value = descriptor.value; | ||
var get = descriptor.get; | ||
var self = this; | ||
if (typeof value == 'function') { | ||
clone.value = function() { | ||
debug('measure', self.name); | ||
self.test(self.strictdom, this, arguments); | ||
return value.apply(this, arguments); | ||
}; | ||
} else if (get) { | ||
clone.get = function() { | ||
debug('measure', self.name); | ||
self.test(self.strictdom, this, arguments); | ||
return get.apply(this, arguments); | ||
}; | ||
} | ||
return clone; | ||
}, | ||
/** | ||
* Throws an Error if the element is attached | ||
* and StrictDOM is not in the 'measure' phase. | ||
* | ||
* If methods/properties are used without | ||
* a context (eg. `getComputedStyle()` instead | ||
* of `window.getComputedStyle()`) we infer | ||
* a `window` context. | ||
* | ||
* @param {StrictDom} strictdom | ||
* @param {Node} ctx | ||
*/ | ||
test: function(strictdom, ctx) { | ||
if (isAttached(ctx || window) && strictdom.not('measure')) { | ||
throw error(2, this.name); | ||
} | ||
} | ||
}); | ||
/** | ||
* A wrapper for properties that mutate | ||
* to the DOM, triggering style/reflow | ||
* operations. | ||
* | ||
* Once a `Mutate` property is enabled | ||
* it can only be used when StrictDom | ||
* is in the 'measure' phase, else it | ||
* will throw. | ||
* | ||
* @constructor | ||
* @extends Property | ||
*/ | ||
function Mutate() { | ||
Property.apply(this, arguments); | ||
} | ||
Mutate.prototype = extend(Property, { | ||
/** | ||
* Return a wrapped descriptor. | ||
* | ||
* @param {Object} descriptor | ||
* @return {Object} | ||
*/ | ||
wrap: function(descriptor) { | ||
debug('wrap mutate', this.name); | ||
var clone = Object.assign({}, descriptor); | ||
var value = descriptor.value; | ||
var self = this; | ||
if (typeof value == 'function') { | ||
clone.value = function() { | ||
self.test(self.strictdom, this, arguments); | ||
return value.apply(this, arguments); | ||
}; | ||
} else if (descriptor.set) { | ||
clone.set = function() { | ||
self.test(self.strictdom, this, arguments); | ||
return descriptor.set.apply(this, arguments); | ||
}; | ||
} | ||
return clone; | ||
}, | ||
/** | ||
* Throws an Error if the element is attached | ||
* and StrictDOM is not in the 'mutate' phase. | ||
* | ||
* If methods/properties are used without | ||
* a context (eg. `getComputedStyle()` instead | ||
* of `window.getComputedStyle()`) we infer | ||
* a `window` context. | ||
* | ||
* @param {StrictDom} strictdom | ||
* @param {Node} ctx | ||
*/ | ||
test: function(strictdom, ctx) { | ||
if (isAttached(ctx || window) && strictdom.not('mutate')) { | ||
throw error(3, this.name); | ||
} | ||
} | ||
}); | ||
/** | ||
* A wrapper for 'accessor' (get/set) properties. | ||
* | ||
* An `Accessor` should be used to wrap | ||
* properties that can both measure and mutate | ||
* the DOM (eg. `element.scrollTop`). | ||
* | ||
* @constructor | ||
* @extends Property | ||
*/ | ||
function Accessor() { | ||
Property.apply(this, arguments); | ||
} | ||
Accessor.prototype = extend(Property, { | ||
/** | ||
* Return a wrapped descriptor. | ||
* | ||
* @param {Object} descriptor | ||
* @return {Object} | ||
*/ | ||
wrap: function(descriptor) { | ||
debug('wrap accessor', this.name); | ||
var clone = Object.assign({}, descriptor); | ||
var get = descriptor.get; | ||
var set = descriptor.set; | ||
var self = this; | ||
if (get) { | ||
clone.get = function() { | ||
self.testRead(self.strictdom, this, arguments); | ||
return get.apply(this, arguments); | ||
}; | ||
} | ||
if (descriptor.set) { | ||
clone.set = function() { | ||
self.testWrite(self.strictdom, this, arguments); | ||
return set.apply(this, arguments); | ||
}; | ||
} | ||
return clone; | ||
}, | ||
testRead: Measure.prototype.test, | ||
testWrite: Mutate.prototype.test | ||
}); | ||
/** | ||
* A wrapper for 'value' properties. | ||
* | ||
* A `Value` should be used to wrap special | ||
* values that like `window.innerWidth`, which | ||
* in Chrome (not Gecko) are not normal 'getter' | ||
* functions, but magical flat getters. | ||
* | ||
* Value wrappers are a for very special cases. | ||
* | ||
* @constructor | ||
* @extends Property | ||
*/ | ||
function Value() { | ||
Property.apply(this, arguments); | ||
} | ||
Value.prototype = extend(Property, { | ||
/** | ||
* Calling `Object.getOwnDescriptor()` can | ||
* trigger a reflow as it returns the `value` | ||
* of the property. So here we just | ||
* return an empty object instead. | ||
* | ||
* @return {Object} | ||
* @private | ||
*/ | ||
getDescriptor: function() { | ||
return {}; | ||
}, | ||
/** | ||
* Value wrappers are disabled by simply | ||
* deleting them from the instance, | ||
* revealing the original descriptor. | ||
* | ||
* @private | ||
*/ | ||
disable: function() { | ||
delete this.object[this.name]; | ||
}, | ||
/** | ||
* Return a wrapped descriptor. | ||
* | ||
* `Value` properties are actually on the | ||
* instance of objects. To wrap them we need | ||
* to replace them with a getter which | ||
* deletes itself on access, call into the v8 | ||
* interceptor, and then add themselves back. | ||
* | ||
* This won't be fast, but these are rarely | ||
* accessed so it should be fine. | ||
* | ||
* @param {Object} descriptor | ||
* @return {Object} | ||
*/ | ||
wrap: function(descriptor) { | ||
debug('wrap value'); | ||
var name = this.name; | ||
var self = this; | ||
descriptor.get = function() { | ||
debug('get value', name); | ||
self.test(self.strictdom, this, arguments); | ||
self.disable(); | ||
var result = this[name]; | ||
self.enable(); | ||
return result; | ||
}; | ||
return descriptor; | ||
}, | ||
test: Measure.prototype.test | ||
}); | ||
function Style() { | ||
Property.apply(this, arguments); | ||
} | ||
Style.prototype = extend(Property, { | ||
wrap: function(descriptor) { | ||
debug('wrap style'); | ||
var strictdom = this.strictdom; | ||
var clone = Object.assign({}, descriptor); | ||
clone.get = function() { return new StrictStyle(this, strictdom); }; | ||
return clone; | ||
} | ||
}); | ||
function ClassList() { | ||
Property.apply(this, arguments); | ||
} | ||
ClassList.prototype = extend(Property, { | ||
wrap: function(descriptor) { | ||
debug('wrap style'); | ||
var strictdom = this.strictdom; | ||
var clone = Object.assign({}, descriptor); | ||
clone.get = function() { return new StrictClassList(this, strictdom); }; | ||
return clone; | ||
} | ||
}); | ||
function StrictStyle(el, strictdom) { | ||
this.strictdom = strictdom; | ||
this.el = el; | ||
} | ||
StrictStyle.prototype = { | ||
_getter: getDescriptor(HTMLElement.prototype, 'style').get, | ||
_get: function() { | ||
return this._getter.call(this.el); | ||
}, | ||
setProperty: function(key, value) { | ||
var illegal = isAttached(this.el) && this.strictdom.not('mutate'); | ||
if (illegal) throw error(1, 'style.' + key); | ||
return this._get()[key] = value; | ||
}, | ||
removeProperty: function(key) { | ||
var illegal = isAttached(this.el) && this.strictdom.not('mutate'); | ||
if (illegal) throw error(1, 'style.' + key); | ||
return this._get().removeProperty(key); | ||
} | ||
}; | ||
// dynamically construct prototype | ||
// from real element.style | ||
(function() { | ||
var styles = document.createElement('div').style; | ||
var proto = {}; | ||
for (var key in styles) { | ||
if (styles[key] === '') { | ||
Object.defineProperty(StrictStyle.prototype, key, { | ||
get: getter(key), | ||
set: setter(key) | ||
}); | ||
} | ||
} | ||
[ | ||
'item', | ||
'getPropertyValue', | ||
'getPropertyCSSValue', | ||
'getPropertyPriority' | ||
].forEach(function(method) { | ||
StrictStyle.prototype[method] = caller(method); | ||
}); | ||
function getter(key) { | ||
return function() { | ||
return this._get()[key]; | ||
}; | ||
} | ||
function setter(key) { | ||
return function(value) { | ||
var illegal = isAttached(this.el) && this.strictdom.not('mutate'); | ||
if (illegal) throw error(1, 'style.' + key); | ||
return this.setProperty(key, value); | ||
}; | ||
} | ||
function caller(key) { | ||
return function() { | ||
var style = this._get(); | ||
return style[key].apply(style, arguments); | ||
}; | ||
} | ||
return proto; | ||
})(); | ||
function StrictClassList(el, strictdom) { | ||
this.strictdom = strictdom; | ||
this.el = el; | ||
} | ||
StrictClassList.prototype = { | ||
_getter: getDescriptor(Element.prototype, 'classList').get, | ||
_get: function() { return this._getter.call(this.el); }, | ||
add: function(className) { | ||
var illegal = isAttached(this.el) && this.strictdom.not('mutate'); | ||
if (illegal) throw error(1, 'class names'); | ||
this._get().add(className); | ||
}, | ||
contains: function(className) { | ||
return this._get().contains(className); | ||
}, | ||
remove: function(className) { | ||
var illegal = isAttached(this.el) && this.strictdom.not('mutate'); | ||
if (illegal) throw error(1, 'class names'); | ||
this._get().remove(className); | ||
}, | ||
toggle: function() { | ||
var illegal = isAttached(this.el) && this.strictdom.not('mutate'); | ||
if (illegal) throw error(1, 'class names'); | ||
var classList = this._get(); | ||
return classList.toggle.apply(classList, arguments); | ||
} | ||
}; | ||
/** | ||
* Utils | ||
*/ | ||
function error(type) { | ||
return new Error({ | ||
1: 'Can only set ' + arguments[1] + ' during \'mutate\' phase', | ||
2: 'Can only get ' + arguments[1] + ' during \'measure\' phase', | ||
3: 'Can only call `.' + arguments[1] + '()` during \'mutate\' phase', | ||
4: 'Invalid phase: ' + arguments[1] | ||
}[type]); | ||
} | ||
function getDescriptor(object, prop) { | ||
return Object.getOwnPropertyDescriptor(object, prop); | ||
} | ||
function extend(parent, props) { | ||
return Object.assign(Object.create(parent.prototype), props); | ||
} | ||
function isAttached(el) { | ||
return el === window || document.contains(el); | ||
} | ||
/** | ||
* Exports | ||
*/ | ||
// Only ever allow one `StrictDom` per document | ||
var exports = window['strictdom'] = (window['strictdom'] || new StrictDom(window)); // jshint ignore:line | ||
// CJS & AMD support | ||
if (("function")[0] == 'f') !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { return exports; }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); | ||
else if ((typeof module)[0] == 'o') module.exports = exports; | ||
})(); | ||
/***/ }, | ||
/* 2 */ | ||
/***/ function(module, exports) { | ||
module.exports = __WEBPACK_EXTERNAL_MODULE_1__; | ||
module.exports = __WEBPACK_EXTERNAL_MODULE_2__; | ||
@@ -117,0 +960,0 @@ /***/ } |
@@ -59,3 +59,3 @@ !(function(win) { | ||
debug('measure'); | ||
var task = { fn: fn, ctx: ctx }; | ||
var task = !ctx ? fn : fn.bind(ctx); | ||
this.reads.push(task); | ||
@@ -76,3 +76,3 @@ scheduleFlush(this); | ||
debug('mutate'); | ||
var task = { fn: fn, ctx: ctx }; | ||
var task = !ctx ? fn : fn.bind(ctx); | ||
this.writes.push(task); | ||
@@ -208,3 +208,3 @@ scheduleFlush(this); | ||
debug('run tasks'); | ||
var task; while (task = tasks.shift()) task.fn.call(task.ctx); | ||
var task; while (task = tasks.shift()) task(); | ||
} | ||
@@ -211,0 +211,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(t){"use strict";function e(){var e=this;e.reads=[],e.writes=[],e.raf=a.bind(t)}function n(t){t.scheduled||(t.scheduled=!0,t.raf(i.bind(null,t)))}function i(t){var e,i=t.writes,o=t.reads;try{r(o),r(i)}catch(s){e=s}if(t.scheduled=!1,(o.length||i.length)&&n(t),e){if(!t["catch"])throw e;t["catch"](e)}}function r(t){for(var e;e=t.shift();)e.fn.call(e.ctx)}function o(t,e){var n=t.indexOf(e);return!!~n&&!!t.splice(n,1)}function s(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])}var a=t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.msRequestAnimationFrame||function(t){return setTimeout(t,16)};e.prototype={constructor:e,measure:function(t,e){var i={fn:t,ctx:e};return this.reads.push(i),n(this),i},mutate:function(t,e){var i={fn:t,ctx:e};return this.writes.push(i),n(this),i},clear:function(t){return o(this.reads,t)||o(this.writes,t)},extend:function(t){if("object"!=typeof t)throw new Error("expected object");var e=Object.create(this);return s(e,t),e.fastdom=this,e.initialize&&e.initialize(),e},"catch":null};var exports=t.fastdom=t.fastdom||new e;"f"==(typeof define)[0]?define(function(){return exports}):"o"==(typeof module)[0]&&(module.exports=exports)}(this); | ||
!function(t){"use strict";function e(){var e=this;e.reads=[],e.writes=[],e.raf=a.bind(t)}function n(t){t.scheduled||(t.scheduled=!0,t.raf(i.bind(null,t)))}function i(t){var e,i=t.writes,o=t.reads;try{r(o),r(i)}catch(s){e=s}if(t.scheduled=!1,(o.length||i.length)&&n(t),e){if(!t["catch"])throw e;t["catch"](e)}}function r(t){for(var e;e=t.shift();)e()}function o(t,e){var n=t.indexOf(e);return!!~n&&!!t.splice(n,1)}function s(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])}var a=t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||t.msRequestAnimationFrame||function(t){return setTimeout(t,16)};e.prototype={constructor:e,measure:function(t,e){var i=e?t.bind(e):t;return this.reads.push(i),n(this),i},mutate:function(t,e){var i=e?t.bind(e):t;return this.writes.push(i),n(this),i},clear:function(t){return o(this.reads,t)||o(this.writes,t)},extend:function(t){if("object"!=typeof t)throw new Error("expected object");var e=Object.create(this);return s(e,t),e.fastdom=this,e.initialize&&e.initialize(),e},"catch":null};var exports=t.fastdom=t.fastdom||new e;"f"==(typeof define)[0]?define(function(){return exports}):"o"==(typeof module)[0]&&(module.exports=exports)}(this); |
{ | ||
"name": "fastdom", | ||
"description": "Eliminates layout thrashing by batching DOM read/write operations", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"main": "fastdom.js", | ||
@@ -6,0 +6,0 @@ "scripts": { |
Sorry, the diff of this file is not supported yet
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
44845
1280