Source code

Revision control

Copy as Markdown

Other Tools

// The Function.prototype.toString() representation of sourceless functions
// must match the NativeFunction syntax.
function test() {
// Greatly (!) simplified patterns for the PropertyName production.
var propertyName = [
// PropertyName :: LiteralPropertyName :: IdentifierName
"\\w+",
// PropertyName :: LiteralPropertyName :: StringLiteral
"(?:'[^']*')",
"(?:\"[^\"]*\")",
// PropertyName :: LiteralPropertyName :: NumericLiteral
"\\d+",
// PropertyName :: ComputedPropertyName
"(?:\\[[^\\]]+\\])",
].join("|")
var nativeCode = RegExp([
"^", "function", ("(?:" + propertyName + ")?"), "\\(", "\\)", "\\{", "\\[native code\\]", "\\}", "$"
].join("\\s*"));
function reportMatch(pattern, str) {
assertEq(pattern.test(str), true);
}
// Function declarations.
eval(`
function funDecl() {}
function* genDecl() {}
async function asyncFunDecl() {}
async function* asyncGenDecl() {}
`);
reportMatch(nativeCode, funDecl.toString());
reportMatch(nativeCode, genDecl.toString());
reportMatch(nativeCode, asyncFunDecl.toString());
reportMatch(nativeCode, asyncGenDecl.toString());
// Named function expressions.
eval(`
var funExpr = function fn() {};
var genExpr = function* fn() {};
var asyncFunExpr = async function fn() {};
var asyncGenExpr = async function* fn() {};
`);
reportMatch(nativeCode, funExpr.toString());
reportMatch(nativeCode, genExpr.toString());
reportMatch(nativeCode, asyncFunExpr.toString());
reportMatch(nativeCode, asyncGenExpr.toString());
// Anonymous function expressions.
eval(`
var funExprAnon = function() {};
var genExprAnon = function*() {};
var asyncFunExprAnon = async function() {};
var asyncGenExprAnon = async function*() {};
`);
reportMatch(nativeCode, funExprAnon.toString());
reportMatch(nativeCode, genExprAnon.toString());
reportMatch(nativeCode, asyncFunExprAnon.toString());
reportMatch(nativeCode, asyncGenExprAnon.toString());
// Class declarations and expressions (implicit constructor).
eval(`
class classDecl {}
var classExpr = class C {};
var classExprAnon = class {};
this.classDecl = classDecl;
`);
reportMatch(nativeCode, classDecl.toString());
reportMatch(nativeCode, classExpr.toString());
reportMatch(nativeCode, classExprAnon.toString());
// Class declarations and expressions (explicit constructor).
eval(`
class classDecl { constructor() {} }
var classExpr = class C { constructor() {} };
var classExprAnon = class { constructor() {} };
this.classDecl = classDecl;
`);
reportMatch(nativeCode, classDecl.toString());
reportMatch(nativeCode, classExpr.toString());
reportMatch(nativeCode, classExprAnon.toString());
// Method definitions (identifier names).
eval(`
var obj = {
m() {},
*gm() {},
async am() {},
async* agm() {},
get x() {},
set x(_) {},
};
`);
reportMatch(nativeCode, obj.m.toString());
reportMatch(nativeCode, obj.gm.toString());
reportMatch(nativeCode, obj.am.toString());
reportMatch(nativeCode, obj.agm.toString());
reportMatch(nativeCode, Object.getOwnPropertyDescriptor(obj, "x").get.toString());
reportMatch(nativeCode, Object.getOwnPropertyDescriptor(obj, "x").set.toString());
// Method definitions (string names).
eval(`
var obj = {
"foo m"() {},
* "foo gm"() {},
async "foo am"() {},
async* "foo agm"() {},
get "foo x"() {},
set "foo x"(_) {},
};
`);
reportMatch(nativeCode, obj["foo m"].toString());
reportMatch(nativeCode, obj["foo gm"].toString());
reportMatch(nativeCode, obj["foo am"].toString());
reportMatch(nativeCode, obj["foo agm"].toString());
reportMatch(nativeCode, Object.getOwnPropertyDescriptor(obj, "foo x").get.toString());
reportMatch(nativeCode, Object.getOwnPropertyDescriptor(obj, "foo x").set.toString());
// Method definitions (number names).
eval(`
var obj = {
100() {},
*200() {},
async 300() {},
async* 400() {},
get 500() {},
set 500(_) {},
};
`);
reportMatch(nativeCode, obj[100].toString());
reportMatch(nativeCode, obj[200].toString());
reportMatch(nativeCode, obj[300].toString());
reportMatch(nativeCode, obj[400].toString());
reportMatch(nativeCode, Object.getOwnPropertyDescriptor(obj, 500).get.toString());
reportMatch(nativeCode, Object.getOwnPropertyDescriptor(obj, 500).set.toString());
// Method definitions (computed property names).
var sym1 = Symbol();
var sym2 = Symbol("desc");
var sym3 = Symbol.for("reg-sym");
var sym4 = Symbol.match;
var sym5 = Symbol();
eval(`
var obj = {
[sym1]() {},
*[sym2]() {},
async [sym3]() {},
async* [sym4]() {},
get [sym5]() {},
set [sym5](_) {},
};
`);
reportMatch(nativeCode, obj[sym1].toString());
reportMatch(nativeCode, obj[sym2].toString());
reportMatch(nativeCode, obj[sym3].toString());
reportMatch(nativeCode, obj[sym4].toString());
reportMatch(nativeCode, Object.getOwnPropertyDescriptor(obj, sym5).get.toString());
reportMatch(nativeCode, Object.getOwnPropertyDescriptor(obj, sym5).set.toString());
// Arrow functions.
eval(`
var arrowFn = () => {};
var asyncArrowFn = () => {};
`);
reportMatch(nativeCode, arrowFn.toString());
reportMatch(nativeCode, asyncArrowFn.toString());
// asm.js functions.
eval(`
function asm() {
"use asm";
function f(){ return 0|0; }
return {f: f};
}
`);
reportMatch(nativeCode, asm.toString());
reportMatch(nativeCode, asm().f.toString());
}
var g = newGlobal({ discardSource: true });
g.evaluate(test.toString() + "test()");