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

[react] Support anything with toString() (such as TrustedHTML) as input for dangerouslySetInnerHTML. #60417

Conversation

lgarron
Copy link
Contributor

@lgarron lgarron commented May 18, 2022

This change allows passing TrustedHTML to dangerouslySetInnerHTML in React. React correctly passes this to innerHTML in a way that is compatible with CSP enforcement of the Trusted Types API. We are prototyping a use case for this inside the GitHub codebase.

Since this is a nested property on an interface, I couldn't find a reasonable way to augment the react namespace to support this inside a single project. So I thought I'd send this PR to see if we could consider marking the functionality in @types/react directly.

@typescript-bot
Copy link
Contributor

typescript-bot commented May 18, 2022

@lgarron Thank you for submitting this PR!

This is a live comment which I will keep updated.

1 package in this PR

Code Reviews

Because this is a widely-used package, a DT maintainer will need to review it before it can be merged.

You can test the changes of this PR in the Playground.

Status

  • ✅ No merge conflicts
  • ✅ Continuous integration tests have passed
  • 🕐 Most recent commit is approved by a DT maintainer

Once every item on this list is checked, I'll ask you for permission to merge and publish the changes.

Inactive

This PR has been inactive for 26 days — it is still unreviewed!


Diagnostic Information: What the bot saw about this PR
{
  "type": "info",
  "now": "-",
  "pr_number": 60417,
  "author": "lgarron",
  "headCommitOid": "40151cd5c393ec6547475ef4557ef32950be3bda",
  "mergeBaseOid": "b6a234377c5edea999fc23777189aad8cdf5d29f",
  "lastPushDate": "2022-05-18T22:03:01.000Z",
  "lastActivityDate": "2022-06-06T18:29:23.000Z",
  "hasMergeConflict": false,
  "isFirstContribution": false,
  "tooManyFiles": false,
  "hugeChange": false,
  "popularityLevel": "Critical",
  "pkgInfo": [
    {
      "name": "react",
      "kind": "edit",
      "files": [
        {
          "path": "types/react/index.d.ts",
          "kind": "definition"
        },
        {
          "path": "types/react/test/index.ts",
          "kind": "test"
        }
      ],
      "owners": [
        "johnnyreilly",
        "bbenezech",
        "pzavolinsky",
        "ericanderson",
        "DovydasNavickas",
        "theruther4d",
        "guilhermehubner",
        "ferdaber",
        "jrakotoharisoa",
        "pascaloliv",
        "hotell",
        "franklixuefei",
        "Jessidhia",
        "saranshkataria",
        "lukyth",
        "eps1lon",
        "zieka",
        "dancerphil",
        "dimitropoulos",
        "disjukr",
        "vhfmag",
        "hellatan",
        "priyanshurav"
      ],
      "addedOwners": [],
      "deletedOwners": [],
      "popularityLevel": "Critical"
    }
  ],
  "reviews": [
    {
      "type": "stale",
      "reviewer": "eps1lon",
      "date": "2022-05-18T20:38:08.000Z",
      "abbrOid": "1fc726a"
    }
  ],
  "mainBotCommentID": 1130507965,
  "ciResult": "pass"
}

@typescript-bot
Copy link
Contributor

@lgarron lgarron force-pushed the react-dangerouslySetInnerHTML-TrustedHTML branch from e66461a to 1fc726a Compare May 18, 2022 20:32
@@ -38,6 +38,7 @@
import * as CSS from 'csstype';
import * as PropTypes from 'prop-types';
import { Interaction as SchedulerInteraction } from 'scheduler/tracing';
import 'trusted-types';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should rather use the same approach we do with the dom related stuff: use an empty interface for TrustedHTML and let users take care of the proper type. We shouldn't use the polyfill directly here.

For more guidance check how we test the other DOM interfaces.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks, I thought trusted-types were the global types to be used. microsoft/TypeScript-DOM-lib-generator#1246 is stalled, so they're not available globally yet. I'll try to take a look.

