Что означает 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 может даже выдать ошибку. Может ли кто-нибудь подтвердить или помочь мне понять реальный смысл?


person Nathan Wall    schedule 21.10.2012    source источник
comment
Вот отправная точка: people.mozilla.org/~jorendorff /es6-draft.html#sec-8.8.4   -  person Fabrício Matté    schedule 21.10.2012
comment
Да, я это читал. Это не имеет для меня полного смысла, но из того, что я могу из этого сделать, похоже, что мне действительно нечего делать на этом шаге, и что если ошибка была выдана ToNumber на шаге 1, она должна быть распространяется, и функция должна завершиться. Однако я не очень понимаю, зачем для этого нужен отдельный шаг, как это следует понимать. Если это так, я хотел бы подтверждения. Если это не так, мне нужна помощь в понимании.   -  person Nathan Wall    schedule 21.10.2012
comment
Ваша интерпретация кажется правильной. Могут быть некоторые детали, которые я упускаю, но важной частью будет возвращение исключения в случае ошибки в покрытии типа, которое я предполагаю.   -  person Fabrício Matté    schedule 21.10.2012


Ответы (1)


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

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;
}
person Community    schedule 21.10.2012
comment
Спасибо! Так что для меня это практически означает ничего не делать. Мне это кажется странным. Может ли ToNumber даже привести к внезапному завершению? Это не так. - person Nathan Wall; 21.10.2012
comment
Кроме того, поправьте меня, если я ошибаюсь, но из моего чтения черновика, который я использую (9-27-12), я думаю, что это ToInteger может быть не на 100% точным из-за строки ToNumber(argument) | 0. Разве это не всегда приводит к конечному числу? Черновик, кажется, указывает, что ToInteger также может привести к бесконечным значениям. - person Nathan Wall; 21.10.2012
comment
Это означает, что ничего не делайте, пока не получите бросок. Подумайте об этом с точки зрения того, что нет попытки поймать. Один из способов реализовать try..catch — делать именно то, что делает спецификация. Возвращайте броски как обычные результаты, но обернутые как тип ThrownValue и всегда проверяйте его. Большую часть времени вам не нужно ничего делать. Но если это особый результат, вам нужно передать его без изменений. Что касается ToInteger, вы действительно правы. Я вроде как некоторые операторы в ожидании второго прохода для деталей. - person ; 22.10.2012
comment
Также следует отметить, что ReturnIfAbrupt является ненаблюдаемой деталью реализации. Спецификация описывает, что должно произойти, но реальные реализации могут работать совершенно по-другому. Одним из примеров может быть использование стиля передачи продолжения и наличие второго канала управления, который используется для передачи специальных результатов, таких как броски. В этом случае вам никогда не придется возиться с проверкой ReturnIfAbrupt, потому что специальное значение никогда не пройдет по обычному каналу. - person ; 22.10.2012