// 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()");