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

Bumping to 0.16.0 - ReferenceError: TextEncoder is not defined #91

Closed
danpottshimself opened this issue Nov 1, 2021 · 26 comments
Closed
Labels
bug Something isn't working

Comments

@danpottshimself
Copy link

danpottshimself commented Nov 1, 2021

When installing - "isomorphic-dompurify": "^0.16.0" I get the following error within a jest test that previously passed.

Error: ReferenceError: TextEncoder is not defined

js file:

import DOMPurify from "isomorphic-dompurify";

return DOMPurify.sanitize(input.trim(), { ADD_ATTR: ["target"] });

Test:

import sanitize from "./sanitizeHtml";

describe("sanitize", () => {
    it("remove js from input", () => {
        expect(sanitize("<img onload='alert(1)' />")).toEqual("<img>");
    });
});

Any ideas what this may be? Thanks in advance

@kkomelin
Copy link
Owner

kkomelin commented Nov 1, 2021

Hi @danpottshimself ,

Thanks for reporting the issue.

First of all, let's make sure that you don't have any dependency conflicts by removing node_modules folder and then installing all dependencies again the following way:

npm install
# or 
yarn
@kkomelin kkomelin added the bug Something isn't working label Nov 1, 2021
@kkomelin
Copy link
Owner

kkomelin commented Nov 1, 2021

By the way, I reformatted the issue description a little bit.

kkomelin added a commit that referenced this issue Nov 1, 2021
@kkomelin
Copy link
Owner

kkomelin commented Nov 1, 2021

I've just added an additional automated test to cover your particular case and it passed.

@danpottshimself
Copy link
Author

@kkomelin odd, I guess this could be some form of clash between dependencies I have installed elsewhere. I have tried multiple node module cleans/rm's and re-installs to no avail. I guess the issue is my side so you can close this issue, thanks for the support

@cnorthwood
Copy link

I'm also getting this fwiw, so it is slightly broader. Not entirely sure what the conflict is, perhaps one of the dependencies here isn't tightly bound enough so something else is pinning it to an older version?

@danpottshimself
Copy link
Author

That makes me feel less crazy @cnorthwood. I was originally thinking it could be jsdom environment potentially since in version 16, it looks like jest etc have been bumped?

@cnorthwood
Copy link

ah yes - that would explain it, and why @kkomelin's automated test passed. Jest with JSDom polyfills that call by itself, so it'll work in a Jest environment because JSDom has polyfilled that function, but won't when not running under Jest.

@kkomelin
Copy link
Owner

kkomelin commented Nov 2, 2021

Thanks guys. I will try to reproduce the issue without Jest. Will keep you updated.

@kkomelin
Copy link
Owner

kkomelin commented Nov 2, 2021

Just tested through a console Node.js script (Node 14.16):

require('isomorphic-dompurify');
DOMPurify.setConfig({ALLOWED_TAGS: ['b']});
console.log(DOMPurify.sanitize('<b>dddd</b><iframe>Iframe!</iframe>'));

And it worked fine.

Could you please give me more details on what are your environments so I could try to reproduce the issue locally? Server/client? Next.js/React/others?

@kkomelin
Copy link
Owner

kkomelin commented Nov 2, 2021

By the way, do you use Yarn or NPM for dependency management?

@cnorthwood
Copy link

I use Yarn - I've rolled back for now but will try and reproduce.

This is server-side Node 14 (Apollo Server) with TypeScript. I dont' use DOMPurify as a global like that, this is how I use it:

import { addHook, sanitize as _sanitize } from "isomorphic-dompurify";

// only let target="_blank" exist on A tags and enforce rel="noopener"
addHook("afterSanitizeAttributes", (node) => {
  if ("target" in node) {
    if (node.tagName === "A" && node.getAttribute("target") === "_blank") {
      node.setAttribute("rel", "noopener");
    } else {
      node.removeAttribute("target");
    }
  }
});

export const sanitize = (body: string) => _sanitize(body, { ADD_TAGS: ["iframe"], ADD_ATTR: ["target"] });
@kkomelin
Copy link
Owner

kkomelin commented Nov 2, 2021

Thanks @cnorthwood Will try to play with your example.

Although I don't think it helps but I've just updated jsdom to the latest minor e466c36 . If you want to test the updated dev snapshot, just install it like this yarn add kkomelin/isomorphic-dompurify#master

@cnorthwood
Copy link

sadly not. For more info, here's the full stack trace I get:

 FAIL  api/resolvers/Mutation/createArticle.test.ts
  ● Test suite failed to run

    ReferenceError: TextEncoder is not defined

      1 | import { ForbiddenError } from "apollo-server-errors";
    > 2 | import { addHook, sanitize as _sanitize } from "isomorphic-dompurify";
        | ^
      3 | import { Model } from "sequelize/types";
      4 |
      5 | import User from "../../db/models/User";

      at Object.<anonymous> (node_modules/whatwg-url/lib/encoding.js:2:21)
      at Object.<anonymous> (node_modules/whatwg-url/lib/url-state-machine.js:5:34)
      at Object.<anonymous> (node_modules/whatwg-url/lib/URL-impl.js:2:13)
      at Object.<anonymous> (node_modules/whatwg-url/lib/URL.js:442:14)
      at Object.<anonymous> (node_modules/whatwg-url/webidl2js-wrapper.js:3:13)
      at Object.<anonymous> (node_modules/whatwg-url/index.js:3:34)
      at Object.<anonymous> (node_modules/jsdom/lib/api.js:7:19)
      at node_modules/isomorphic-dompurify/index.js:1:278
      at Object.<anonymous> (node_modules/isomorphic-dompurify/index.js:1:344)
      at Object.<anonymous> (api/validators/index.ts:2:1)
      at Object.<anonymous> (db/models/Question.ts:4:1)
      at Object.<anonymous> (db/models/Answer.ts:13:1)
      at Object.<anonymous> (db/createTestAccounts.ts:3:1)
      at Object.<anonymous> (api/resolvers/Mutation/createArticle.test.ts:3:1)
      at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13)
      at runJest (node_modules/@jest/core/build/runJest.js:401:19)
      at _run10000 (node_modules/@jest/core/build/cli/index.js:320:7)
      at runCLI (node_modules/@jest/core/build/cli/index.js:173:3)
