Set Function.name for funcs in variables and properties as per spec.

Implements correct Function.name for cases like following:
 * `var x = function () { ... }`
 * `var obj = {prop: function () { ... }}`
This commit is contained in:
Ingvar Stepanyan 2015-02-15 23:32:14 +02:00
parent 15dff73cc8
commit 17e65cc772
7 changed files with 135 additions and 1 deletions

View File

@ -59,7 +59,8 @@ File.helpers = [
"object-destructuring-empty", "object-destructuring-empty",
"temporal-undefined", "temporal-undefined",
"temporal-assert-defined", "temporal-assert-defined",
"tail-call" "tail-call",
"self-global"
]; ];
File.validOptions = [ File.validOptions = [

View File

@ -0,0 +1,7 @@
(function () {
function GET_OUTER_ID() {
return ID;
}
return FUNCTION;
})()

View File

@ -91,6 +91,7 @@ module.exports = {
"spec.typeofSymbol": require("./spec/typeof-symbol"), "spec.typeofSymbol": require("./spec/typeof-symbol"),
"spec.undefinedToVoid": require("./spec/undefined-to-void"), "spec.undefinedToVoid": require("./spec/undefined-to-void"),
"spec.functionName": require("./spec/function-name"),
_moduleFormatter: require("./internal/module-formatter"), _moduleFormatter: require("./internal/module-formatter"),

View File

@ -0,0 +1,53 @@
"use strict";
var t = require("../../../types");
var util = require("../../../util");
var propertyFunctionVisitor = {
enter: function (node, parent, scope, state, file) {
if (t.isReferencedIdentifier(node, parent, { name: state.name }) && scope.getBindingIdentifier(node.name) === state.binding) {
return state.getOuter();
}
}
};
exports.FunctionExpression = function (node, parent, scope, file) {
if (node.id) return;
var id;
if (t.isProperty(parent)) {
id = parent.key;
} else if (t.isVariableDeclarator(parent)) {
id = parent.id;
} else {
return;
}
var binding = scope.getBindingIdentifier(id.name);
var outerId, selfGlobalId;
scope.traverse(node, propertyFunctionVisitor, {
name: id.name,
binding: binding,
getOuter: function () {
if (!binding) {
return t.memberExpression(
selfGlobalId || (selfGlobalId = file.addHelper("self-global")),
id
);
}
return t.callExpression(
outerId || (outerId = scope.generateUidIdentifier("getOuter")),
[]
);
}
});
node.id = id;
if (outerId) {
return util.template("named-func", {
GET_OUTER_ID: outerId,
ID: id,
FUNCTION: node
});
}
};
exports.optional = true;

View File

@ -0,0 +1,27 @@
var obj = {
f: function () {
(function f() {
console.log(f);
})();
},
g: function () {
console.log(g);
},
h: function () {
console.log(h);
},
m: function () {
doSmth();
}
};
var f = function () {
console.log(f, g);
};
var g = function () {
doSmth();
};

View File

@ -0,0 +1,42 @@
"use strict";
var _selfGlobal = typeof global === "undefined" ? self : global;
var obj = {
f: function f() {
(function f() {
console.log(f);
})();
},
g: (function () {
function _getOuter() {
return g;
}
return function g() {
console.log(_getOuter());
};
})(),
h: function h() {
console.log(_selfGlobal.h);
},
m: function m() {
doSmth();
}
};
var f = (function () {
function _getOuter() {
return f;
}
return function f() {
console.log(_getOuter(), g);
};
})();
var g = function g() {
doSmth();
};

View File

@ -0,0 +1,3 @@
{
"whitelist": ["spec.functionName"]
}