Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Javascript, how can I check if a function is in strict mode *without changing the function*?

I want to write a test suite to ensure some given functions are using strict mode. There are many of them, and manually inspecting them seems like a chore.

An answer in a similar question uses a regex on the function's definition to check. However, I believe this will misdetect situations where the function being tested is inside a function with "use strict" or a file-level "use strict" declaration. The answer says that "use strict" is prepended, but in my environment (Mozilla Rhino), this is not the case:

$ 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";
}

I feel like the answer is "no", but is there no way to introspect a function to see if it was parsed and found to be strict mode?

Update: One method suggest by @Amy was to parse the function's source to figure it out. This works if the function has a use-strict declaration (although it's tedious), but not if it the strict-mode is propagation from, say, Program-level; in that case, we have to walk up the AST to the Program level and check that for use strict. To make this robust, we'd have to implement all the rules for use strict-propagation, which the interpreter already has somewhere.

(Tested in 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

)

like image 792
nfirvine Avatar asked Dec 02 '15 19:12

nfirvine


1 Answers

Strict mode functions do have a "poisoned" .caller and .arguments properties (also ES5, extra), so you can test that:

function isStrict(fn) {
    if (typeof fn != "function")
        throw new TypeError("expected function");
    try {
        fn.caller; // expected to throw
        return false;
    } catch(e) {
        return true;
    }
}
like image 184
Bergi Avatar answered Sep 29 '22 10:09

Bergi