@cnorthwood
Copy link

so the issue appears to be in whatwg-url

$ yarn why whatwg-url
yarn why v1.22.13
[1/4] 🤔  Why do we have the module "whatwg-url"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "whatwg-url@10.0.0"
info Has been hoisted to "whatwg-url"
info Reasons this module exists
   - Hoisted from "isomorphic-dompurify#jsdom#whatwg-url"
   - Hoisted from "isomorphic-dompurify#jsdom#data-urls#whatwg-url"
info Disk size without dependencies: "140KB"
info Disk size with unique dependencies: "412KB"
info Disk size with transitive dependencies: "460KB"
info Number of shared dependencies: 3
=> Found "node-fetch#whatwg-url@5.0.0"
info This module exists because "node-fetch" depends on it.
info Disk size without dependencies: "76KB"
info Disk size with unique dependencies: "348KB"
info Disk size with transitive dependencies: "396KB"
info Number of shared dependencies: 3
=> Found "jest-environment-jsdom#whatwg-url@8.7.0"
info Reasons this module exists
   - "jest-cli#jest-config#jest-environment-jsdom#jsdom" depends on it
   - Hoisted from "jest-cli#jest-config#jest-environment-jsdom#jsdom#whatwg-url"
   - Hoisted from "jest-cli#jest-config#jest-environment-jsdom#jsdom#data-urls#whatwg-url"
info Disk size without dependencies: "136KB"
info Disk size with unique dependencies: "5.28MB"
info Disk size with transitive dependencies: "5.32MB"
info Number of shared dependencies: 4
@kkomelin
Copy link
Owner

kkomelin commented Nov 2, 2021

Just for reference jsdom/whatwg-url#209

@kkomelin
Copy link
Owner

kkomelin commented Nov 2, 2021

Good catch @cnorthwood ! Now when we know the cause, what solution would you recommend?

@kkomelin
Copy link
Owner

kkomelin commented Nov 2, 2021

Jsdom is a complex project which has already caused some dependency pain #54

@tinykite
Copy link

tinykite commented Jan 14, 2022

For anyone hitting this same issue, I was able to fix this on a project (which had a failing test due to this error) by including the following in my jest.setup.js file:

import { TextDecoder, TextEncoder } from 'util'

global.TextEncoder = TextEncoder
global.TextDecoder = TextDecoder
@aakashbacancy
Copy link

aakashbacancy commented Dec 15, 2022

I installed and I'm facing a similar issue. Everything seems fine.

The test suite failed to run

    ReferenceError: TextEncoder is not defined

I tried to print the process version using console.log(process.version) and it's 14.7.0, still giving an error.

What is the right solution?

Node version: 14.7.0

@dannyyu92
Copy link

dannyyu92 commented Jan 3, 2023

I've tried

import { TextDecoder, TextEncoder } from 'util'

global.TextEncoder = TextEncoder
global.TextDecoder = TextDecoder

in my jest setup

but I just get this error:

    TypeError: TextEncoder is not a constructor

    > 5 | import DOMPurify from 'isomorphic-dompurify';

any ideas?

edit:

for anybody having this issue, I fixed it by importing from 'node:util'
so:

import { TextDecoder, TextEncoder } from 'node:util'
@Vavaste
Copy link

Vavaste commented Jan 17, 2023

I've tried each one of the solutions provided above but since i'm working with nextJest the tests were failing.
I solved it by adding

setupFiles: ["path/to/personalizedJest.setup.js"],

to the personalized configuration for jest, in this file i just imported TextEncoder and TextDecoder from util:

import { TextDecoder, TextEncoder } from 'util';

global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;
@donald-boosted
Copy link

For me, I had to add the following to jest.setup.js

import { TextDecoder, TextEncoder } from 'util';

global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;

and import the lib like import * as dompurify from 'isomorphic-dompurify';

@stevedeighton
Copy link

For me, the TextDecoder had a type mismatch issue with the above approach, so I solved it with this syntax instead:

import { TextEncoder, TextDecoder } from 'util';

Object.assign(global, { TextDecoder, TextEncoder });

Thanks to leonheess - https://stackoverflow.com/questions/68468203/why-am-i-getting-textencoder-is-not-defined-in-jest

@kopach
Copy link

kopach commented Jul 17, 2024

Not reproducible for me anymore in 2.13.0
I guess, issue can be closed

@kkomelin
Copy link
Owner

@kopach Thanks for the update. Yes, it's a very old issue, so let's close it for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
10 participants