Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a Symbol to tag every ReactElement #4832

Merged
merged 1 commit into from
Sep 10, 2015

Commits on Sep 10, 2015

  1. Use a Symbol to tag every ReactElement

    Fixes facebook#3473
    
    I tag each React element with `$$typeof: Symbol.for('react.element')`. We need
    this to be able to safely distinguish these from plain objects that might have
    come from user provided JSON.
    
    The idiomatic JavaScript way of tagging an object is for it to inherent some
    prototype and then use `instanceof` to test for it.
    
    However, this has limitations since it doesn't work with value types which
    require `typeof` checks. They also don't work across realms. Which is why there
    are alternative tag checks like `Array.isArray` or the `toStringTag`. Another
    problem is that different instances of React that might have been created not knowing about eachother. npm tends to make this kind of problem occur a lot.
    
    Additionally, it is our hope that ReactElement will one day be specified in
    terms of a "Value Type" style record instead of a plain Object.
    
    This Value Types proposal by @nikomatsakis is currently on hold but does satisfy all these requirements:
    
    https://github.com/nikomatsakis/typed-objects-explainer/blob/master/valuetypes.md#the-typeof-operator
    
    Additionally, there is already a system for coordinating tags across module
    systems and even realms in ES6. Namely using `Symbol.for`.
    
    Currently these objects are not able to transfer between Workers but there is
    nothing preventing that from being possible in the future. You could imagine
    even `Symbol.for` working across Worker boundaries. You could also build a
    system that coordinates Symbols and Value Types from server to client or through
    serialized forms. That's beyond the scope of React itself, and if it was built
    it seems like it would belong with the `Symbol` system. A system could override
    the `Symbol.for('react.element')` to return a plain yet
    cryptographically random or unique number. That would allow ReactElements to
    pass through JSON without risking the XSS issue.
    
    The fallback solution is a plain well-known number. This makes it unsafe with
    regard to the XSS issue described in facebook#3473. We could have used a much more
    convoluted solution to protect against JSON specifically but that would require
    some kind of significant coordination, or change the check to do a
    `typeof element.$$typeof === 'function'` check which would not make it unique to
    React. It seems cleaner to just use a fixed number since the protection is just
    a secondary layer anyway. I'm not sure if this is the right tradeoff.
    
    In short, if you want the XSS protection, use a proper Symbol polyfill.
    
    Finally, the reason for calling it `$$typeof` is to avoid confusion with `.type`
    and the use case is to add a tag that the `typeof` operator would refer to.
    I would use `@@typeof` but that seems to deopt in JSC. I also don't use
    `__typeof` because this is more than a framework private. It should really be
    part of the polyfilling layer.
    sebmarkbage committed Sep 10, 2015
    Configuration menu
    Copy the full SHA
    031fc24 View commit details
    Browse the repository at this point in the history