closure-compiler
closure-compiler copied to clipboard
`TypedArray` constructors are missing `@nosideeffects`
Unused TypedArray global variables are not eliminated. Consider the example
// a.js
/** @const {!Uint8Array} */
const Arr = Uint8Array.from([1, 2, 3]);
/** @const {string} */
const Str = "string";
console.log("a.js");
When compiled with Google Closure Compiler 20221102.0.1
yarn google-closure-compiler -W VERBOSE -O ADVANCED \
--emit_use_strict \
--module_resolution NODE \
--assume_function_wrapper \
--dependency_mode PRUNE \
--entry_point a.js \
--js a.js
> 'use strict';Uint8Array.from([1,2,3]);console.log("a.js");
The compiler is able to eliminate the string constant Str, but not the typed array Arr. Indeed, the constructor definition here does not have the @nosideeffects annotation.
Potential duplicate https://github.com/google/closure-compiler/issues/709
The previous issue (#709) is unresolved. A lot of libraries (crypto, ml, etc) have big hardcoded arrays which should be eliminated when not used.
Unfortunately, the optional "map" function prevents this method from being marked as @nosideeffect. We need an annotation like "if the function is missing or known to be side effect free then this method is @nosideeffect".
@concavelenz Why would map() prevent this? It looks like map() is not in-place (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/map). Even if it were, how is this different from Array<>
Let's consider this
const a = new Uint8Array(10);
const b = new Uint8Array(a.buffer);
const c = b.map(Math.sqrt);
Where is the problem in this code?
@concavelenz The from() method does have a mapFn parameter, which may have side effects as you said
Example:
const a = Uint8Array.from([1, 2, 3], (x) => { console.log(x); return x * x; })
On the other hand, the Uint8Array constructor appears to be safe for marking @nosideeffects, but it isn't. Could you please verify?