it('should escape string', function() {
    var escaped = escapeTextForBrowser('<script type=\'\' src=""></script>');
    expect(escaped).not.toContain('<');
    expect(escaped).not.toContain('>');
    expect(escaped).not.toContain('\'');
    expect(escaped).not.toContain('/');
    expect(escaped).not.toContain('\"');

    escaped = escapeTextForBrowser('&');
    expect(escaped).toBe('&amp;');
  });
Example #2
0
  _createOpenTagMarkup: function() {
    var props = this.props;
    var ret = this._tagOpen;

    for (var propKey in props) {
      if (!props.hasOwnProperty(propKey)) {
        continue;
      }
      var propValue = props[propKey];
      if (propValue == null) {
        continue;
      }
      if (registrationNames[propKey]) {
        putListener(this._rootNodeID, propKey, propValue);
      } else {
        if (propKey === STYLE) {
          if (propValue) {
            propValue = props.style = merge(props.style);
          }
          propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
        }
        var markup =
          DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
        if (markup) {
          ret += ' ' + markup;
        }
      }
    }

    var escapedID = escapeTextForBrowser(this._rootNodeID);
    return ret + ' ' + ReactMount.ATTR_NAME + '="' + escapedID + '">';
  },
Example #3
0
 mountComponent: function(rootID) {
   ReactComponent.Mixin.mountComponent.call(this, rootID);
   return (
     '<span id="' + rootID + '">' +
       escapeTextForBrowser(this.props.text) +
     '</span>'
   );
 },
Example #4
0
var flattenChildrenImpl = function(res, children, nameSoFar) {
  var key, escapedKey;
  if (Array.isArray(children)) {
    for (var i = 0; i < children.length; i++) {
      var child = children[i];
      key = child && (child._key || (child.props && child.props.key));
      escapedKey = key ? escapeTextForBrowser(key) : ('' + i);
      flattenChildrenImpl(
        res,
        child,
        nameSoFar + ':' + escapedKey
      );
    }
  } else {
    var type = typeof children;
    var isOnlyChild = nameSoFar === '';
    var storageName = isOnlyChild ? ONLY_CHILD_NAME : nameSoFar;
    if (children === null || children === undefined || type === 'boolean') {
      res[storageName] = null;
    } else if (children.mountComponentIntoNode) {
      /* We found a component instance */
      if (__DEV__) {
        throwIf(res.hasOwnProperty(storageName), DUPLICATE_KEY_ERROR);
      }
      res[storageName] = children;
    } else {
      if (type === 'object') {
        throwIf(children && children.nodeType === 1, INVALID_CHILD);
        for (key in children) {
          if (children.hasOwnProperty(key)) {
            escapedKey = escapeTextForBrowser(key);
            flattenChildrenImpl(
              res,
              children[key],
              nameSoFar + ':' + escapedKey
            );
          }
        }
      } else if (type === 'string') {
        res[storageName] = new ReactTextComponent(children);
      } else if (type === 'number') {
        res[storageName] = new ReactTextComponent('' + children);
      }
    }
  }
};
  it('should escape object to string', function() {
    var escaped = escapeTextForBrowser({
      toString: function() {
        return 'ponys';
      }
    });

    expect(escaped).toBe('ponys');
  });
 createMarkupForProperty: function(name, value) {
   if (DOMProperty.isStandardName[name]) {
     if (value == null || DOMProperty.hasBooleanValue[name] && !value) {
       return '';
     }
     var attributeName = DOMProperty.getAttributeName[name];
     return processAttributeNameAndPrefix(attributeName) +
       escapeTextForBrowser(value) + '"';
   } else if (DOMProperty.isCustomAttribute(name)) {
     if (value == null) {
       return '';
     }
     return processAttributeNameAndPrefix(name) +
       escapeTextForBrowser(value) + '"';
   } else {
     return null;
   }
 },
Example #7
0
 createMarkupForProperty: function(name, value) {
   if (DOMProperty.isStandardName[name]) {
     if (shouldIgnoreValue(name, value)) {
       return '';
     }
     var attributeName = DOMProperty.getAttributeName[name];
     return processAttributeNameAndPrefix(attributeName) +
       escapeTextForBrowser(value) + '"';
   } else if (DOMProperty.isCustomAttribute(name)) {
     if (value == null) {
       return '';
     }
     return processAttributeNameAndPrefix(name) +
       escapeTextForBrowser(value) + '"';
   } else if (__DEV__) {
     warnUnknownProperty(name);
   }
   return null;
 },
Example #8
0
 mountComponent: function(rootID, transaction, mountDepth) {
   ReactComponent.Mixin.mountComponent.call(
     this,
     rootID,
     transaction,
     mountDepth
   );
   return (
     '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' +
       escapeTextForBrowser(this.props.text) +
     '</span>'
   );
 },
 mountComponent: function(rootID, transaction, mountDepth) {
   ReactComponent.Mixin.mountComponent.call(
     this,
     rootID,
     transaction,
     mountDepth
   );
   return (
     '<span ' + ReactMount.ATTR_NAME + '="' + rootID + '">' +
       escapeTextForBrowser(this.props.text) +
     '</span>'
   );
 },
