driver-worker
Advanced tools
Comparing version 0.6.3 to 0.6.4
@@ -178,3 +178,3 @@ 'use strict'; | ||
set: function set(text) { | ||
mutation(this, 'characterData', { oldValue: this.data }); | ||
mutation(this, 'characterData', { newValue: text }); | ||
this.data = text; | ||
@@ -224,3 +224,5 @@ }, | ||
value: function setAttribute(key, value) { | ||
this.setAttributeNS(null, key, value); | ||
if (value !== this.getAttribute(key)) { | ||
this.setAttributeNS(null, key, value); | ||
} | ||
} | ||
@@ -251,4 +253,3 @@ }, { | ||
} | ||
mutation(this, 'attributes', { attributeName: name }); | ||
mutation(this, 'attributes', { attributeName: name, newValue: value }); | ||
} | ||
@@ -271,3 +272,3 @@ }, { | ||
(this.eventListeners[toLower(type)] || (this.eventListeners[toLower(type)] = [])).push(handler); | ||
mutation(this, 'events', { eventName: type }); | ||
mutation(this, 'addEvent', { eventName: type }); | ||
} | ||
@@ -278,3 +279,3 @@ }, { | ||
splice(this.eventListeners[toLower(type)], handler, 0, true); | ||
mutation(this, 'events', { eventName: type }); | ||
mutation(this, 'removeEvent', { eventName: type }); | ||
} | ||
@@ -284,6 +285,6 @@ }, { | ||
value: function dispatchEvent(event) { | ||
var t = event.currentTarget = this, | ||
c = event.cancelable, | ||
l = void 0, | ||
i = void 0; | ||
var t = event.currentTarget = this; | ||
var c = event.cancelable; | ||
var l = void 0; | ||
var i = void 0; | ||
do { | ||
@@ -363,2 +364,92 @@ l = t.eventListeners && t.eventListeners[toLower(event.type)]; | ||
var CanvasRenderingContext2D = function CanvasRenderingContext2D(vnode) { | ||
var _this5 = this; | ||
_classCallCheck(this, CanvasRenderingContext2D); | ||
this.canvas = vnode; | ||
var propertyValues = { | ||
fillStyle: '#000000', | ||
filter: 'none', | ||
font: '10px sans-serif', | ||
globalAlpha: 1, | ||
globalCompositeOperation: 'source-over', | ||
imageSmoothingEnabled: true, | ||
imageSmoothingQuality: 'low', | ||
lineCap: 'butt', | ||
lineDashOffset: 0, | ||
lineJoin: 'miter', | ||
lineWidth: 1, | ||
miterLimit: 10, | ||
shadowBlur: 0, | ||
shadowColor: 'rgba(0, 0, 0, 0)', | ||
shadowOffsetX: 0, | ||
shadowOffsetY: 0, | ||
strokeStyle: '#000000', | ||
textAlign: 'start', | ||
textBaseline: 'alphabetic' | ||
}; | ||
// context properties | ||
var properties = ['direction', 'fillStyle', 'filter', 'font', 'globalAlpha', 'globalCompositeOperation', 'imageSmoothingEnabled', 'imageSmoothingQuality', 'lineCap', 'lineDashOffset', 'lineJoin', 'lineWidth', 'miterLimit', 'shadowBlur', 'shadowColor', 'shadowOffsetX', 'shadowOffsetY', 'strokeStyle', 'textAlign', 'textBaseline']; | ||
properties.forEach(function (property) { | ||
Object.defineProperty(_this5, property, { | ||
get: function get() { | ||
return propertyValues[property]; | ||
}, | ||
set: function set(value) { | ||
propertyValues[property] = value; | ||
} | ||
}); | ||
}); | ||
// context api | ||
var methods = ['arc', 'arcTo', 'addHitRegion', 'beginPath', 'bezierCurveTo', 'clearHitRegions', 'clearRect', 'clip', 'closePath', 'createImageData', 'createLinearGradient', 'createPattern', 'createRadialGradient', 'drawFocusIfNeeded', 'drawImage', 'drawWidgetAsOnScreen', 'drawWindow', 'ellipse', 'fill', 'fillRect', 'fillText', 'getImageData', 'getLineDash', 'isPointInPath', 'isPointInStroke', 'lineTo', 'measureText', 'moveTo', 'putImageData', 'quadraticCurveTo', 'rect', 'removeHitRegion', 'resetTransform', 'restore', 'rotate', 'save', 'scale', 'scrollPathIntoView', 'setLineDash', 'setTransform', 'stroke', 'strokeRect', 'strokeText', 'transform', 'translate']; | ||
methods.forEach(function (method) { | ||
_this5[method] = function () { | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
mutation(vnode, 'canvasRenderingContext2D', { | ||
method: method, | ||
args: args, | ||
properties: propertyValues | ||
}); | ||
}; | ||
}); | ||
}; | ||
var CanvasElement = function (_Element2) { | ||
_inherits(CanvasElement, _Element2); | ||
function CanvasElement() { | ||
var _ref; | ||
_classCallCheck(this, CanvasElement); | ||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
return _possibleConstructorReturn(this, (_ref = CanvasElement.__proto__ || Object.getPrototypeOf(CanvasElement)).call.apply(_ref, [this].concat(args))); | ||
} | ||
_createClass(CanvasElement, [{ | ||
key: 'getContext', | ||
value: function getContext(contextType) { | ||
if (contextType === '2d') { | ||
return new CanvasRenderingContext2D(this); | ||
} else { | ||
return {}; | ||
} | ||
} | ||
}]); | ||
return CanvasElement; | ||
}(Element); | ||
function createComment(content) { | ||
@@ -369,2 +460,5 @@ return new Comment(content); | ||
function createElement(type) { | ||
if (type === 'canvas') { | ||
return new CanvasElement(null, String(type).toUpperCase()); | ||
} | ||
return new Element(null, String(type).toUpperCase()); | ||
@@ -371,0 +465,0 @@ } |
@@ -19,3 +19,4 @@ 'use strict'; | ||
var TEXT_CONTENT_ATTR = 'textContent' in document ? 'textContent' : 'nodeValue'; | ||
var TEXT_CONTENT = 'textContent'; | ||
var TEXT_CONTENT_ATTR = TEXT_CONTENT in document ? TEXT_CONTENT : 'nodeValue'; | ||
var EVENT_OPTIONS = supportsPassive ? { | ||
@@ -33,2 +34,3 @@ capture: true, | ||
var registeredEventCounts = {}; | ||
var canvasCache = {}; | ||
@@ -41,3 +43,3 @@ function getNode(node) { | ||
function addEvent(name) { | ||
function _addEvent(name) { | ||
var registeredCount = registeredEventCounts[name]; | ||
@@ -54,3 +56,3 @@ | ||
function removeEvent() { | ||
function _removeEvent() { | ||
registeredEventCounts[name]--; | ||
@@ -110,2 +112,3 @@ if (registeredEventCounts[name] === 0) { | ||
} | ||
if (vnode.style) { | ||
@@ -118,2 +121,3 @@ for (var i in vnode.style) { | ||
} | ||
if (vnode.attributes) { | ||
@@ -130,2 +134,3 @@ for (var _i = 0; _i < vnode.attributes.length; _i++) { | ||
} | ||
if (vnode.childNodes) { | ||
@@ -136,5 +141,6 @@ for (var _i2 = 0; _i2 < vnode.childNodes.length; _i2++) { | ||
} | ||
if (vnode.events) { | ||
for (var _i3 = 0; _i3 < vnode.events.length; _i3++) { | ||
addEvent(vnode.events[_i3]); | ||
_addEvent(vnode.events[_i3]); | ||
} | ||
@@ -180,20 +186,13 @@ } | ||
var target = _ref3.target, | ||
attributeName = _ref3.attributeName; | ||
attributeName = _ref3.attributeName, | ||
newValue = _ref3.newValue; | ||
// TODO performance optimize | ||
var vnode = target; | ||
var val = void 0; | ||
for (var i = vnode.attributes.length; i--;) { | ||
var p = vnode.attributes[i]; | ||
if (p.name === attributeName) { | ||
val = p.value; | ||
break; | ||
} | ||
} | ||
// TODO attributes remove handle | ||
var node = getNode(vnode); | ||
if ((typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') { | ||
node[attributeName] = val; | ||
if (newValue == null) { | ||
node.removeAttribute(attributeName); | ||
} else if ((typeof newValue === 'undefined' ? 'undefined' : _typeof(newValue)) === 'object') { | ||
node[attributeName] = newValue; | ||
} else { | ||
node.setAttribute(attributeName, val); | ||
node.setAttribute(attributeName, newValue); | ||
} | ||
@@ -203,87 +202,54 @@ }, | ||
var target = _ref4.target, | ||
oldValue = _ref4.oldValue; | ||
newValue = _ref4.newValue; | ||
var vnode = target; | ||
var node = getNode(vnode); | ||
node[TEXT_CONTENT_ATTR] = vnode.data; | ||
node[TEXT_CONTENT_ATTR] = newValue; | ||
}, | ||
events: function events(_ref5) { | ||
addEvent: function addEvent(_ref5) { | ||
var target = _ref5.target, | ||
eventName = _ref5.eventName; | ||
addEvent(eventName); | ||
} | ||
}; | ||
_addEvent(eventName); | ||
}, | ||
removeEvent: function removeEvent(_ref6) { | ||
var target = _ref6.target, | ||
eventName = _ref6.eventName; | ||
function applyMutation(mutation) { | ||
MUTATIONS[mutation.type](mutation); | ||
} | ||
_removeEvent(eventName); | ||
}, | ||
canvasRenderingContext2D: function canvasRenderingContext2D(_ref7) { | ||
var target = _ref7.target, | ||
method = _ref7.method, | ||
args = _ref7.args, | ||
properties = _ref7.properties; | ||
var timer = void 0; | ||
var MUTATION_QUEUE = []; | ||
var vnode = target; | ||
var canvas = getNode(vnode); | ||
var context = canvas.getContext('2d'); | ||
if (!window.requestIdleCallback) { | ||
var IDLE_TIMEOUT = 10; | ||
window.requestIdleCallback = function (cb) { | ||
var start = Date.now(); | ||
setTimeout(function () { | ||
return cb({ | ||
timeRemaining: function timeRemaining() { | ||
return Math.max(0, IDLE_TIMEOUT - (Date.now() - start)); | ||
if (properties) { | ||
for (var key in properties) { | ||
if (properties.hasOwnProperty(key)) { | ||
context[key] = properties[key]; | ||
} | ||
}); | ||
}, 1); | ||
}; | ||
} | ||
function processMutationQueue(deadline) { | ||
clearTimeout(timer); | ||
var q = MUTATION_QUEUE; | ||
var start = Date.now(); | ||
var isDeadline = deadline && deadline.timeRemaining; | ||
var cache = {}; | ||
var i = void 0; | ||
for (i = 0; i < q.length; i++) { | ||
if (isDeadline ? deadline.timeRemaining() <= 0 : Date.now() - start > 1) break; | ||
var m = q[i]; | ||
applyMutation(q.splice(i--, 1)[0]); | ||
} | ||
if (q.length) doProcessMutationQueue(); | ||
} | ||
function doProcessMutationQueue() { | ||
clearTimeout(timer); | ||
timer = setTimeout(processMutationQueue, 100); | ||
requestIdleCallback(processMutationQueue); | ||
} | ||
function queueMutation(mutation) { | ||
if (mutation.type === 'characterData' || mutation.type === 'attributes') { | ||
for (var i = MUTATION_QUEUE.length; i--;) { | ||
var m = MUTATION_QUEUE[i]; | ||
if (m.type == mutation.type && m.target.$$id == mutation.target.$$id) { | ||
if (m.type === 'attributes') { | ||
MUTATION_QUEUE.splice(i + 1, 0, mutation); | ||
} else { | ||
MUTATION_QUEUE[i] = mutation; | ||
} | ||
return; | ||
} | ||
} | ||
if (method) { | ||
context[method].apply(context, args); | ||
} | ||
} | ||
if (MUTATION_QUEUE.push(mutation) === 1) { | ||
doProcessMutationQueue(); | ||
} | ||
} | ||
}; | ||
worker.onmessage = function (_ref6) { | ||
var data = _ref6.data; | ||
worker.onmessage = function (_ref8) { | ||
var data = _ref8.data; | ||
var type = data.type; | ||
if (type === 'MutationRecord') { | ||
for (var i = 0; i < data.mutations.length; i++) { | ||
queueMutation(data.mutations[i]); | ||
var mutations = data.mutations; | ||
for (var i = 0; i < mutations.length; i++) { | ||
// apply mutation | ||
var mutation = mutations[i]; | ||
MUTATIONS[mutation.type](mutation); | ||
} | ||
@@ -290,0 +256,0 @@ } |
@@ -7,2 +7,4 @@ 'use strict'; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
@@ -18,4 +20,5 @@ | ||
var TO_SANITIZE = ['addedNodes', 'removedNodes', 'nextSibling', 'previousSibling', 'target']; | ||
var ELEMENT_NODE = 1; | ||
var TEXT_NODE = 3; | ||
var COMMENT_NODE = 8; | ||
var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML'; | ||
@@ -27,6 +30,20 @@ var CLASS_NAME = 'className'; | ||
var EVENT_PREFIX_REGEXP = /^on[A-Z]/; | ||
var BODY = 'BODY'; | ||
var ADD_EVENT = 'addEvent'; | ||
var REMOVE_EVENT = 'removeEvent'; | ||
var TO_SANITIZE = ['target', 'addedNodes', 'removedNodes', 'nextSibling', 'previousSibling']; | ||
var UPPERCASE_REGEXP = /[A-Z]/g; | ||
var CSSPropCache = {}; | ||
function styleToCSS(style) { | ||
var css = ''; | ||
for (var prop in style) { | ||
var val = style[prop]; | ||
prop = CSSPropCache[prop] ? CSSPropCache[prop] : CSSPropCache[prop] = prop.replace(UPPERCASE_REGEXP, '-$&').toLowerCase(); | ||
css = css + (prop + ':' + val + ';'); | ||
} | ||
return css; | ||
} | ||
exports.default = function (_ref) { | ||
@@ -47,3 +64,3 @@ var postMessage = _ref.postMessage, | ||
if (!id) return null; | ||
if (node.nodeName === 'BODY') return document.body; | ||
if (node.nodeName === BODY) return document.body; | ||
return NODES.get(id); | ||
@@ -60,28 +77,35 @@ } | ||
function sanitize(obj) { | ||
function sanitize(obj, prop) { | ||
if (!obj || (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object') return obj; | ||
if (Array.isArray(obj)) return obj.map(sanitize); | ||
if (Array.isArray(obj)) return obj.map(function (o) { | ||
return sanitize(o, prop); | ||
}); | ||
if (obj instanceof document.defaultView.Node) { | ||
var id = obj.$$id; | ||
if (!id) { | ||
id = obj.$$id = String(++COUNTER); | ||
} | ||
NODES.set(id, obj); | ||
if (!obj.$$id) { | ||
obj.$$id = String(++COUNTER); | ||
NODES.set(obj.$$id, obj); | ||
} | ||
var out = { | ||
$$id: obj.$$id, | ||
events: Object.keys(obj.eventListeners || {}), | ||
attributes: obj.attributes, | ||
nodeName: obj.nodeName, | ||
nodeType: obj.nodeType, | ||
style: obj.style, | ||
childNodes: obj.childNodes, | ||
data: obj.data | ||
$$id: obj.$$id | ||
}; | ||
if (out.childNodes && out.childNodes.length) { | ||
out.childNodes = sanitize(out.childNodes); | ||
if (obj.nodeName === BODY) { | ||
out.nodeName = BODY; | ||
} else if (prop === 'addedNodes') { | ||
var nodeType = obj.nodeType; | ||
if (nodeType === ELEMENT_NODE) { | ||
out = _extends({}, out, { | ||
events: Object.keys(obj.eventListeners || {}), | ||
attributes: obj.attributes, | ||
nodeName: obj.nodeName, | ||
style: obj.style | ||
}); | ||
} else if (nodeType === TEXT_NODE || nodeType === COMMENT_NODE) { | ||
out.data = obj.data; | ||
} | ||
out.nodeType = nodeType; | ||
} | ||
@@ -97,6 +121,6 @@ | ||
var prop = TO_SANITIZE[j]; | ||
mutation[prop] = sanitize(mutation[prop]); | ||
mutation[prop] = sanitize(mutation[prop], prop); | ||
} | ||
} | ||
send({ type: 'MutationRecord', mutations: mutations }); | ||
postMessage({ type: 'MutationRecord', mutations: mutations }); | ||
}); | ||
@@ -106,6 +130,2 @@ | ||
function send(message) { | ||
postMessage(JSON.parse(JSON.stringify(message))); | ||
} | ||
addEventListener('message', function (_ref2) { | ||
@@ -269,2 +289,4 @@ var data = _ref2.data; | ||
} | ||
// For trigger attribute mutation | ||
node.style.cssText = styleToCSS(node.style); | ||
}, | ||
@@ -271,0 +293,0 @@ beforeRender: function beforeRender() { |
{ | ||
"name": "driver-worker", | ||
"version": "0.6.3", | ||
"version": "0.6.4", | ||
"description": "Worker driver for Rax", | ||
@@ -16,4 +16,4 @@ "license": "BSD-3-Clause", | ||
"dependencies": { | ||
"style-unit": "^0.6.3" | ||
"style-unit": "^0.6.4" | ||
} | ||
} |
@@ -159,3 +159,3 @@ function assign(obj, props) { | ||
set textContent(text) { | ||
mutation(this, 'characterData', { oldValue: this.data }); | ||
mutation(this, 'characterData', { newValue: text }); | ||
this.data = text; | ||
@@ -193,7 +193,11 @@ } | ||
setAttribute(key, value) { | ||
this.setAttributeNS(null, key, value); | ||
if (value !== this.getAttribute(key)) { | ||
this.setAttributeNS(null, key, value); | ||
} | ||
} | ||
getAttribute(key) { | ||
return this.getAttributeNS(null, key); | ||
} | ||
removeAttribute(key) { | ||
@@ -215,5 +219,5 @@ this.removeAttributeNS(null, key); | ||
} | ||
mutation(this, 'attributes', { attributeName: name, newValue: value }); | ||
} | ||
mutation(this, 'attributes', { attributeName: name }); | ||
} | ||
getAttributeNS(ns, name) { | ||
@@ -223,2 +227,3 @@ let attr = findWhere(this.attributes, createAttributeFilter(ns, name)); | ||
} | ||
removeAttributeNS(ns, name) { | ||
@@ -234,13 +239,15 @@ splice(this.attributes, createAttributeFilter(ns, name)); | ||
).push(handler); | ||
mutation(this, 'events', { eventName: type }); | ||
mutation(this, 'addEvent', { eventName: type }); | ||
} | ||
removeEventListener(type, handler) { | ||
splice(this.eventListeners[toLower(type)], handler, 0, true); | ||
mutation(this, 'events', { eventName: type }); | ||
mutation(this, 'removeEvent', { eventName: type }); | ||
} | ||
dispatchEvent(event) { | ||
let t = event.currentTarget = this, | ||
c = event.cancelable, | ||
l, | ||
i; | ||
let t = event.currentTarget = this; | ||
let c = event.cancelable; | ||
let l; | ||
let i; | ||
do { | ||
@@ -291,2 +298,70 @@ l = t.eventListeners && t.eventListeners[toLower(event.type)]; | ||
class CanvasRenderingContext2D { | ||
constructor(vnode) { | ||
this.canvas = vnode; | ||
let propertyValues = { | ||
fillStyle: '#000000', | ||
filter: 'none', | ||
font: '10px sans-serif', | ||
globalAlpha: 1, | ||
globalCompositeOperation: 'source-over', | ||
imageSmoothingEnabled: true, | ||
imageSmoothingQuality: 'low', | ||
lineCap: 'butt', | ||
lineDashOffset: 0, | ||
lineJoin: 'miter', | ||
lineWidth: 1, | ||
miterLimit: 10, | ||
shadowBlur: 0, | ||
shadowColor: 'rgba(0, 0, 0, 0)', | ||
shadowOffsetX: 0, | ||
shadowOffsetY: 0, | ||
strokeStyle: '#000000', | ||
textAlign: 'start', | ||
textBaseline: 'alphabetic' | ||
}; | ||
// context properties | ||
const properties = ['direction', 'fillStyle', 'filter', 'font', 'globalAlpha', 'globalCompositeOperation', 'imageSmoothingEnabled', 'imageSmoothingQuality', 'lineCap', 'lineDashOffset', 'lineJoin', 'lineWidth', 'miterLimit', 'shadowBlur', 'shadowColor', 'shadowOffsetX', 'shadowOffsetY', 'strokeStyle', 'textAlign', 'textBaseline']; | ||
properties.forEach((property) => { | ||
Object.defineProperty(this, property, { | ||
get: function() { | ||
return propertyValues[property]; | ||
}, | ||
set: function(value) { | ||
propertyValues[property] = value; | ||
} | ||
}); | ||
}); | ||
// context api | ||
const methods = ['arc', 'arcTo', 'addHitRegion', 'beginPath', 'bezierCurveTo', 'clearHitRegions', 'clearRect', 'clip', 'closePath', 'createImageData', 'createLinearGradient', 'createPattern', 'createRadialGradient', 'drawFocusIfNeeded', 'drawImage', 'drawWidgetAsOnScreen', 'drawWindow', 'ellipse', 'fill', 'fillRect', 'fillText', 'getImageData', 'getLineDash', 'isPointInPath', 'isPointInStroke', 'lineTo', 'measureText', 'moveTo', 'putImageData', 'quadraticCurveTo', 'rect', 'removeHitRegion', 'resetTransform', 'restore', 'rotate', 'save', 'scale', 'scrollPathIntoView', 'setLineDash', 'setTransform', 'stroke', 'strokeRect', 'strokeText', 'transform', 'translate']; | ||
methods.forEach((method) => { | ||
this[method] = (...args) => { | ||
mutation(vnode, 'canvasRenderingContext2D', { | ||
method: method, | ||
args: args, | ||
properties: propertyValues | ||
}); | ||
}; | ||
}); | ||
} | ||
} | ||
class CanvasElement extends Element { | ||
constructor(...args) { | ||
super(...args); | ||
} | ||
getContext(contextType) { | ||
if (contextType === '2d') { | ||
return new CanvasRenderingContext2D(this); | ||
} else { | ||
return {}; | ||
} | ||
} | ||
} | ||
function createComment(content) { | ||
@@ -297,2 +372,5 @@ return new Comment(content); | ||
function createElement(type) { | ||
if (type === 'canvas') { | ||
return new CanvasElement(null, String(type).toUpperCase()); | ||
} | ||
return new Element(null, String(type).toUpperCase()); | ||
@@ -345,2 +423,2 @@ } | ||
return createDocument(); | ||
} | ||
} |
@@ -11,3 +11,4 @@ // feature-detect support for event listener options | ||
const TEXT_CONTENT_ATTR = 'textContent' in document ? 'textContent' : 'nodeValue'; | ||
const TEXT_CONTENT = 'textContent'; | ||
const TEXT_CONTENT_ATTR = TEXT_CONTENT in document ? TEXT_CONTENT : 'nodeValue'; | ||
const EVENT_OPTIONS = supportsPassive | ||
@@ -23,2 +24,3 @@ ? { | ||
const registeredEventCounts = {}; | ||
const canvasCache = {}; | ||
@@ -109,2 +111,3 @@ function getNode(node) { | ||
} | ||
if (vnode.style) { | ||
@@ -116,2 +119,3 @@ for (let i in vnode.style) | ||
} | ||
if (vnode.attributes) { | ||
@@ -128,2 +132,3 @@ for (let i = 0; i < vnode.attributes.length; i++) { | ||
} | ||
if (vnode.childNodes) { | ||
@@ -134,2 +139,3 @@ for (let i = 0; i < vnode.childNodes.length; i++) { | ||
} | ||
if (vnode.events) { | ||
@@ -174,96 +180,42 @@ for (let i = 0; i < vnode.events.length; i++) { | ||
}, | ||
attributes({ target, attributeName }) { | ||
// TODO performance optimize | ||
attributes({ target, attributeName, newValue }) { | ||
let vnode = target; | ||
let val; | ||
for (let i = vnode.attributes.length; i--; ) { | ||
let p = vnode.attributes[i]; | ||
if (p.name === attributeName) { | ||
val = p.value; | ||
break; | ||
} | ||
} | ||
// TODO attributes remove handle | ||
let node = getNode(vnode); | ||
if (typeof val === 'object') { | ||
node[attributeName] = val; | ||
if (newValue == null) { | ||
node.removeAttribute(attributeName); | ||
} else if (typeof newValue === 'object') { | ||
node[attributeName] = newValue; | ||
} else { | ||
node.setAttribute(attributeName, val); | ||
node.setAttribute(attributeName, newValue); | ||
} | ||
}, | ||
characterData({ target, oldValue }) { | ||
characterData({ target, newValue }) { | ||
let vnode = target; | ||
let node = getNode(vnode); | ||
node[TEXT_CONTENT_ATTR] = vnode.data; | ||
node[TEXT_CONTENT_ATTR] = newValue; | ||
}, | ||
events({ target, eventName }) { | ||
addEvent({ target, eventName }) { | ||
addEvent(eventName); | ||
} | ||
}; | ||
}, | ||
removeEvent({ target, eventName }) { | ||
removeEvent(eventName); | ||
}, | ||
canvasRenderingContext2D({ target, method, args, properties }) { | ||
let vnode = target; | ||
let canvas = getNode(vnode); | ||
let context = canvas.getContext('2d'); | ||
function applyMutation(mutation) { | ||
MUTATIONS[mutation.type](mutation); | ||
} | ||
let timer; | ||
let MUTATION_QUEUE = []; | ||
if (!window.requestIdleCallback) { | ||
const IDLE_TIMEOUT = 10; | ||
window.requestIdleCallback = cb => { | ||
let start = Date.now(); | ||
setTimeout( | ||
() => | ||
cb({ | ||
timeRemaining: () => | ||
Math.max(0, IDLE_TIMEOUT - (Date.now() - start)) | ||
}), | ||
1 | ||
); | ||
}; | ||
} | ||
function processMutationQueue(deadline) { | ||
clearTimeout(timer); | ||
let q = MUTATION_QUEUE; | ||
let start = Date.now(); | ||
let isDeadline = deadline && deadline.timeRemaining; | ||
let cache = {}; | ||
let i; | ||
for (i = 0; i < q.length; i++) { | ||
if (isDeadline ? deadline.timeRemaining() <= 0 : Date.now() - start > 1) | ||
break; | ||
let m = q[i]; | ||
applyMutation(q.splice(i--, 1)[0]); | ||
} | ||
if (q.length) doProcessMutationQueue(); | ||
} | ||
function doProcessMutationQueue() { | ||
clearTimeout(timer); | ||
timer = setTimeout(processMutationQueue, 100); | ||
requestIdleCallback(processMutationQueue); | ||
} | ||
function queueMutation(mutation) { | ||
if (mutation.type === 'characterData' || mutation.type === 'attributes') { | ||
for (let i = MUTATION_QUEUE.length; i--; ) { | ||
let m = MUTATION_QUEUE[i]; | ||
if (m.type == mutation.type && m.target.$$id == mutation.target.$$id) { | ||
if (m.type === 'attributes') { | ||
MUTATION_QUEUE.splice(i + 1, 0, mutation); | ||
} else { | ||
MUTATION_QUEUE[i] = mutation; | ||
if (properties) { | ||
for (let key in properties) { | ||
if (properties.hasOwnProperty(key)) { | ||
context[key] = properties[key]; | ||
} | ||
return; | ||
} | ||
} | ||
if (method) { | ||
context[method].apply(context, args); | ||
} | ||
} | ||
if (MUTATION_QUEUE.push(mutation) === 1) { | ||
doProcessMutationQueue(); | ||
} | ||
} | ||
}; | ||
@@ -273,4 +225,7 @@ worker.onmessage = ({ data }) => { | ||
if (type === 'MutationRecord') { | ||
for (let i = 0; i < data.mutations.length; i++) { | ||
queueMutation(data.mutations[i]); | ||
let mutations = data.mutations; | ||
for (let i = 0; i < mutations.length; i++) { | ||
// apply mutation | ||
let mutation = mutations[i]; | ||
MUTATIONS[mutation.type](mutation); | ||
} | ||
@@ -285,2 +240,2 @@ } | ||
}); | ||
}; | ||
}; |
import { convertUnit, setRem } from 'style-unit'; | ||
import createDocument from './create-document'; | ||
const TO_SANITIZE = [ | ||
'addedNodes', | ||
'removedNodes', | ||
'nextSibling', | ||
'previousSibling', | ||
'target' | ||
]; | ||
const ELEMENT_NODE = 1; | ||
const TEXT_NODE = 3; | ||
const COMMENT_NODE = 8; | ||
const DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML'; | ||
@@ -18,6 +13,26 @@ const CLASS_NAME = 'className'; | ||
const EVENT_PREFIX_REGEXP = /^on[A-Z]/; | ||
const BODY = 'BODY'; | ||
const ADD_EVENT = 'addEvent'; | ||
const REMOVE_EVENT = 'removeEvent'; | ||
const TO_SANITIZE = [ | ||
'target', | ||
'addedNodes', | ||
'removedNodes', | ||
'nextSibling', | ||
'previousSibling' | ||
]; | ||
const UPPERCASE_REGEXP = /[A-Z]/g; | ||
const CSSPropCache = {}; | ||
function styleToCSS(style) { | ||
let css = ''; | ||
for (var prop in style) { | ||
let val = style[prop]; | ||
prop = CSSPropCache[prop] ? CSSPropCache[prop] : CSSPropCache[prop] = prop.replace(UPPERCASE_REGEXP, '-$&').toLowerCase(); | ||
css = css + `${prop}:${val};`; | ||
} | ||
return css; | ||
} | ||
export default ({ postMessage, addEventListener }) => { | ||
@@ -35,3 +50,3 @@ let document = createDocument(); | ||
if (!id) return null; | ||
if (node.nodeName === 'BODY') return document.body; | ||
if (node.nodeName === BODY) return document.body; | ||
return NODES.get(id); | ||
@@ -48,28 +63,34 @@ } | ||
function sanitize(obj) { | ||
function sanitize(obj, prop) { | ||
if (!obj || typeof obj !== 'object') return obj; | ||
if (Array.isArray(obj)) return obj.map(sanitize); | ||
if (Array.isArray(obj)) return obj.map(o => sanitize(o, prop)); | ||
if (obj instanceof document.defaultView.Node) { | ||
let id = obj.$$id; | ||
if (!id) { | ||
id = obj.$$id = String(++COUNTER); | ||
} | ||
NODES.set(id, obj); | ||
if (!obj.$$id) { | ||
obj.$$id = String(++COUNTER); | ||
NODES.set(obj.$$id, obj); | ||
} | ||
let out = { | ||
$$id: obj.$$id, | ||
events: Object.keys(obj.eventListeners || {}), | ||
attributes: obj.attributes, | ||
nodeName: obj.nodeName, | ||
nodeType: obj.nodeType, | ||
style: obj.style, | ||
childNodes: obj.childNodes, | ||
data: obj.data | ||
$$id: obj.$$id | ||
}; | ||
if (out.childNodes && out.childNodes.length) { | ||
out.childNodes = sanitize(out.childNodes); | ||
if (obj.nodeName === BODY) { | ||
out.nodeName = BODY; | ||
} else if (prop === 'addedNodes') { | ||
let nodeType = obj.nodeType; | ||
if (nodeType === ELEMENT_NODE) { | ||
out = { | ||
...out, | ||
events: Object.keys(obj.eventListeners || {}), | ||
attributes: obj.attributes, | ||
nodeName: obj.nodeName, | ||
style: obj.style, | ||
}; | ||
} else if (nodeType === TEXT_NODE || nodeType === COMMENT_NODE) { | ||
out.data = obj.data; | ||
} | ||
out.nodeType = nodeType; | ||
} | ||
@@ -85,6 +106,6 @@ | ||
let prop = TO_SANITIZE[j]; | ||
mutation[prop] = sanitize(mutation[prop]); | ||
mutation[prop] = sanitize(mutation[prop], prop); | ||
} | ||
} | ||
send({ type: 'MutationRecord', mutations }); | ||
postMessage({ type: 'MutationRecord', mutations }); | ||
}); | ||
@@ -94,6 +115,2 @@ | ||
function send(message) { | ||
postMessage(JSON.parse(JSON.stringify(message))); | ||
} | ||
addEventListener('message', ({ data }) => { | ||
@@ -288,2 +305,4 @@ switch (data.type) { | ||
} | ||
// For trigger attribute mutation | ||
node.style.cssText = styleToCSS(node.style); | ||
}, | ||
@@ -290,0 +309,0 @@ |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
59632
1817
1
Updatedstyle-unit@^0.6.4