Что означает ReturnIfAbrupt в проекте ES6?

В настоящее время я реализую некоторые прокладки для проекта ES6. Мне интересно, может ли кто-нибудь сказать мне, что означает ReturnIfAbrupt. Например, моя реализация для Number.toInt (которая вызывает внутреннюю [[ToInteger]] следующим образом:

if (!('toInt' in Number))
    Object.defineProperty(Number, 'toInt', {

        value: function toInt(value) {
            // ECMA-262 Ed. 6, 9-27-12. 9.1.4

            // 1. Let number be the result of calling ToNumber on the input argument.
            var number = Number(value);

            // 2. ReturnIfAbrupt(number).
            // ?

            // 3. If number is NaN, return +0.
            if (number != number) return 0;

            // 4. If number is +0, -0, +Infinity, or -Infinity, return number.
            if (number == 0 || 1 / number == 0) return number;

            // 5. Return the result of computing sign(number) * floor(abs(number)).
            return (n < 0 ? -1 : 1) * Math.floor(Math.abs(number));

        },

        writable: true,
        configurable: true

    });

Шаг 2 - ReturnIfAbrupt(number). Вы заметите, что у меня есть // ? для этого шага, потому что я не уверен, что делать. Что это значит, когда он говорит ReturnIfAbrupt(...)?

Я прочитал раздел в ReturnIfAbrupt в проекте, однако я не могу понять, что делать для шага 2, что положить вместо // ? в приведенном выше коде.

Из моего чтения может быть, что ничего не должно быть сделано, а шаг ReturnIfAbrupt просто означает, чтобы любая ошибка, которая произошла в ToNumber, распространялась вверх, выходя из функции. Тем не менее, это кажется чересчур многословным, поскольку я думаю, что это могло бы не сказаться. Кроме того, мне не кажется, что ToNumber может даже выбросить ошибку. Может ли кто-нибудь подтвердить или помочь мне понять реальный смысл?

Ответ 1

ReturnIfAbrupt ссылается на Abrutt Completion. Запись завершения содержит тип и значение, связанные с ним. Нормальное завершение было бы чем-то вроде результата выражения. Завершение возврата из функции - это обычное ожидаемое завершение, кроме обычного завершения. Любые другие типы завершения являются резкими. Этот бросок, перерыв, продолжится.

if (isCompletionRecord(v)) {
  if (isAbruptCompletion(v)) {
    return v;
  } else {
    v = v.value;
  }
}

Реализуя это как есть, то, что это повлечет за собой, - это обернуть функцию в try catch. Выброшенное значение будет резким завершением. Это не то, что вы видите на уровне JS, но для реализации потока управления и нелокальных передач управления на уровне двигателя.

Я реализовал большую часть спецификации ES6 на виртуальной машине JS, которая также может помочь пролить свет на нее, здесь ToInteger: https://github.com/Benvie/continuum/blob/master/lib/continuum.js#L516

function ToInteger(argument){
  if (argument && typeof argument === OBJECT && argument.IsCompletion) {
    if (argument.IsAbruptCompletion) {
      return argument;
    }
    argument = argument.value;
  }
  return ToNumber(argument) | 0;
}