Aller au contenu principal

7.4.0 est disponible : core-js 3, méthodes privées statiques et application partielle

· 13 min de lecture
Traduction Bêta Non Officielle

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

Aujourd'hui, nous publions Babel 7.4.0 !

Cette version inclut la prise en charge de TypeScript 3.4, la proposition d'application partielle dans les appels de fonction et les méthodes privées statiques.

Nous avons ajouté la prise en charge des expressions parenthésées significatives dans @babel/parser, et l'avons rendu plus conforme aux spécifications que jamais !

Enfin, @babel/preset-env et @babel/transform-runtime prennent désormais en charge core-js@3, tandis que @babel/template propose une nouvelle syntaxe très pratique !

Vous pouvez consulter l'intégralité du journal des modifications sur GitHub.


Un grand merci à tous les nouveaux contributeurs de Babel 😊. Depuis que nous générons les journaux de publication via GitHub Actions, nous n'avions pas pu les remercier individuellement dans chaque version, mais ils sont nombreux depuis Babel 7.3.3 !

De nombreuses fonctionnalités de cette version ont été développées avec nos sponsors. Bloomberg a contribué à implémenter un nouvel élément privé dans chaque version depuis la 7.0 (7.1, 7.2, 7.3), et vient désormais d'implémenter les méthodes privées statiques ! Il ne reste donc plus que les accesseurs statiques privés (getters/setters).

De même, Trivago (sponsor de soutien de base sur OpenCollective) a pris en charge l'implémentation du plugin d'application partielle.

Ce dernier mois, nous avons expérimenté une collaboration plus directe avec des entreprises sur diverses fonctionnalités/optimisations profitant à la communauté : RunKit a sponsorisé Nicolò pour implémenter la prise en charge des espaces réservés dans @babel/template.

Lorsqu'on gère un gros projet open source, tout n'est pas que code : nous devons gérer des serveurs, l'intégration continue, les comptes sur les réseaux sociaux et... beaucoup de mots de passe ! Nous remercions vivement 1Password de nous avoir acceptés dans leur programme de soutien open source et de nous fournir un compte gratuit 1Password Teams !

Si vous ou votre entreprise souhaitez soutenir Babel et l'évolution de JavaScript sans savoir comment faire, vous pouvez nous faire un don sur OpenCollective ou, mieux encore, collaborer directement avec nous à l'implémentation des nouvelles propositions ECMAScript ! En tant que projet porté par des bénévoles, nous dépendons du soutien communautaire pour financer nos efforts visant à accompagner les nombreux utilisateurs de JavaScript et à maintenir la base de code. Contactez Henry à henry@babeljs.io pour en discuter !

