Skip to content

fix(directive): @Input({transform: window ? atob : btoa}) / atob || btoa reports a false "must be a function" #517

Description

@Brooooooklyn

ngtsc evaluates ambient globals (from lib.dom.d.ts) as references, which count as truthy. So window ? atob : btoa and atob || btoa resolve to atob. OXC treats the globals as unknown values, so the transform stays dynamic. The transform validation added in #494 then reports an error.

Repro

import {Directive, Input} from '@angular/core';
@Directive({selector: '[d]'})
export class D { @Input({transform: window ? atob : btoa}) a: any; }

(same with transform: atob || btoa)

OXC #504 tip

Error: Input transform must be a function Value could not be determined statically.

OXC main

No error. The expression is emitted as written: inputs:{a:[2,"a","a",(window? atob: btoa)]} ((atob || btoa)). This works at runtime but doesn't match ngtsc.

ngtsc 22.1.7

inputs: { a: [2, "a", "a", atob] }

Where

crates/oxc_angular_compiler/src/directive/evaluator.rs at the #504 tip. The global identifier evaluates to Value::Dynamic. The transform check (~L2640, added by #494 feat/validate-input-transforms, commit 58b12f7) then reports "must be a function".

In ngtsc, partial_evaluator/src/interpreter.ts turns a declared-only variable (isVariableDeclarationDeclared, e.g. declare var window in lib.dom) into a Reference. A Reference is truthy, so visitConditionalExpression and || take the atob branch.

On main?

No. This false error comes with #494. Main has no check here.

Direction

Either treat a known ambient global identifier (one not declared in the file) as a truthy opaque reference for ?:, ||, && and ??, as ngtsc does. Or, more simply, don't report "must be a function" when the dynamic part is only a global, and emit the expression as main does.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions