В Javascript, как я могу проверить, находится ли функция в строгом режиме * без изменения функции *?

Я хочу написать набор тестов, чтобы убедиться, что некоторые заданные функции используют строгий режим. Их много, и проверять их вручную кажется рутиной.

Ответ в аналогичный вопрос использует регулярное выражение для определения функции для проверки. Однако я считаю, что это приведет к неправильному обнаружению ситуаций, когда тестируемая функция находится внутри функции с «использованием строгого» или с объявлением «использовать строгое» на уровне файла. В ответе говорится, что в начале используется "use strict", но в моей среде (Mozilla Rhino) это не так:

$ cat strict_sub.js
"use strict";
var strict_function = function() {
    not_a_real_global = "foo";
};

print(strict_function);
$ rhino strict_sub.js 

function () {
    not_a_real_global = "foo";
}

Я чувствую, что ответ «нет», но нет ли способа проанализировать функцию, чтобы увидеть, была ли она проанализирована и признана строгой?

Обновление: один из методов, предложенных @Amy, заключался в том, чтобы проанализировать источник функции, чтобы понять это. Это работает, если функция имеет объявление use-strict (хотя это утомительно), но не в том случае, если строгий режим распространяется, скажем, на уровне программы; в этом случае мы должны поднять AST до уровня программы и проверить это для use strict. Чтобы сделать это надежным, нам пришлось бы реализовать все правила для use strict-распространения, которые где-то уже есть в интерпретаторе.

(Проверено в SpiderMonkey:

function f() {
  "use strict";
}
var fast1 = Reflect.parse(f.toString());

var first_line = fast1.body[0].body.body[0].expression;

print(first_line.type === 'Literal' && first_line.value === 'use strict'); //true

)


person nfirvine    schedule 02.12.2015    source источник
comment
Я обычно использую это: var isStrict = (function() { return !this; })(); console.log (строго);   -  person Shakawkaw    schedule 02.12.2015
comment
@Shakawkaw: но это нужно запустить внутри тестируемой функции. Мне нужно проверить его внешне.   -  person nfirvine    schedule 02.12.2015
comment
нет ли способа проанализировать функцию, чтобы убедиться, что она была проанализирована и признана строгой? Нет.   -  person Felix Kling    schedule 02.12.2015
comment
Не без самостоятельного разбора (например, с помощью Spidermonkey Parser API) и проверки полученного AST, нет.   -  person    schedule 02.12.2015
comment
@Amy: я пробовал анализировать с помощью Spidermonkey, но на самом деле он только говорит мне, что (например) там есть строковый литерал. Если есть строгий уровень файла, я должен был бы проверить это и сам.   -  person nfirvine    schedule 04.12.2015
comment
Верно. Вам придется разобрать весь файл.   -  person    schedule 04.12.2015


Ответы (1)


Функции строгого режима имеют свойства "отравленные" .caller и .arguments (также ES5, extra), поэтому вы можете проверить это:

function isStrict(fn) {
    if (typeof fn != "function")
        throw new TypeError("expected function");
    try {
        fn.caller; // expected to throw
        return false;
    } catch(e) {
        return true;
    }
}
person Bergi    schedule 02.12.2015
comment
Источник спецификации был бы полезен. - person Ben Aston; 02.12.2015
comment
О, черт, я перепутал Функция .caller с объектом arguments, который имеет эти отравленные свойства (@BenAston: ES5, ES6) - person Bergi; 02.12.2015
comment
@BenAston: О, я только что наткнулся на это: объекты функций строгого режима на самом деле также имеют отравленные свойства. - person Bergi; 10.12.2015
comment
Я просто не уверен, работает ли это по-прежнему с ES6, где эти отравленные свойства, похоже, унаследованы от Function.prototype, так что даже у неаккуратных функций режима они могут быть, если среда не создает для них нестандартные собственные свойства. - person Bergi; 10.12.2015
comment
Не уверен, что я полностью понимаю, но я реализовал вашу функцию и провел несколько тестов. В Spidermonkey работает хорошо. В Rhino кажется, что function.caller не реализован :( Даже если ваш ответ не работает в Rhino, я бы сказал, что это Rhino сломан. - person nfirvine; 10.12.2015
comment
@nfirvine: эта функция не зависит от .caller поддержки функций. Он опирается на спецификацию ES5, требующую, чтобы функции строгого режима не реализовывали его, и даже более того, он должен был генерировать. Вы тестировали в Rhino? Следует ли Rhino ES5 или ES6? - person Bergi; 11.12.2015