Example #10
0
  mountComponent: function(rootID, transaction, context) {
    this._rootNodeID = rootID;
    var escapedText = escapeTextForBrowser(this._stringText);

    if (transaction.renderToStaticMarkup) {
      // Normally we'd wrap this in a `span` for the reasons stated above, but
      // since this is a situation where React won't take over (static pages),
      // we can simply return the text as it is.
      return escapedText;
    }

    return (
      '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' +
        escapedText +
      '</span>'
    );
  },
Example #11
0
 _createContentMarkup: function(transaction) {
   // Intentional use of != to avoid catching zero/false.
   var innerHTML = this.props.dangerouslySetInnerHTML;
   if (innerHTML != null) {
     if (innerHTML.__html != null) {
       return innerHTML.__html;
     }
   } else {
     var contentToUse =
       CONTENT_TYPES[typeof this.props.children] ? this.props.children : null;
     var childrenToUse = contentToUse != null ? null : this.props.children;
     if (contentToUse != null) {
       return escapeTextForBrowser(contentToUse);
     } else if (childrenToUse != null) {
       return this.mountMultiChild(
         flattenChildren(childrenToUse),
         transaction
       );
     }
   }
   return '';
 },
Example #12
0
  _createContentMarkup: function(transaction, context) {
    var prefix = '';
    if (this._tag === 'listing' ||
        this._tag === 'pre' ||
        this._tag === 'textarea') {
      // Add an initial newline because browsers ignore the first newline in
      // a <listing>, <pre>, or <textarea> as an "authoring convenience" -- see
      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody.
      prefix = '\n';
    }

    var props = this._currentElement.props;

    // Intentional use of != to avoid catching zero/false.
    var innerHTML = props.dangerouslySetInnerHTML;
    if (innerHTML != null) {
      if (innerHTML.__html != null) {
        return prefix + innerHTML.__html;
      }
    } else {
      var contentToUse =
        CONTENT_TYPES[typeof props.children] ? props.children : null;
      var childrenToUse = contentToUse != null ? null : props.children;
      if (contentToUse != null) {
        return prefix + escapeTextForBrowser(contentToUse);
      } else if (childrenToUse != null) {
        var mountImages = this.mountChildren(
          childrenToUse,
          transaction,
          context
        );
        return prefix + mountImages.join('');
      }
    }
    return prefix;
  },
 createMarkupForID: function(id) {
   return processAttributeNameAndPrefix(DOMProperty.ID_ATTRIBUTE_NAME) +
     escapeTextForBrowser(id) + '"';
 },
