cure53 / DOMPurify

DOMPurify - a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. DOMPurify works with a secure default, but offers a lot of configurability and hooks. Demo:
https://cure53.de/purify
Other
13.67k stars 698 forks source link

JavaScript errors in purify.js #871

Closed tmb-github closed 10 months ago

tmb-github commented 10 months ago

This issue proposes a bug, that should be fixed.

Background & Context

I use the Closure Compiler for minification. It throws warnings and errors when I attempt to minify purify.js, all of which except one seem to be JavaScript syntax errors (note: at least one set of them seems to be a conflation of Java syntax with JavaScript syntax).

There are three minification settings of the Closure Compiler. One simply removes whitespace, which is not useful. The other two are "simple" and "advanced", which are widely used. There are 9 warnings and 1 error detected in the "simple" minification mode, and 92 warnings and 1 error detected in the "advanced" minification mode. Each warning and error cites the line of code and explains what must be done to fix it.

Please correct the syntax errors and the error so that Closure Compiler can do its work. (These warnings and errors pose a problem for all interpreters of the script, not just the Closure Compiler.)

You may use the online version of the Closure Compiler without any need to install it. It will attempt to compile/minify the JavaScript and report all problems directly in the online interface, so verification of syntax and error correction may be done easily.

Bug

In "simple" compiler mode, the 9 warnings are:

JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1163 character 84 ...e] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpT... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1163 character 145 ...TR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || F... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1169 character 309 ...instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else { ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1174 character 46 } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWE... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1174 character 130 ...eplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcNam... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1174 character 294 ...ta:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS &&... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1174 character 407 ...RIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) { ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1176 character 13 } else ; ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1301 character 28 if (namespaceURI) ; else { ^

The 1 error detected in "simple" mode is:

JSC_CANNOT_CONVERT: This code cannot be transpiled. "..." passed to a constructor (consider using --language_out=ES5) at line 47 character 13 return new Func(...args); ^

In "advanced" mode, the 92 warnings are:

JSC_INEXISTENT_PARAM: parameter transformCaseFunc does not appear in addToSet's parameter list at line 105 character 2 function addToSet(set, array) { ^ JSC_TYPE_MISMATCH: actual parameter 1 of setPrototypeOf does not match formal parameter found : (Object|null) required: Object at line 112 character 21 setPrototypeOf(set, null); ^ JSC_TYPE_MISMATCH: actual parameter 1 of entries does not match formal parameter found : (Object|null) required: Object<?,?> at line 149 character 44 for (const [property, value] of entries(object)) { ^ JSC_TYPE_MISMATCH: actual parameter 2 of getOwnPropertyDescriptor does not match formal parameter found : (String|null) required: (string|symbol) at line 167 character 52 const desc = getOwnPropertyDescriptor(object, prop); ^ JSC_WRONG_ARGUMENT_COUNT: Function createDOMPurify: called with 1 argument(s). Function requires at least 0 argument(s) and no more than 0 argument(s). at line 291 character 30 const DOMPurify = root => createDOMPurify(root); ^ JSC_TYPE_MISMATCH: actual parameter 2 of lookupGetter does not match formal parameter found : string required: (String|null) at line 330 character 53 const cloneNode = lookupGetter(ElementPrototype, 'cloneNode'); ^ JSC_TYPE_MISMATCH: actual parameter 2 of lookupGetter does not match formal parameter found : string required: (String|null) at line 331 character 58 const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling'); ^ JSC_TYPE_MISMATCH: actual parameter 2 of lookupGetter does not match formal parameter found : string required: (String|null) at line 332 character 57 const getChildNodes = lookupGetter(ElementPrototype, 'childNodes'); ^ JSC_TYPE_MISMATCH: actual parameter 2 of lookupGetter does not match formal parameter found : string required: (String|null) at line 333 character 57 const getParentNode = lookupGetter(ElementPrototype, 'parentNode'); // As... ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 518 character 39 const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NA... ^ JSC_INEXISTENT_PARAM: parameter cfg does not appear in _parseConfig's parameter list at line 545 character 25 const _parseConfig = function _parseConfig() { ^ JSC_POSSIBLE_INEXISTENT_PROPERTY: Property PARSER_MEDIA_TYPE never defined on Object

This property is accessed on a "loose" type, but is not defined anywhere in the program, so it must not exist. If this error comes from a library target, see go/js-practices/goog-module#possibly-undefined-properties-and-js-library. at line 562 character 47 SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DE... ^ JSC_POSSIBLE_INEXISTENT_PROPERTY: Property PARSER_MEDIA_TYPE never defined on Object

