microsoft / microsoft/TypeScript

Proposal: Add new __construct helper for better ES5/ES6 class interop

Abierto
#15,397 3 comentarios 26 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Awaiting More Feedback Suggestion
Lenguaje dominante
Go
Estrellas
111k
Forks
14.4k
Merge medio
1 d 19 h
PR fusionados (30 d)
117

Descripción

I propose we add a new helper to assist with class instance construction runtime semantics when extending ES6 built-in classes while compiling with --target ES5.

Background

Our current emit for classes for --target ES5 assumes that the superclass follows the same runtime semantics as the classes we emit. Generally this means that the constructor can be called as a function via call() or apply(). However, a number of ES6 built-in classes are specified to throw when not used as a constructor (i.e. Promise, Map, etc.), and other ES6 built-in classes return a value when called, ignoring the this value provided to call() or apply() (i.e. Error, Array, etc.).

Previously we provided guidance for possible workarounds for this to support the latter scenario, but we do not currently have a solution for the former scenario.

Proposal

The following code listing describes a new __construct helper that we would need to emit for any file that contains an explicit (or implicit, for property declarations) super() call:

class MyPromise extends Promise {
  constructor(executor) {
    super(executor);
  }
}

// becomes...
var __extends = ...;
var __construct = (this && this.__construct) || (typeof Reflect !== "undefined" && Reflect.construct
    ? function (s, t, a, n) { return t !== null ? Reflect.construct(t, a, n) : s; }
    : function (s, t, a) { return t !== null && t.apply(s, a) || s; });

var MyPromise = (function (_super) {
  __extends(MyPromise, _super);
  function MyPromise(executor) {
    var _this = this;
    var _newTarget = this.constructor;
    _this = __construct(this, _super, [executor], _newTarget);
    return _this;
  }
  return MyPromise;
})(Promise);
Benefits
  • Allows down-level class emit to extend ES6 built-ins if running in an ES6 host by feature detecting Reflect.construct.
  • Falls back to the existing behavior when running in an ES5 host.
  • Handles extends null and extends x when x is null in the same way as existing behavior.
  • Handles custom return values from super in the same way as existing behavior.
Drawbacks
  • Larger helper footprint
  • Subclassing a built-in in an ES5 host has different runtime semantics than subclassing a built-in in an ES6 host:
    • In ES5, subclassing Array or Error will not have the correct prototype chain. The only solution is to explicitly set the prototype chain using the non-standard __proto__ property as per established guidance.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

El issue propone un nuevo helper __construct para la emisión de clases ES5 al extender built-ins de ES6. Empieza localizando el helper __extends existente y la emisión de clases a una versión inferior; la propuesta define la detección de la funcionalidad Reflect.construct y el comportamiento de fallback. Se considera terminado cuando se admitan las semánticas descritas para hosts ES6 y hosts ES5, incluidos extends null y los valores de retorno personalizados de super.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
javascript, typescript
Área
compilers
Tipo de issue
Nueva funcionalidad
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
30/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.