core-js 3 (#7646)

Nous avons reçu de nombreux éloges pour notre travail sur @babel/preset-env, mais la plupart reviennent à Denis pour son travail remarquable. Il maintient core-js qui fournit tous les polyfills chargés par @babel/polyfill, @babel/runtime et @babel/preset-env.

core-js@3 vient de sortir et inclut de nombreuses nouveautés : vous pouvez les découvrir dans "core-js@3, babel and a look into the future". En plus des nouvelles propositions, il permet de polyfiller les méthodes d'instance via @babel/plugin-transform-runtime pour les utiliser dans d'anciens navigateurs sans polluer l'environnement global :

JavaScript
// 'foo' could be either a string or an array, or a custom object
foo.includes("a");

// ⮕

import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";

_includesInstanceProperty(foo).call(foo, "a");

@babel/preset-env et @babel/plugin-transform-runtime prennent désormais en charge le polyfill des propositions : il suffit d'utiliser corejs: { version: 3, proposals: true } au lieu de corejs: 3 dans votre configuration. Gardez à l'esprit que les propositions ECMAScript sont intrinsèquement instables et pourraient changer dans core-js@4 !

Auparavant, @babel/preset-env s'appuyait entièrement sur les données de compat-table pour déterminer quels polyfills charger pour un environnement donné. core-js@3 introduit son propre jeu de données de compatibilité avec une suite de tests exhaustive qui devrait garantir un polyfill bien plus précis !

Migration depuis core-js@2

Les versions 2 et 3 de core-js étant incompatibles (nous ne voulons pas casser votre code !), cette fonctionnalité n'est pas activée par défaut.

  • If you are using @babel/preset-env, you need to enable the corejs: 3 option:

    JavaScript
    presets: [
    ["@babel/preset-env", {
    useBuiltIns: "usage", // or "entry"
    corejs: 3,
    }]
    ]

    Don't forget to update your installed version of core-js!

    npm install --save core-js@3

    When using core-js 3, the useBuiltIns: "entry" option not only transforms import "core-js" imports, but also regenerator-runtime/runtime and all the nested core-js entry points.

    For example, when targeting Chrome 72, it will apply this transformation:

    Input
    JavaScript
    import "core-js/es";
    import "core-js/proposals/set-methods";
    import "core-js/features/set/map";
    Output
    JavaScript
    import "core-js/modules/es.array.unscopables.flat";
    import "core-js/modules/es.array.unscopables.flat-map";
    import "core-js/modules/es.object.from-entries";
    import "core-js/modules/esnext.set.difference";
    import "core-js/modules/esnext.set.intersection";
    import "core-js/modules/esnext.set.is-disjoint-from";
    import "core-js/modules/esnext.set.is-subset-of";
    import "core-js/modules/esnext.set.is-superset-of";
    import "core-js/modules/esnext.set.map";
    import "core-js/modules/esnext.set.symmetric-difference";
    import "core-js/modules/esnext.set.union";

    Unlike when using core-js 2, it doesn't transform @babel/polyfill imports because when used directly that package loads version 2 of core-js.

  • Si vous utilisez @babel/plugin-transform-runtime, vous devez activer l'option corejs: 3 :

    JavaScript
    plugins: [
    ["@babel/transform-runtime", {
    corejs: 3,
    }]
    ]

    Vous pouvez supprimer @babel/runtime-corejs2, mais vous devez installer @babel/runtime-corejs3 !

    npm remove @babel/runtime-corejs2
    npm install --save @babel/runtime-corejs3
  • @babel/polyfill n'est ni un plugin ni un preset, mais un package d'exécution : si nous avions ajouté une option pour basculer entre core-js@2 et core-js@3, les deux versions auraient dû être incluses dans votre bundle. Pour cette raison, nous avons décidé de le déprécier : vous devez désormais charger core-js pour les polyfills, et regenerator-runtime/runtime si vous transformez des générateurs :

    JavaScript
    // before
    import "@babel/polyfill";

    // after
    import "core-js/stable";
    import "regenerator-runtime/runtime";

    Cela vous donne la possibilité de charger n'importe quelle version souhaitée et de mettre à jour ces deux packages indépendamment.

    Si cela vous intéresse, vous pouvez consulter l'ancien code source de @babel/polyfill pour core-js@2 : packages/babel-polyfill/src/index.js.

Application partielle (#9343 et #9474)

Cette version inclut le support dans @babel/parser et la transformation pour la proposition d'application partielle, actuellement au Stage 1 (présentée pour la dernière fois en juillet 2018). L'implémentation complète a été réalisée par Behrang Yarahmadi, sponsorisé par Trivago.

Cette nouvelle fonctionnalité permet de lier certains arguments et le récepteur this d'une fonction, similaire à la méthode Function#bind existante mais avec moins de limitations.

JavaScript
const half = divide(?, 2); // half = num => divide(num, 3)
half(6); // 3


element.addEventListener(
"click",
// handleEvent will be called with the correct "this".
this.handleEvent("click", ?) // e => this.handleEvent("click", e)
);

Elle est également très utile conjointement avec la proposition de l'opérateur pipeline (surtout avec les variantes "minimal" ou "F-sharp"), car elle permet d'éviter de nombreuses fonctions fléchées :

JavaScript
let newScore = player.score
|> add(?, 7)
|> clamp(0, 100, ?);

// Without this proposal:
let newScore = player.score
|> (_ => add(_, 7))
|> (_ => clamp(0, 100, _));

Vous pouvez la tester en ajoutant @babel/plugin-proposal-partial-application à votre configuration, ou en activant le preset stage 1 dans le repl en ligne !

note

Bien que la proposition décrive aussi l'application partielle pour les littéraux de modèle étiquetés, cela n'a pas été implémenté car elle sera probablement retirée.

Méthodes privées statiques (#9446)

JavaScript
class Person {
static #is(obj) {
return obj instanceof Person;
}

constructor(name) {
if (Person.#is(name)) {
throw "It is already a person!";
}
}
}

Merci encore à Tim (Bloomberg) pour l'implémentation de cette proposition !

Si vous utilisez déjà des méthodes privées d'instance, vous pouvez utiliser cette nouvelle fonctionnalité sans configuration supplémentaire. Sinon, ajoutez @babel/plugin-proposal-private-methods à votre liste de plugins. Dans le repl en ligne, elle est activée par le preset stage-3.

Le support complet des fonctionnalités privées des classes n'est plus qu'à un pas ! 😄

Class PrivateInstanceStatic
Fields
class A { #a = 1 }
7.0.07.1.0
Methods
class A { #a() {} }
7.2.07.4.0
Accessors
class A { get #a() {} }
7.3.0✖️

Support de TypeScript 3.4 RC (#9529 et #9534)

TypeScript 3.4 RC a été publié il y a quelques jours, et grâce à Tan Li Hau il est déjà supporté par Babel !

Deux nouvelles fonctionnalités pour les annotations de type : les contextes const, qui marquent un objet comme "profondément gelé", et le modificateur readonly pour les tableaux et tuples.

JavaScript
const student = {
name: "Joe Blogs",
marks: [25, 23, 30]
} as const;

const vowels: readonly string[] = ["a", "e", "i", "o", "u"];

Gardez à l'esprit que TypeScript 3.4 RC n'est pas une version stable. Vous devriez donc attendre la sortie officielle de TypeScript 3.4 : vous pouvez vous abonner au blog TypeScript pour être notifié lors de sa disponibilité. 🙂

Expressions entre parenthèses (#8025)

Les parenthèses n'ont généralement pas de signification pour les compilateurs JavaScript ou les générateurs de code : elles servent uniquement d'"indices" pour indiquer au parser que certains nœuds ont une précédence différente de celle par défaut :

Code1 + 2 * 3 / 1 + (2 * 3)(1 + 2) * 3
AST structure

Une fois l'AST généré, la précédence des opérations est déterminée par la structure arborescente et non par les parenthèses originales : c'est pourquoi Babel ne les traçait pas.

Lors de l'impression d'un AST, @babel/generator ne connaît pas le formatage original et ne génère des parenthèses que là où c'est nécessaire.

Cela pose problème dans certaines situations. Par exemple, avec Google Closure Compiler, les parenthèses servent à marquer les expressions de transtypage :

JavaScript
/** @type {!MyType} */ (valueExpression)

Nous avions déjà un nœud ParenthesizedExpression pour représenter les parenthèses, mais il n'était jamais généré par @babel/parser et ne pouvait être injecté que par des plugins personnalisés. Grâce au travail d'Erik Arvidsson, vous pouvez désormais utiliser l'option createParenthesizedExpressions du parser pour les suivre automatiquement !

Code1 + (2 * 3)(1 + 2) * 3
AST structure

Conformité aux spécifications de @babel/parser

Daniel améliore continuellement la conformité de @babel/parser aux spécifications ECMAScript : il passe désormais 98,97 % des tests de la suite Test262. 😎

Cette version rend @babel/parser conscient des règles de portée de JavaScript : il sait désormais quelles variables sont déclarées, s'il y a des conflits, si elles sont hoistées, et si une construction syntaxique est autorisée dans son contexte.

Tous ces exemples invalides sont désormais correctement signalés comme erreurs, évitant de devoir les interdire manuellement dans chaque outil utilisant @babel/parser :

JavaScript
let a, a; // Duplicate declaration 💥

if (foo) {
if (bar) { var b }
let b; // Duplicate declaration, again 💥
}

export { Foo }; // Error, Foo is not declared ❓

class C {
constructor() {
super(); // Super in a non-derived class 🤔
}

method(d, d) {} // Duplicate parameter 💥
}

Espaces réservés pour le code (#9364)

Le code n'est pas toujours destiné à être écrit directement par des humains : que faire si du code doit être généré, peut-être via un template prédéfini ?

Les fichiers template sont souvent utilisés pour générer du code HTML, que ce soit avec un langage comme PHP ou un moteur de template comme Handlebars :

<!-- PHP -->
<section>
<h1><?= $title ?></h1>
<main><?= $body ?></main>
</section>

<!-- Handlebars -->
<section>
<h1>{{ title }}</h1>
<main>{{ body }}</main>
</section>

Si vous avez déjà développé un plugin Babel, vous avez probablement utilisé @babel/template : cet utilitaire permet de faire la même chose pour générer du code JavaScript :

JavaScript
const buildAssign = template`
var NAME = VALUE;
`;

const result = buildAssign({
NAME: varName,
VALUE: varValue,
});

Jusqu'à présent, @babel/template utilisait des identifiants en majuscules comme "espaces réservés", qui devaient ensuite être remplacés. Bien que cette approche fonctionnait dans la plupart des cas, elle présentait quelques limites :

  • par défaut, tout identifiant majuscule était considéré comme espace réservé et @babel/template générait une erreur s'il n'était pas remplacé.

  • il était impossible de placer un espace réservé là où un identifiant n'est pas autorisé, par exemple pour un corps de fonction ou une déclaration exportée.

Pour résoudre ces problèmes, nous avons introduit un nouvel élément syntaxique pouvant remplacer n'importe quel nœud : %%placeholder_name%%.

JavaScript
const buildLazyFn = template`
function %%name%%(%%params%%) {
return function () %%body%%;
}
`;

const result = buildLazyFn({
name: functionName,
params: functionParams,
body: functionBody,
});

Cette fonctionnalité a été sponsorisée par Stripe (via Runkit). Nous expérimentons de nouvelles façons de financer Babel, et pour la première fois une entreprise a directement sponsorisé l'implémentation d'une fonctionnalité en rémunérant un membre de l'équipe. Si votre entreprise souhaite sponsoriser l'implémentation d'une proposition ECMAScript ou une amélioration générale de Babel, contactez-nous !


Discuter sur Twitter