diff --git a/demos/hello-guest.js b/demos/hello-guest.js index af4c76f..3c043cd 100644 --- a/demos/hello-guest.js +++ b/demos/hello-guest.js @@ -1,5 +1,6 @@ var div = document.createElement('div'); var span = document.createElement('span'); span.innerHTML = 'Hello, TreeHouse!'; +div.style.color = 'red'; div.appendChild(span); document.getElementById('root').appendChild(div); diff --git a/src/loader.js b/src/loader.js index 4e87877..8aa8649 100644 --- a/src/loader.js +++ b/src/loader.js @@ -19,6 +19,34 @@ var initBroker; 'undefined', 'unescape', 'webkitURL', 'win', 'window', 'doc', 'document', 'initBroker' ]; + var styleAttributeList = [ + 'azimuth', 'backgroundAttachment', 'backgroundColor', 'backgroundImage', + 'backgroundPosition', 'backgroundRepeat', 'background', + 'borderCollapse', 'borderColor', 'borderSpacing', 'borderStyle', + 'borderTop', 'borderRight', 'borderBottom', 'borderLeft', + 'borderTopColor', 'borderRightColor', 'borderBottomColor', + 'borderLeftColor', 'borderTopStyle', 'borderRightStyle', + 'borderBottomStyle', 'borderLeftStyle', 'borderTopWidth', + 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth', + 'borderWidth', 'border', 'bottom', 'captionSide', 'clear', 'clip', + 'color', 'content', 'counterIncrement', 'counterReset', 'cueAfter', + 'cueBefore', 'cue', 'cursor', 'direction', 'display', 'elevation', + 'emptyCells', 'float', 'fontFamily', 'fontSize', 'fontStyle', + 'fontVariant', 'fontWeight', 'font', 'height', 'left', 'letterSpacing', + 'lineHeight', 'listStyleImage', 'listStylePostion', 'listStyleType', + 'listStyle', 'margin', 'marginTop', 'marginRight', 'marginBottom', + 'marginLeft', 'maxHeight', 'maxWidth', 'minHeight', 'minWidth', + 'orphans', 'outlineColor', 'outlineStyle', 'outlineWidth', 'outline', + 'overflow', 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', + 'paddingLeft', 'pageBreakAfter', 'pageBreakBefore', 'pageBreakInside', + 'pauseAfter', 'pauseBefore', 'pause', 'pitchRange', 'pitch', + 'playDuring', 'position', 'quotes', 'richness', 'right', 'speakHeader', + 'speakNumeral', 'speakPunctuation', 'speak', 'speechRate', 'stress', + 'tableLayout', 'textAlign', 'textDecoration', 'textIndent', + 'textTransform', 'top', 'unicodeBidi', 'verticalAlign', 'visibility', + 'voiceFamily', 'volume', 'whiteSpace', 'widows', 'width', 'wordSpacing', + 'zIndex' + ]; var blacklist = ['Worker']; var nop = function (){}; var ignored = {}; @@ -180,15 +208,8 @@ var initBroker; * an attribute on the element */ function hookStyleProperty(property) { - // propertyName -> data-treehouse-style-property-name var name = STYLE_ATTRIBUTE_PREFIX + util.camelCaseToDashed(property); - if (hookedStyles[property]) { - // already hooked - return; - } - - hookedStyles[property] = true; Object.defineProperty(CSSStyleDeclaration.prototype, property, { set: function (newValue) { this._element.setAttribute(name, newValue); @@ -198,22 +219,7 @@ var initBroker; } }); } - - // Export style properties in the base policy - for (k in basePolicy['!elements']['!attributes']) { - for (m in basePolicy['!elements']['!attributes'][k].style) { - hookStyleProperty(k); - } - } - - // Export any style properties that don't appear in the base policy - for (k in policy['!elements']['!attributes']) { - for (m in policy['!elements']['!attributes'][k].style) { - hookStyleProperty(k); - } - } - - // XXX: setPolicy needs to do this too + _.each(styleAttributeList, hookStyleProperty); // Wrap addEventListener so that we can ask the monitor to install // listeners in the actual DOM @@ -285,18 +291,14 @@ var initBroker; // TODO: if the new node has onfoo handers, register them and delete the attributes // from the serialized node - if (e.attrChange === MutationEvent.prototype.ADDITION) { - // When adding a node to the DOM, serialize the node and append - // it to the traversal - target = serialization.serializeNode(e.target); - // get the traversal from the root node to the parent - related = serialization.getNodeTraversal(e.relatedNode, document.body).slice(1); - e = serialization.serializeEvent(e, document.body); - e.target.push(target); - e.relatedNode = e.relatedNode.concat(related); - } else { - e = serialization.serializeEvent(e, document.body); - } + // get the traversal from the root node to the parent + related = serialization.getNodeTraversal(e.relatedNode, document.body).slice(1); + // get the serialized representation of the target node + target = serialization.serializeNode(e.target); + e = serialization.serializeEvent(e, document.body); + // append the serialized node to its traversal + e.target.push(target); + e.relatedNode = related; if (!validate.checkDOMMutation(policy, e, document.body)) { terminate('VDOM modification violates policy', e); diff --git a/src/sandbox.js b/src/sandbox.js index d5ce1cb..b2e6921 100644 --- a/src/sandbox.js +++ b/src/sandbox.js @@ -10,6 +10,7 @@ function(serialization, SortedSet, validate, basePolicy) { var ev = document.createEvent('CustomEvent'); var serializedTarget = e.target; var rootNode = this._children.get(serializedTarget.shift()); + var serializedTargetNode; if (e.type !== 'DOMSubtreeModified') { return; @@ -19,16 +20,16 @@ function(serialization, SortedSet, validate, basePolicy) { this.onPolicyViolation(); } + serializedTargetNode = e.target.pop(); + if (e.attrChange === MutationEvent.ADDITION) { // the last element of the target is the new node to add - e.target = serialization.deserializeNode(serializedTarget.pop()); - e.__serializedTarget = serializedTarget.slice(0); + e.target = serialization.deserializeNode(serializedTargetNode); e.target.__treehouseNextSibling = serialization.traverseToNode( serializedTarget, rootNode); } - e = serialization.deserializeEvent(e, this._children.get()); - e.__serializedTarget = serializedTarget; + e = serialization.deserializeEvent(e, rootNode); this.debug('Deserialized received event', e); ev.initCustomEvent('sandboxDOMEvent', true, true, e); ev.detail.sandbox = this;