Home Reference Source

src/stdlib/Function.js

'use strict';

const EasyObjectValue = require('../values/EasyObjectValue');
const ClosureValue = require('../values/ClosureValue');
const CompletionRecord = require('../CompletionRecord');
const ASTPreprocessor = require('../ASTPreprocessor');
const PropertyDescriptor = require('../values/PropertyDescriptor');

class FunctionObject extends EasyObjectValue {
	*call(thiz, args, scope) {
		let an = new Array(args.length - 1);
		for ( let i = 0; i < args.length - 1; ++i ) {
			an[i] = (yield * args[i].toStringValue()).toNative();
		}
		let code = 'function name(' + an.join(', ') + ') {\n' + args[args.length - 1].toNative().toString() + '\n}';
		let ast;
		try {
			let oast = scope.realm.parser(code, {loc: true});
			ast = ASTPreprocessor.process(oast);
		} catch ( e ) {
			return new CompletionRecord(CompletionRecord.THROW, e);
		}

		let fn = new ClosureValue(ast.body[0], scope.global);
		fn.boundScope = scope.global;
		return fn;
	}

	_init(realm) {
		super._init(realm);
		let cs = new PropertyDescriptor(this);
		cs.configurable = false;
		cs.enumerable = false;
		this.properties['constructor'] = cs;
	}

	callPrototype(realm) { return realm.FunctionPrototype; }
	get callLength() { return 1; }
	//objPrototype(realm) { return realm.Function; }
}

module.exports = FunctionObject;