Example #14
0
var processAttributeNameAndPrefix = memoizeStringOnly(function(name) {
  return escapeTextForBrowser(name) + '="';
});
Example #15
0
var processStyleName = memoizeStringOnly(function(styleName) {
  return escapeTextForBrowser(hyphenate(styleName));
});
Example #16
0
function assertValidProps(e){e&&(invariant(null==e.children||null==e.dangerouslySetInnerHTML,"Can only set one of `children` or `props.dangerouslySetInnerHTML`."),__DEV__&&e.contentEditable&&null!=e.children&&console.warn("A component is `contentEditable` and contains `children` managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. This is probably not intentional."),invariant(null==e.style||"object"==typeof e.style,"The `style` prop expects a mapping from style properties to values, not a string."))}function putListener(e,t,n,r){__DEV__&&("onScroll"!==t||isEventSupported("scroll",!0)||(monitorCodeUse("react_no_scroll_event"),console.warn("This browser doesn't support the `onScroll` event")));var o=ReactMount.findReactContainerForID(e);if(o){var i=o.nodeType===ELEMENT_NODE_TYPE?o.ownerDocument:o;listenTo(t,i)}r.getPutListenerQueue().enqueuePutListener(e,t,n)}function validateDangerousTag(e){hasOwnProperty.call(validatedTagCache,e)||(invariant(VALID_TAG_REGEX.test(e),"Invalid tag: %s",e),validatedTagCache[e]=!0)}function ReactDOMComponent(e){validateDangerousTag(e),this._tag=e,this.tagName=e.toUpperCase()}var CSSPropertyOperations=require("CSSPropertyOperations"),DOMProperty=require("DOMProperty"),DOMPropertyOperations=require("DOMPropertyOperations"),ReactBrowserComponentMixin=require("ReactBrowserComponentMixin"),ReactComponent=require("ReactComponent"),ReactBrowserEventEmitter=require("ReactBrowserEventEmitter"),ReactMount=require("ReactMount"),ReactMultiChild=require("ReactMultiChild"),ReactPerf=require("ReactPerf"),assign=require("Object.assign"),escapeTextForBrowser=require("escapeTextForBrowser"),invariant=require("invariant"),isEventSupported=require("isEventSupported"),keyOf=require("keyOf"),monitorCodeUse=require("monitorCodeUse"),deleteListener=ReactBrowserEventEmitter.deleteListener,listenTo=ReactBrowserEventEmitter.listenTo,registrationNameModules=ReactBrowserEventEmitter.registrationNameModules,CONTENT_TYPES={string:!0,number:!0},STYLE=keyOf({style:null}),ELEMENT_NODE_TYPE=1,omittedCloseTags={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},VALID_TAG_REGEX=/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/,validatedTagCache={},hasOwnProperty={}.hasOwnProperty;ReactDOMComponent.displayName="ReactDOMComponent",ReactDOMComponent.Mixin={mountComponent:ReactPerf.measure("ReactDOMComponent","mountComponent",function(e,t,n){ReactComponent.Mixin.mountComponent.call(this,e,t,n),assertValidProps(this.props);var r=omittedCloseTags[this._tag]?"":"</"+this._tag+">";return this._createOpenTagMarkupAndPutListeners(t)+this._createContentMarkup(t)+r}),_createOpenTagMarkupAndPutListeners:function(e){var t=this.props,n="<"+this._tag;for(var r in t)if(t.hasOwnProperty(r)){var o=t[r];if(null!=o)if(registrationNameModules.hasOwnProperty(r))putListener(this._rootNodeID,r,o,e);else{r===STYLE&&(o&&(o=t.style=assign({},t.style)),o=CSSPropertyOperations.createMarkupForStyles(o));var i=DOMPropertyOperations.createMarkupForProperty(r,o);i&&(n+=" "+i)}}if(e.renderToStaticMarkup)return n+">";var a=DOMPropertyOperations.createMarkupForID(this._rootNodeID);return n+" "+a+">"},_createContentMarkup:function(e){var t=this.props.dangerouslySetInnerHTML;if(null!=t){if(null!=t.__html)return t.__html}else{var n=CONTENT_TYPES[typeof this.props.children]?this.props.children:null,r=null!=n?null:this.props.children;if(null!=n)return escapeTextForBrowser(n);if(null!=r){var o=this.mountChildren(r,e);return o.join("")}}return""},receiveComponent:function(e,t){(e!==this._currentElement||null==e._owner)&&ReactComponent.Mixin.receiveComponent.call(this,e,t)},updateComponent:ReactPerf.measure("ReactDOMComponent","updateComponent",function(e,t){assertValidProps(this._currentElement.props),ReactComponent.Mixin.updateComponent.call(this,e,t),this._updateDOMProperties(t.props,e),this._updateDOMChildren(t.props,e)}),_updateDOMProperties:function(e,t){var n,r,o,i=this.props;for(n in e)if(!i.hasOwnProperty(n)&&e.hasOwnProperty(n))if(n===STYLE){var a=e[n];for(r in a)a.hasOwnProperty(r)&&(o=o||{},o[r]="")}else registrationNameModules.hasOwnProperty(n)?deleteListener(this._rootNodeID,n):(DOMProperty.isStandardName[n]||DOMProperty.isCustomAttribute(n))&&ReactComponent.BackendIDOperations.deletePropertyByID(this._rootNodeID,n);for(n in i){var s=i[n],l=e[n];if(i.hasOwnProperty(n)&&s!==l)if(n===STYLE)if(s&&(s=i.style=assign({},s)),l){for(r in l)!l.hasOwnProperty(r)||s&&s.hasOwnProperty(r)||(o=o||{},o[r]="");for(r in s)s.hasOwnProperty(r)&&l[r]!==s[r]&&(o=o||{},o[r]=s[r])}else o=s;else registrationNameModules.hasOwnProperty(n)?putListener(this._rootNodeID,n,s,t):(DOMProperty.isStandardName[n]||DOMProperty.isCustomAttribute(n))&&ReactComponent.BackendIDOperations.updatePropertyByID(this._rootNodeID,n,s)}o&&ReactComponent.BackendIDOperations.updateStylesByID(this._rootNodeID,o)},_updateDOMChildren:function(e,t){var n=this.props,r=CONTENT_TYPES[typeof e.children]?e.children:null,o=CONTENT_TYPES[typeof n.children]?n.children:null,i=e.dangerouslySetInnerHTML&&e.dangerouslySetInnerHTML.__html,a=n.dangerouslySetInnerHTML&&n.dangerouslySetInnerHTML.__html,s=null!=r?null:e.children,l=null!=o?null:n.children,p=null!=r||null!=i,u=null!=o||null!=a;null!=s&&null==l?this.updateChildren(null,t):p&&!u&&this.updateTextContent(""),null!=o?r!==o&&this.updateTextContent(""+o):null!=a?i!==a&&ReactComponent.BackendIDOperations.updateInnerHTMLByID(this._rootNodeID,a):null!=l&&this.updateChildren(l,t)},unmountComponent:function(){this.unmountChildren(),ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID),ReactComponent.Mixin.unmountComponent.call(this)}},assign(ReactDOMComponent.prototype,ReactComponent.Mixin,ReactDOMComponent.Mixin,ReactMultiChild.Mixin,ReactBrowserComponentMixin),module.exports=ReactDOMComponent;
 it('should escape boolean to string', function() {
   expect(escapeTextForBrowser(true)).toBe('true');
   expect(escapeTextForBrowser(false)).toBe('false');
 });
 it('should escape number to string', function() {
   expect(escapeTextForBrowser(42)).toBe('42');
 });