@typescript-bot typescript-bot added the Revision needed This PR needs code changes before it can be merged. label May 18, 2022
@typescript-bot typescript-bot moved this from Waiting for Code Reviews to Needs Author Action in New Pull Request Status Board May 18, 2022
@typescript-bot
Copy link
Contributor

@lgarron One or more reviewers has requested changes. Please address their comments. I'll be back once they sign off or you've pushed new commits. Thank you!

@eps1lon
Copy link
Collaborator

eps1lon commented May 18, 2022

Also: Could you check in which version support for trusted types was added to React?

@eps1lon
Copy link
Collaborator

eps1lon commented May 18, 2022

I don't think React has actual support for trusted types yet.

I think this only works incidentally now because TrustedHTML implements toString().

So instead of accepting only string we should probably just widen the accepted types to { toString(): string } i.e. there's no need to mention TrustedHTML in the typings at all.

@lgarron
Copy link
Contributor Author

lgarron commented May 18, 2022

I don't think React has actual support for trusted types yet.

I think this only works incidentally now because TrustedHTML implements toString().

So instead of accepting only string we should probably just widen the accepted types to { toString(): string } i.e. there's no need to mention TrustedHTML in the typings at all.

From what I can tell, React passes the input to innerHTML without converting to a string. I think accepting anything with toString() makes sense, though, because that string value does get used in the end. (That is, {toString: () => "<b>hello world</b>"} can be passed both to innerHTML and dangerouslySetInnerHTML.)

@lgarron lgarron changed the title [react] Support TrustedHTML as input for dangerouslySetInnerHTML. [react] Support anything with toString() (such as TrustedHTML) as input for dangerouslySetInnerHTML. May 18, 2022
@typescript-bot typescript-bot removed the Revision needed This PR needs code changes before it can be merged. label May 18, 2022
@typescript-bot typescript-bot moved this from Needs Author Action to Waiting for Code Reviews in New Pull Request Status Board May 18, 2022
@eps1lon
Copy link
Collaborator

eps1lon commented May 18, 2022

From what I can tell, React passed the input to innerHTML without converting to a string.

Looks like it: https://codesandbox.io/s/trustedhtml-kfxbhz

I think accepting anything with toString() makes sense, though, because that string value does get used.

Nah, if it really is just assigned we should simply accept the same type as HTMLElement.prototype.innerHTML. But then we'd still need to add TrustedHTML to https://github.com/microsoft/TypeScript-DOM-lib-generator/blob/bdf9e19b9676d8b1a4ea4fde7407354004e7104a/baselines/dom.generated.d.ts#L8907

@lgarron
Copy link
Contributor Author

lgarron commented May 18, 2022

Nah, if it really is just assigned we should simply accept the same type as HTMLElement.prototype.innerHTML. But then we'd still need to add TrustedHTML to https://github.com/microsoft/TypeScript-DOM-lib-generator/blob/bdf9e19b9676d8b1a4ea4fde7407354004e7104a/baselines/dom.generated.d.ts#L8907

That certainly makes sense. If it makes sense to wait on that, would you have any advice for any TypeScript projects that want to pass TrustedHTML to dangerouslySetInnerHTML today, without suppressing errors?

@typescript-bot typescript-bot added the The CI failed When GH Actions fails label May 18, 2022
@typescript-bot typescript-bot moved this from Waiting for Code Reviews to Needs Author Action in New Pull Request Status Board May 18, 2022
@typescript-bot
Copy link
Contributor

@lgarron The CI build failed! Please review the logs for more information.

Once you've pushed the fixes, the build will automatically re-run. Thanks!

Note: builds which are failing do not end up on the list of PRs for the DT maintainers to review.

@lgarron lgarron force-pushed the react-dangerouslySetInnerHTML-TrustedHTML branch from a6f249a to 40151cd Compare May 18, 2022 22:03
@typescript-bot typescript-bot removed the The CI failed When GH Actions fails label May 18, 2022
@typescript-bot typescript-bot moved this from Needs Author Action to Waiting for Code Reviews in New Pull Request Status Board May 18, 2022
@DangerBotOSS
Copy link

