microsoft / microsoft/TypeScript

expando fields not added to symbol exports

Ouverte
#31,778 2 commentaires 0 réactions 1 personne assignée Voir sur GitHub

@sandersn y travaille déjà.

Depuis le 13/6/2019.

Needs Investigation
Langage dominant
Go
Étoiles
111k
Forks
14.3k
Merge moyen
2 j 4 h
PR mergées (30 j)
132

Description

TypeScript Version: 3.4.0, 3.5.0, master (7dc1f40dc15132ba87a70a3bec6d63317cb5b91e)

Search Terms:
expando, iife, umd, exports

Code

Given the following code, similar to an UMD file:

(function(){
    var A = (function () {
        function A() {}
        return A;
    }());
    A.expando = true;
}());

Expected behavior:

The ts.Symbol of the outer A should have expando in it.

Actual behavior:

The ts.Symbol of the outer A does not have expando in it. When the declaration of A is at the top-level, without the "UMD wrapper", it works properly:

var A = (function () {
    function A() {}
    return A;
}());
A.expando = true;

I have researched what is preventing the expando static prop to be added to exports, and it is due to when a ts.Symbol is considered for expando properties, here:

https://github.com/microsoft/TypeScript/blob/3d2af9ff332fca6c5db2390be0b1f08bba8402a1/src/compiler/binder.ts#L2649-L2678

Specifically, the symbol's flag of A inside the UMD wrapper are not sufficient to take the early-return in the first statement, whereas with A at the top-level it has been assigned appropriate flags.

Because the appropriate flags are not present, the code structure is analyzed to determine if the symbol should be classified as expando. Specifically, the relevant code is in getExpandoInitializer:

https://github.com/microsoft/TypeScript/blob/3d2af9ff332fca6c5db2390be0b1f08bba8402a1/src/compiler/utilities.ts#L1873-L1896

From this function, it becomes clear why the symbol fails to be recognized as expando symbol: the used IIFE syntax deviates from the syntax that is accounted for in getExpandoInitializer. When changing the sample into the following, it does indeed work as expected:

(function(){
    var A = (function () {
        function A() {}
        return A;
    })(); // <-- The difference is here
    A.expando = true;
}());

Unfortunately however, downleveled ES5 code does use the syntax that is not accounted for.

Playground Link:

Can't be replicated in the playground, but copying the code into https://ts-ast-viewer.com, setting the script kind to JS and inspecting the Symbol of the outer A declaration shows that its exports are empty. The alternative IIFE syntax does have the proper exports.

Related Issues:
n/a

Background info
This is an issue for Angular's Compatibility Compiler, which uses the TypeScript compiler to parse JavaScript bundles in various formats and uses the symbol information to reason about the code. PR https://github.com/angular/angular/pull/30795 now contains a hack to patch TS's getExpandoInitializer, which does indeed resolve the issue.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.