This property is accessed on a "loose" type, but is not defined anywhere in the program, so it must not exist. If this error comes from a library target, see go/js-practices/goog-module#possibly-undefined-properties-and-js-library. at line 562 character 107 ...-1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE; // HTML tags and a... ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 567 character 45 ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, t... ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 568 character 45 ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, t... ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 569 character 57 ALLOWED_NAMESPACES = 'ALLOWED_NAMESPACES' in cfg ? addToSet({}, cfg.ALL... ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 570 character 57 URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAU... ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 575 character 51 DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DAT... ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 580 character 51 FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CO... ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 581 character 43 FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS, tran... ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 582 character 43 FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR, tran... ^ JSC_POSSIBLE_INEXISTENT_PROPERTY: Property ALLOW_ARIA_ATTR never defined on Object

This property is accessed on a "loose" type, but is not defined anywhere in the program, so it must not exist. If this error comes from a library target, see go/js-practices/goog-module#possibly-undefined-properties-and-js-library. at line 584 character 28 ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true ^ JSC_POSSIBLE_INEXISTENT_PROPERTY: Property ALLOW_DATA_ATTR never defined on Object

This property is accessed on a "loose" type, but is not defined anywhere in the program, so it must not exist. If this error comes from a library target, see go/js-practices/goog-module#possibly-undefined-properties-and-js-library. at line 586 character 28 ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true ^ JSC_POSSIBLE_INEXISTENT_PROPERTY: Property ALLOW_SELF_CLOSE_IN_ATTR never defined on Object

This property is accessed on a "loose" type, but is not defined anywhere in the program, so it must not exist. If this error comes from a library target, see go/js-practices/goog-module#possibly-undefined-properties-and-js-library. at line 590 character 37 ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // D... ^ JSC_POSSIBLE_INEXISTENT_PROPERTY: Property SANITIZE_DOM never defined on Object

This property is accessed on a "loose" type, but is not defined anywhere in the program, so it must not exist. If this error comes from a library target, see go/js-practices/goog-module#possibly-undefined-properties-and-js-library. at line 604 character 25 SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true ^ JSC_POSSIBLE_INEXISTENT_PROPERTY: Property KEEP_CONTENT never defined on Object

This property is accessed on a "loose" type, but is not defined anywhere in the program, so it must not exist. If this error comes from a library target, see go/js-practices/goog-module#possibly-undefined-properties-and-js-library. at line 608 character 25 KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 673 character 8 addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc); ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 681 character 8 addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc); ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 685 character 8 addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc); ^ JSC_WRONG_ARGUMENT_COUNT: Function addToSet: called with 3 argument(s). Function requires at least 2 argument(s) and no more than 2 argument(s). at line 693 character 8 addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc); ^ JSC_POSSIBLE_INEXISTENT_PROPERTY: Property tbody never defined on Object