Inspecting the JavaScript source for this package found some properties that are not in the .d.ts files.
The check for missing properties isn't always right, so take this list as advice, not a requirement.

react (unpkg)

was missing the following properties:

  1. unstable_act

Generated by 🚫 dangerJS against 40151cd

@typescript-bot
Copy link
Contributor

@eps1lon Thank you for reviewing this PR! The author has pushed new commits since your last review. Could you take another look and submit a fresh review?

@typescript-bot typescript-bot moved this from Waiting for Code Reviews to Needs Maintainer Review in New Pull Request Status Board May 18, 2022
@eps1lon
Copy link
Collaborator

eps1lon commented May 19, 2022

would you have any advice for any TypeScript projects that want to pass TrustedHTML to dangerouslySetInnerHTML today, without suppressing errors?

Unfortunately module augmentation doesn't work for existing properties so all you can do is error suppression.

@lgarron
Copy link
Contributor Author

lgarron commented May 24, 2022

would you have any advice for any TypeScript projects that want to pass TrustedHTML to dangerouslySetInnerHTML today, without suppressing errors?

Unfortunately module augmentation doesn't work for existing properties so all you can do is error suppression.

Do I understand correctly that the best way forward is to advocate for microsoft/TypeScript-DOM-lib-generator#1246 to land, and to change dangerouslySetInnerHTML to take the type of the Element.innerHTML setter from the DOM types?

@lgarron
Copy link
Contributor Author

lgarron commented May 25, 2022

change dangerouslySetInnerHTML to take the type of the Element.innerHTML setter from the DOM types?

Is there a good way to do this? It looks like types from lib.dom.ts are not available inside the React definitions right now — would it be worth importing those vs. adding a toString() alternative directly to the type?

@eps1lon
Copy link
Collaborator

eps1lon commented May 25, 2022

Do I understand correctly that the best way forward is to advocate for microsoft/TypeScript-DOM-lib-generator#1246 to land, and to change dangerouslySetInnerHTML to take the type of the Element.innerHTML setter from the DOM types?

Yep

Is there a good way to do this?

I don't know. One difficulty is how this change will integrate into react-native

@typescript-bot typescript-bot added the Unreviewed No one showed up to review this PR, so it'll be reviewed by a DT maintainer. label May 30, 2022
@typescript-bot
Copy link
Contributor

Re-ping @johnnyreilly, @bbenezech, @pzavolinsky, @ericanderson, @DovydasNavickas, @theruther4d, @guilhermehubner, @ferdaber, @jrakotoharisoa, @pascaloliv, @Hotell, @franklixuefei, @Jessidhia, @saranshkataria, @lukyth, @eps1lon, @zieka, @dancerphil, @dimitropoulos, @disjukr, @vhfmag, @hellatan, @priyanshurav:

This PR has been out for over a week, yet I haven't seen any reviews.

Could someone please give it some attention? Thanks!

@typescript-bot typescript-bot moved this from Needs Maintainer Review to Needs Maintainer Action in New Pull Request Status Board Jun 6, 2022
@typescript-bot
Copy link
Contributor

It has been more than two weeks and this PR still has no reviews.

I'll bump it to the DT maintainer queue. Thank you for your patience, @lgarron.

(Ping @johnnyreilly, @bbenezech, @pzavolinsky, @ericanderson, @DovydasNavickas, @theruther4d, @guilhermehubner, @ferdaber, @jrakotoharisoa, @pascaloliv, @Hotell, @franklixuefei, @Jessidhia, @saranshkataria, @lukyth, @eps1lon, @zieka, @dancerphil, @dimitropoulos, @disjukr, @vhfmag, @hellatan, @priyanshurav.)

@eps1lon
Copy link
Collaborator

eps1lon commented Jun 6, 2022

Alternate proposal #60691

@sandersn sandersn removed this from Needs Maintainer Action in New Pull Request Status Board Jun 21, 2022
@lgarron lgarron deleted the react-dangerouslySetInnerHTML-TrustedHTML branch October 12, 2023 06:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Critical package Unreviewed No one showed up to review this PR, so it'll be reviewed by a DT maintainer.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants