closure-compiler icon indicating copy to clipboard operation
closure-compiler copied to clipboard

`TypedArray` constructors are missing `@nosideeffects`

Open KimlikDAO-bot opened this issue 2 years ago • 5 comments
trafficstars

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.

KimlikDAO-bot avatar Dec 07 '22 22:12 KimlikDAO-bot

Potential duplicate https://github.com/google/closure-compiler/issues/709

KimlikDAO-bot avatar Dec 07 '22 22:12 KimlikDAO-bot

The previous issue (#709) is unresolved. A lot of libraries (crypto, ml, etc) have big hardcoded arrays which should be eliminated when not used.

KimlikDAO-bot avatar Dec 07 '22 22:12 KimlikDAO-bot

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 avatar Dec 09 '22 19:12 concavelenz

@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?

KimlikDAO-bot avatar Dec 12 '22 03:12 KimlikDAO-bot

@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?

KimlikDAO-bot avatar May 29 '24 18:05 KimlikDAO-bot