This property is accessed on a "loose" type, but is not defined anywhere in the program, so it must not exist. If this error comes from a library target, see go/js-practices/goog-module#possibly-undefined-properties-and-js-library. at line 712 character 27 delete FORBID_TAGS.tbody; ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Element It's possible that a local variable called 'Element' is shadowing the intended global namespace. at line 763 character 16

  • @param {Element} element a DOM element whose namespace is being checked ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Node It's possible that a local variable called 'Node' is shadowing the intended global namespace. at line 857 character 16
  • @param {Node} node a DOM node ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Node It's possible that a local variable called 'Node' is shadowing the intended global namespace. at line 877 character 16
  • @param {Node} node a DOM node ^ JSC_DETERMINISTIC_TEST: condition always evaluates to false left : (String|null) right: string at line 896 character 10 if (name === 'is' && !ALLOWED_ATTR[name]) { ^ JSC_TYPE_MISMATCH: assignment found : string required: (String|null) at line 922 character 8 dirty = '' + dirty; ^ JSC_TYPE_MISMATCH: assignment found : string required: (String|null) at line 931 character 8 dirty = '<bod... ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Node It's possible that a local variable called 'Node' is shadowing the intended global namespace. at line 974 character 16
  • @param {Node} root The root element or node to start traversing on. ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Node It's possible that a local variable called 'Node' is shadowing the intended global namespace. at line 986 character 16
  • @param {Node} elm element to check for clobbering attacks ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 992 character 13 return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'stri... ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Node It's possible that a local variable called 'Node' is shadowing the intended global namespace. at line 997 character 16
  • @param {Node} object object to check whether it's a DOM node ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1003 character 13 return typeof Node === 'function' && object instanceof Node; ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Node It's possible that a local variable called 'Node' is shadowing the intended global namespace. at line 1010 character 16
  • @param {Node} currentNode node to work on with the hook ^ JSC_BAD_JSDOC_ANNOTATION: Parse error. illegal use of unknown JSDoc tag "protect"; ignoring it. Place another character before the @ to stop JSCompiler from parsing it as an annotation. at line 1027 character 7
  • @protect nodeName ^ JSC_BAD_JSDOC_ANNOTATION: Parse error. illegal use of unknown JSDoc tag "protect"; ignoring it. Place another character before the @ to stop JSCompiler from parsing it as an annotation. at line 1028 character 7
  • @protect textContent ^ JSC_BAD_JSDOC_ANNOTATION: Parse error. illegal use of unknown JSDoc tag "protect"; ignoring it. Place another character before the @ to stop JSCompiler from parsing it as an annotation. at line 1029 character 7
  • @protect removeChild ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Node It's possible that a local variable called 'Node' is shadowing the intended global namespace. at line 1031 character 17
  • @param {Node} currentNode to check for permission to exist ^ JSC_TYPE_MISMATCH: actual parameter 1 of _executeHook does not match formal parameter found : string required: (String|null) at line 1040 character 19 _executeHook('beforeSanitizeElements', currentNode, null); ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1047 character 15 return true; ^ JSC_TYPE_MISMATCH: actual parameter 1 of _executeHook does not match formal parameter found : string required: (String|null) at line 1055 character 19 _executeHook('uponSanitizeElement', currentNode, { ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1065 character 15 return true; ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1074 character 19 return false; ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1078 character 19 return false; ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1099 character 15 return true; ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1107 character 15 return true; ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1115 character 15 return true; ^ JSC_TYPE_MISMATCH: actual parameter 1 of _executeHook does not match formal parameter found : string required: (String|null) at line 1137 character 19 _executeHook('afterSanitizeElements', currentNode, null); ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1139 character 13 return false; ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1155 character 15 return false; ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1163 character 84 ...e] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpT... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1163 character 145 ...TR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || F... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1169 character 309 ...instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else { ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1170 character 17 return false; ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1174 character 46 } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWE... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1174 character 130 ...eplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcNam... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1174 character 294 ...ta:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS &&... ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1174 character 407 ...RIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) { ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1175 character 15 return false; ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1176 character 13 } else ; ^ JSC_TYPE_MISMATCH: inconsistent return type found : boolean required: (Boolean|null) at line 1178 character 13 return true; ^ JSC_BAD_JSDOC_ANNOTATION: Parse error. illegal use of unknown JSDoc tag "protect"; ignoring it. Place another character before the @ to stop JSCompiler from parsing it as an annotation. at line 1196 character 7
  • @protect attributes ^ JSC_BAD_JSDOC_ANNOTATION: Parse error. illegal use of unknown JSDoc tag "protect"; ignoring it. Place another character before the @ to stop JSCompiler from parsing it as an annotation. at line 1197 character 7
  • @protect nodeName ^ JSC_BAD_JSDOC_ANNOTATION: Parse error. illegal use of unknown JSDoc tag "protect"; ignoring it. Place another character before the @ to stop JSCompiler from parsing it as an annotation. at line 1198 character 7
  • @protect removeAttribute ^ JSC_BAD_JSDOC_ANNOTATION: Parse error. illegal use of unknown JSDoc tag "protect"; ignoring it. Place another character before the @ to stop JSCompiler from parsing it as an annotation. at line 1199 character 7
  • @protect setAttribute ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Node It's possible that a local variable called 'Node' is shadowing the intended global namespace. at line 1201 character 16
  • @param {Node} currentNode to sanitize ^ JSC_TYPE_MISMATCH: actual parameter 1 of _executeHook does not match formal parameter found : string required: (String|null) at line 1207 character 19 _executeHook('beforeSanitizeAttributes', currentNode, null); ^ JSC_TYPE_MISMATCH: actual parameter 1 of _executeHook does not match formal parameter found : string required: (String|null) at line 1243 character 21 _executeHook('uponSanitizeAttribute', currentNode, hookEvent); ^ JSC_SUSPICIOUS_SEMICOLON: If this if/for/while really shouldn't have a body, use {} at line 1301 character 28 if (namespaceURI) ; else { ^ JSC_TYPE_MISMATCH: actual parameter 1 of _executeHook does not match formal parameter found : string required: (String|null) at line 1334 character 19 _executeHook('afterSanitizeAttributes', currentNode, null); ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type DocumentFragment It's possible that a local variable called 'DocumentFragment' is shadowing the intended global namespace. at line 1339 character 16
  • @param {DocumentFragment} fragment to iterate over recursively ^ JSC_TYPE_MISMATCH: actual parameter 1 of _executeHook does not match formal parameter found : string required: (String|null) at line 1350 character 19 _executeHook('beforeSanitizeShadowDOM', fragment, null); ^ JSC_TYPE_MISMATCH: actual parameter 1 of _executeHook does not match formal parameter found : string required: (String|null) at line 1354 character 21 _executeHook('uponSanitizeShadowNode', shadowNode, null); ^ JSC_TYPE_MISMATCH: actual parameter 1 of _executeHook does not match formal parameter found : string required: (String|null) at line 1375 character 19 _executeHook('afterSanitizeShadowDOM', fragment, null); ^ JSC_UNRECOGNIZED_TYPE_ERROR: Bad type annotation. Unknown type Node It's possible that a local variable called 'Node' is shadowing the intended global namespace. at line 1381 character 22
  • @param {String|Node} dirty string or DOM node ^ JSC_INEXISTENT_PARAM: parameter cfg does not appear in DOMPurify.sanitize's parameter list at line 1387 character 25 DOMPurify.sanitize = function (dirty) { ^ JSC_WRONG_ARGUMENT_COUNT: Function _parseConfig: called with 1 argument(s). Function requires at least 0 argument(s) and no more than 0 argument(s). at line 1426 character 8 _parseConfig(cfg); ^ JSC_TYPE_MISMATCH: actual parameter 1 of _initDocument does not match formal parameter found : string required: (String|null) at line 1450 character 29 body = _initDocument('<!---->'); ^ JSC_INEXISTENT_PARAM: parameter cfg does not appear in DOMPurify.setConfig's parameter list at line 1567 character 26 DOMPurify.setConfig = function () { ^ JSC_WRONG_ARGUMENT_COUNT: Function _parseConfig: called with 1 argument(s). Function requires at least 0 argument(s) and no more than 0 argument(s). at line 1570 character 6 _parseConfig(cfg); ^ JSC_WRONG_ARGUMENT_COUNT: Function _parseConfig: called with 1 argument(s). Function requires at least 0 argument(s) and no more than 0 argument(s). at line 1600 character 8 _parseConfig({}); ^ JSC_TYPE_MISMATCH: actual parameter 3 of _isValidAttribute does not match formal parameter found : (String|null) required: string at line 1605 character 46 return _isValidAttribute(lcTag, lcName, value); ^ JSC_MISSING_RETURN_STATEMENT: Missing return statement. Function expected to return (Function|null). at line 1634 character 27 DOMPurify.removeHook = function (entryPoint) { ^

The one error is:

JSC_CANNOT_CONVERT: This code cannot be transpiled. "..." passed to a constructor (consider using --language_out=ES5) at line 47 character 13 return new Func(...args); ^

Input

Some HTML which is thrown at DOMPurify.

Given output

The output given by DOMPurify.

Expected output

The Closure Compiler should minify/compile the JavaScript without any warnings or errors, both in "simple" and "advanced" mode.

Feature

n/a

tmb-github commented 10 months ago

Note: the 9 warnings provided by the Closure Compiler provide the code that solves the problem (i.e., replacing each of the indicated semicolons with {}, although the real problem is that those if statements should simply be turned into comments, since nothing is to be done if those conditions obtain.)

The one error (i.e., return new Func(...args);) may be fixed with this code revision: return new Func.apply(null, args);

The warnings from the Advanced mode require more work that the author(s) of the code would be best to attend to.

cure53 commented 10 months ago

I am wondering, since these are only warnings, why not just ignore them?

cure53 commented 10 months ago

Looking at the code, the error thrown by the Closure Compiler comes from code that is older than 3 years:

https://github.com/cure53/DOMPurify/blame/main/src/utils.js#L32

This makes me think the problem is not on our end, wdyt?

tmb-github commented 10 months ago

Consider line 1163 (of the the stand-alone purify.js):

if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName])

The first if and else if statements do nothing; they apparently function as comments to the programmer as to what's not being done for certain cases; they really should just be comments. Only the last else if produces an actionable result.

All of the warnings in simple mode are triggered by this, which is poor coding on the face of it (is there something deeper going on here that necessitates this?)

cure53 commented 10 months ago

At the end of the day, those contraptions were created to make it easier to follow the complex sanitization logic and are what I would judge a matter of taste, nothing deeper going on here.

I would personally not judge this as poor coding but am happy to accept that others might think differently about this. Still, not a strong reason yet to change things assuming the only reason is to satisfy another compressor or linter tool than the ones we have opted to use for ourselves.