<commit_before>/**
 * <p>Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.</p>
 * 
 * This module defines and injects the built-in global objects into the global namespace.
 * 
 * @module Global
 * @author <NAME> &lt;<a href="mailto:<EMAIL>"><EMAIL></a>&gt;
 */
 
var util = require("util"),

	Base = require("./Base"),
	Runtime = require("./Runtime"),
	RuleProcessor = require("./RuleProcessor"),
	AST = require("./AST"),
	Exceptions = require("./Exceptions");

/*****************************************
 *
 * Non-spec helpers
 *
 *****************************************/

/**
 * Injects
 */
exports.injectGlobals = injectGlobals;
function injectGlobals() {
	
	var globalEnvironmentRecord = Runtime.globalContext.lexicalEnvironment.envRec;
	
	function addObject(name, value) {
		globalEnvironmentRecord.createMutableBinding(name, false, true);
		globalEnvironmentRecord.setMutableBinding(name, value, false, true);
	}
	
	addObject("eval", new EvalFunction());
	addObject("parseInt", new ParseIntFunction());
	addObject("parseFloat", new ParseFloatFunction());
	addObject("isNaN", new IsNaNFunction());
	addObject("isFinite", new IsFiniteFunction());
	addObject("decodeURI", new DecodeURIFunction());
	addObject("decodeURIComponent", new DecodeURIComponentFunction());
	addObject("encodeURI", new EncodeURIFunction());
	addObject("encodeURIComponent", new EncodeURIComponentFunction());
	addObject("Object", new ObjectConstructor());
	addObject("Function", new FunctionConstructor());
	addObject("Array", new ArrayConstructor());
	addObject("String", new StringConstructor());
	addObject("Boolean", new BooleanConstructor());
	addObject("Number", new NumberConstructor());
	addObject("Date", new DateConstructor());
	addObject("RegExp", new RegExpConstructor());
	addObject("Error", new ErrorConstructor("Error"));
	addObject("EvalError", new ErrorConstructor("EvalError"));
	addObject("RangeError", new ErrorConstructor("RangeError"));
	addObject("ReferenceError", new ErrorConstructor("ReferenceError"));
	addObject("SyntaxError", new ErrorConstructor("SyntaxError"));
	addObject("TypeError", new ErrorConstructor("TypeError"));
	addObject("URIError", new ErrorConstructor("URIError"));
	addObject("Math", new MathObject());
	addObject("JSON", new JSONObject());
}

/*****************************************
 *
 * Chapter 15 - Global Functions
 *
 *****************************************/

/**
 * eval method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.1
 */
function EvalFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(EvalFunction, Base.FunctionTypeBase);
EvalFunction.prototype.call = function call(thisVal, args) {
	
	var x = args[0],
		prog,
		evalCtx,
		result;
	
	// Step 1
	if (Base.type(x) !== "String") {
		return x;
	}
	
	// Step 2
	if (!(prog = AST.parseString(x.value))) {
		throw new Exceptions.SyntaxError();
	}
	
	// Step 3
	evalCtx = Base.createEvalContext(Runtime.getCurrentContext(), prog, 
		!!(prog[0] && prog[0][0].name === "directive" && prog[0][1] === "use strict"));
	Runtime.contextStack.push(evalCtx);
	
	// Step 4
	prog.useCurrentContext = true;
	result = RuleProcessor.processRule(prog);
	
	// Step 5
	Runtime.contextStack.pop();
	
	// Step 6
	if (result[0] === "normal") {
		return result[1] ? result[1] : new Base.UndefinedType();
	} else {
		throw new Exceptions.Error();
	}
};

/**
 * parseInt method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.2
 */
function ParseIntFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(2), false, true);
}
util.inherits(ParseIntFunction, Base.FunctionTypeBase);
ParseIntFunction.prototype.call = function call(thisVal, args) {
	
	// Steps 1, 2, and 6
	var string = args[0],
		radix = args[1],
		s = Base.toString(string).value.trim(),
		r = radix && Base.type(radix) !== "Undefined" ? Base.toInt32(radix).value : 10;
		
	// Use the built-in method to perform the parseInt
	return new Base.NumberType(parseInt(s, r));
};

/**
 * parseFloat method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.3
 */
function ParseFloatFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(ParseFloatFunction, Base.FunctionTypeBase);
ParseFloatFunction.prototype.call = function call(thisVal, args) {
	
	// Steps 1 and 2
	var string = args[0],
		s = Base.toString(string).value.trim();
		
	// Use the built-in method to perform the parseFloat
	return new Base.NumberType(parseFloat(s));
};

/**
 * isNaN method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.4
 */
function IsNaNFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(IsNaNFunction, Base.FunctionTypeBase);
IsNaNFunction.prototype.call = function call(thisVal, args) {
		
	// Use the built-in method to perform the isNaN
	return new Base.BooleanType(isNaN(Base.toNumber(args[0]).value));
};

/**
 * isFinite method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.5
 */
function IsFiniteFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(IsFiniteFunction, Base.FunctionTypeBase);
IsFiniteFunction.prototype.call = function call(thisVal, args) {
		
	// Use the built-in method to perform the isFinite
	return new Base.BooleanType(isFinite(Base.toNumber(args[0]).value));
};

/**
 * decodeURI method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.3.1
 */
function DecodeURIFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(DecodeURIFunction, Base.FunctionTypeBase);
DecodeURIFunction.prototype.call = function call(thisVal, args) {
	
	// Use the built-in method to perform the decodeURI
	return new Base.StringType(decodeURI(Base.toString(args[0]).value));
};

/**
 * decodeURIComponent method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.3.2
 */
function DecodeURIComponentFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(DecodeURIComponentFunction, Base.FunctionTypeBase);
DecodeURIComponentFunction.prototype.call = function call(thisVal, args) {
	
	// Use the built-in method to perform the decodeURI
	return new Base.StringType(decodeURIComponent(Base.toString(args[0]).value));
};

/**
 * encodeURI method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.3.3
 */
function EncodeURIFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(EncodeURIFunction, Base.FunctionTypeBase);
EncodeURIFunction.prototype.call = function call(thisVal, args) {
	
	// Use the built-in method to perform the decodeURI
	return new Base.StringType(encodeURI(Base.toString(args[0]).value));
};

/**
 * encodeURIComponent method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.3.4
 */
function EncodeURIComponentFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(EncodeURIComponentFunction, Base.FunctionTypeBase);
EncodeURIComponentFunction.prototype.call = function call(thisVal, args) {
	
	// Use the built-in method to perform the decodeURI
	return new Base.StringType(encodeURIComponent(Base.toString(args[0]).value));
};

/*****************************************
 *
 * Chapter 15 - Global Constructors
 *
 *****************************************/

// ******** Object Constructor ********

/**
 * getPrototypeOf() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectGetPrototypeOfFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(ObjectGetPrototypeOfFunc, Base.FunctionTypeBase);
ObjectGetPrototypeOfFunc.prototype.call = function call(thisVal, args) {
	var o = args[0];
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	return o.objectPrototype ? o.objectPrototype : new UndefinedType();
};

/**
 * getOwnPropertyDescriptor() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectGetOwnPropertyDescriptorFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(2), false, true);
}
util.inherits(ObjectGetOwnPropertyDescriptorFunc, Base.FunctionTypeBase);
ObjectGetOwnPropertyDescriptorFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p = args[1],
		name,
		desc;
	
	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	name = Base.toString(p).value;
	
	// Steps 3 and 4
	return Base.fromPropertyDescriptor(o.getOwnProperty(name));
};

/**
 * getOwnPropertyNames() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectGetOwnPropertyNamesFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(ObjectGetOwnPropertyNamesFunc, Base.FunctionTypeBase);
ObjectGetOwnPropertyNamesFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		array,
		n = 0,
		name;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	array = new Base.ArrayType();
	
	// Step 4
	for (name in o._properties) {
		array.defineOwnProperty(n, {
			value: name,
			writable: true,
			enumerable: true,
			configurable: true
		}, false, true);
		n++;
	}
	
	// Step 5
	return array;
};

/**
 * create() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectCreateFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectCreateFunc, Base.FunctionTypeBase);
ObjectCreateFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		properties = args[1],
		obj;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	obj = new Base.ObjectType();
	
	// Step 3
	obj.objectPrototype = o;
	
	// Step 4
	if (properties && Base.type(properties) !== "Undefined") {
		ObjectDefinePropertiesFunc.prototype.call(thisVal, [obj, properties]);
	}
	
	// Step 5
	return obj;
};

/**
 * defineProperties() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectDefinePropertyFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectDefinePropertyFunc, Base.FunctionTypeBase);
ObjectDefinePropertyFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p = args[1],
		attributes = args[2],
		obj,
		name,
		desc;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	name = Base.toString(p).value;
	
	// Step 3
	desc = Base.toPropertyDescriptor(attributes);
	
	// Step 4
	o.defineOwnProperty(name, desc, true);
	
	// Step 5
	return o;
};

/**
 * defineProperties() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectDefinePropertiesFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectDefinePropertiesFunc, Base.FunctionTypeBase);
ObjectDefinePropertiesFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		properties = args[1],
		props = Base.toObject(properties),
		names = Object.keys(props._properties),
		i = 0,
		len = names.length,
		p;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Steps 5 and 6
	for(; i < len; i++) {
		p = names[i];
		o.defineOwnProperty(p, Base.toPropertyDescriptor(props.get(p)), true);
	}
	
	// Step 7
	return o;
};

/**
 * seal() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectSealFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectSealFunc, Base.FunctionTypeBase);
ObjectSealFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p,
		desc;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	for(p in o._properties) {
		desc = o.getOwnProperty(p);
		desc.configurable = false;
		o.defineOwnProperty(p, desc, true);
	}
	
	// Step 3
	o.extensible = false;
	
	// Step 4
	return o;
};

/**
 * freeze() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectFreezeFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectFreezeFunc, Base.FunctionTypeBase);
ObjectFreezeFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p,
		desc;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	for(p in o._properties) {
		desc = o.getOwnProperty(p);
		if (Base.isDataDescriptor(desc)) {
			desc.writable = false;
		}
		desc.configurable = false;
		o.defineOwnProperty(p, desc, true);
	}
	
	// Step 3
	o.extensible = false;
	
	// Step 4
	return o;
};

/**
 * preventExtensions() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectPreventExtensionsFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectPreventExtensionsFunc, Base.FunctionTypeBase);
ObjectPreventExtensionsFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0];

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	o.extensible = false;
	
	// Step 3
	return o;
};

/**
 * isSealed() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectIsSealedFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectIsSealedFunc, Base.FunctionTypeBase);
ObjectIsSealedFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	for(p in o._properties) {
		if (o.getOwnProperty(p).configurable) {
			return new Base.BooleanType(false);
		}
	}
	
	// Step 3
	return new Base.BooleanType(!o.extensible);
};

/**
 * isFrozen() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectIsFrozenFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectIsFrozenFunc, Base.FunctionTypeBase);
ObjectIsFrozenFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		desc,
		p;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	for(p in o._properties) {
		desc = o.getOwnProperty(p);
		if ((Base.isDataDescriptor(desc) && desc.writable) || desc.configurable) {
			return new Base.BooleanType(false);
		}
	}
	
	// Step 3
	return new Base.BooleanType(!o.extensible);
};

/**
 * isExtensible() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectIsExtensibleFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectIsExtensibleFunc, Base.FunctionTypeBase);
ObjectIsExtensibleFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0];

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	return new Base.BooleanType(o.extensible);
};

/**
 * keys() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectKeysFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectKeysFunc, Base.FunctionTypeBase);
ObjectKeysFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		array,
		index = 0,
		p;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 3
	array = new Base.ArrayType();
	
	// Step 5
	for(p in o._properties) {
		if (o._properties[p].enumerable) {
			array.defineOwnProperty(index, {
				value: new Base.StringType(p),
				writable: true,
				enumerable: true,
				configurable: true
			}, false);
			index++;
		}
	}
	
	// Step 6
	return array;
};

/**
 * Object constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2
 */
function ObjectConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
	
	this.put("getPrototypeOf", new ObjectGetPrototypeOfFunc(), false, true);
	this.put("getOwnPropertyDescriptor", new ObjectGetOwnPropertyDescriptorFunc(), false, true);
	this.put("getOwnPropertyNames", new ObjectGetOwnPropertyNamesFunc(), false, true);
	this.put("create", new ObjectCreateFunc(), false, true);
	this.put("defineProperty", new ObjectDefinePropertyFunc(), false, true);
	this.put("defineProperties", new ObjectDefinePropertiesFunc(), false, true);
	this.put("seal", new ObjectSealFunc(), false, true);
	this.put("freeze", new ObjectFreezeFunc(), false, true);
	this.put("preventExtensions", new ObjectPreventExtensionsFunc(), false, true);
	this.put("isSealed", new ObjectIsSealedFunc(), false, true);
	this.put("isFrozen", new ObjectIsFrozenFunc(), false, true);
	this.put("isExtensible", new ObjectIsExtensibleFunc(), false, true);
	this.put("keys", new ObjectKeysFunc(), false, true);
}
util.inherits(ObjectConstructor, Base.FunctionTypeBase);
ObjectConstructor.prototype.call = function call(thisVal, args) {
	
	var value = args[0];
	
	// Step 1
	if (!value || Base.isType(value, ["Null", "Undefined"])) {
		return new Base.ObjectType();
	}
	
	// Step 2
	return Base.toObject(value);
};
ObjectConstructor.prototype.construct = function call(args) {
	debugger;
	var value = args[0],
		obj;
	
	// Step 1
	if (value && !Base.isType(value, ["Undefined", "Null"])) {
		if (Base.type(value) === "Object") {
			return value;
		} else {
			return Base.toObject(value);
		}
	}
	
	// Steps 3-8
	return new Base.ObjectType();
};

// ******** Function Constructor ********

/**
 * Function constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function FunctionConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(FunctionConstructor, Base.FunctionTypeBase);
FunctionConstructor.prototype.call = function call(thisVal, args) {
	return FunctionConstructor.prototype.construct.call(this, args);
};
FunctionConstructor.prototype.construct = function call(args) {
	
	var argCount = args.length,
		p = "",
		parsedParameters,
		body,
		k = 1,
		i = 0,
		len;
	
	// Step 3
	if (argCount === 0) {
		body = new Base.StringType();

	// Step 4
	} else if (argCount === 1) {
		body = args[0];
		
	// Step 5
	} else if (argCount > 1) {
		p = Base.toString(args[0]).value;
		while (k < argCount - 1) {
			p += "," + Base.toString(args[k]).value;
			k++;
		}
		body = args[k];
	}
	
	// Step 6
	body = Base.toString(body).value;
	
	// Step 7
	p = AST.parseString("function temp(" + p + "){}");
	if (!p) {
		throw new Exceptions.SyntaxError();
	}
	p = p[1][0][2];
	
	// Step 8
	body = AST.parseString("function temp(){" + body + "}");
	if (!body) {
		throw new Exceptions.SyntaxError();
	}
	body = body[1][0][3];
	
	// Step 10
	return new Base.FunctionType(p, body, Runtime.getGlobalContext().lexicalEnvironment, 
		!!(body[0] && body[0][0].name === "directive" && [0][1] === "use strict"));
};

// ******** Array Constructor ********

/**
 * isArray() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ArrayIsArrayFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(ArrayIsArrayFunc, Base.FunctionTypeBase);
ArrayIsArrayFunc.prototype.call = function call(thisVal, args) {
	
	var arg = args[0];
	
	// Steps 1 and 2
	return new Base.BooleanType(Base.type(arg) === "Object" && arg.className === "Array");
};

/**
 * Array constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function ArrayConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
	
	this.put("isArray", new ArrayIsArrayFunc(), false, true);
}
util.inherits(ArrayConstructor, Base.FunctionTypeBase);
ArrayConstructor.prototype.call = function call(thisVal, args) {
	return ArrayConstructor.prototype.construct.call(this, args);
};
ArrayConstructor.prototype.construct = function call(args) {
	debugger;
	var array = new Base.ArrayType(),
		len,
		i = 0;
	
	if (args.length === 1) {
		len = args[0];
		if (type(len) === "Number") {
			if (len.value === Base.toUint32(len).value) {
				array.put("length", Base.toUint32(len), true);
			} else {
				throw new Exceptions.RangeError();
			}
		} else {
			array.put("length", new Base.NumberType(1), true);
			array.put("0", len, true);
		}
	} else if (args.length > 1){
		len = args.length
		array.put("length", new Base.NumberType(len), true);
		for(; i < len; i++) {
			array.put(i, args[i], true);
		}
	}
	
	return array;
};

// ******** String Constructor ********

/**
 * isArray() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function StringFromCharCodeFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(StringFromCharCodeFunc, Base.FunctionTypeBase);
StringFromCharCodeFunc.prototype.call = function call(thisVal, args) {
	
	var i = 0,
		len = args.length;
	
	// Convert the array to something we can apply()
	for(; i < len; i++) {
		args[i] = Base.toUint16(args[i]).value;
	}
	
	// Use the built-in match method to perform the match
	return new Base.StringType(String.fromCharCode.apply(this, args));
};

/**
 * String constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function StringConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
	
	this.put("fromCharCode", new StringFromCharCodeFunc(), false, true);
}
util.inherits(StringConstructor, Base.FunctionTypeBase);
StringConstructor.prototype.call = function call(thisVal, args) {
	
	var value = args[0];
	
	if (!value) {
		return new Base.StringType();
	}
	return Base.toString(value);
};
StringConstructor.prototype.construct = function call(args) {
	
	var value = args[0],
		obj = new Base.ObjectType();
	
	obj.className = "String";
	obj.primitiveValue = value ? Base.toString(value).value : "";
	obj.objectPrototype = new Base.StringPrototypeType();
	
	return obj;
};

// ******** Boolean Constructor ********

/**
 * Boolean constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function BooleanConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(BooleanConstructor, Base.FunctionTypeBase);
BooleanConstructor.prototype.call = function call(thisVal, args) {
	return Base.toBoolean(args[0]);
};
BooleanConstructor.prototype.construct = function call(args) {
	
	var value = args[0],
		obj = new Base.ObjectType();
	
	obj.className = "Boolean";
	obj.primitiveValue = value ? Base.toBoolean(value).value : "";
	obj.objectPrototype = new Base.BooleanPrototypeType();
		
	return obj;
	
};

// ******** Number Constructor ********

/**
 * Number constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function NumberConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);

	this.put("MAX_VALUE", new Base.NumberType(Number.MAX_VALUE), false, true);
	this.put("MIN_VALUE", new Base.NumberType(Number.MIN_VALUE), false, true);
	this.put("NaN", new Base.NumberType(Number.NaN), false, true);
	this.put("NEGATIVE_INFINITY", new Base.NumberType(Number.NEGATIVE_INFINITY), false, true);
	this.put("POSITIVE_INFINITY", new Base.NumberType(Number.POSITIVE_INFINITY), false, true);
}
util.inherits(NumberConstructor, Base.FunctionTypeBase);
NumberConstructor.prototype.call = function call(thisVal, args) {
	return Base.toNumber(args[0]);
};
NumberConstructor.prototype.construct = function call(args) {
	
	var value = args[0],
		obj = new Base.ObjectType();
	
	obj.className = "Number";
	obj.primitiveValue = value ? Base.toNumber(value).value : "";
	obj.objectPrototype = new Base.NumberPrototypeType();
		
	return obj;
};

// ******** RegExp Constructor ********

/**
 * RegExp constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function RegExpConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(RegExpConstructor, Base.FunctionTypeBase);
RegExpConstructor.prototype.call = function call(thisVal, args) {
	
	var pattern = args[0],
		flags = args[1];
	
	if (type(pattern) === "Object" && pattern.className = "RegExp") {
		return pattern;
	}
	
	return RegExpConstructor.prototype.construct(args);
};
RegExpConstructor.prototype.construct = function call(args) {
	
	var obj,
		pattern = args[0],
		flags = args[1],
		p,
		f;
	
	// Parse the parameters
	if (Base.type(pattern) === "Object" && pattern.className === "RegExp") {
		if (flags && Base.type(flags) !== "Undefined") {
			throw new Exceptions.TypeError();
		}
		p = pattern._pattern;
		f = pattern._flags;
	} else {
		p = pattern && Base.type(pattern) !== "Undefined" ? Base.toString(pattern).value : "";
		f = flags && Base.type(flags) !== "Undefined" ? Base.toString(flags).value : "";
	}
	
	// Create the regex object
	return new Base.RegExpType(p, f);
};

// ******** Date Type Class ********
<commit_msg>[TIMOB-10117] Fleshed out exception handling in eval() and cleaned up some code.<commit_after>/**
 * <p>Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.</p>
 * 
 * This module defines and injects the built-in global objects into the global namespace.
 * 
 * @module Global
 * @author <NAME> &lt;<a href="mailto:<EMAIL>"><EMAIL></a>&gt;
 */
 
var util = require("util"),

	Base = require("./Base"),
	Runtime = require("./Runtime"),
	RuleProcessor = require("./RuleProcessor"),
	AST = require("./AST"),
	Exceptions = require("./Exceptions");

/*****************************************
 *
 * Non-spec helpers
 *
 *****************************************/

/**
 * Injects
 */
exports.injectGlobals = injectGlobals;
function injectGlobals() {
	
	var globalEnvironmentRecord = Runtime.globalContext.lexicalEnvironment.envRec;
	
	function addObject(name, value) {
		globalEnvironmentRecord.createMutableBinding(name, false, true);
		globalEnvironmentRecord.setMutableBinding(name, value, false, true);
	}
	
	addObject("eval", new EvalFunction());
	addObject("parseInt", new ParseIntFunction());
	addObject("parseFloat", new ParseFloatFunction());
	addObject("isNaN", new IsNaNFunction());
	addObject("isFinite", new IsFiniteFunction());
	addObject("decodeURI", new DecodeURIFunction());
	addObject("decodeURIComponent", new DecodeURIComponentFunction());
	addObject("encodeURI", new EncodeURIFunction());
	addObject("encodeURIComponent", new EncodeURIComponentFunction());
	addObject("Object", new ObjectConstructor());
	addObject("Function", new FunctionConstructor());
	addObject("Array", new ArrayConstructor());
	addObject("String", new StringConstructor());
	addObject("Boolean", new BooleanConstructor());
	addObject("Number", new NumberConstructor());
	addObject("Date", new DateConstructor());
	addObject("RegExp", new RegExpConstructor());
	addObject("Error", new ErrorConstructor("Error"));
	addObject("EvalError", new ErrorConstructor("EvalError"));
	addObject("RangeError", new ErrorConstructor("RangeError"));
	addObject("ReferenceError", new ErrorConstructor("ReferenceError"));
	addObject("SyntaxError", new ErrorConstructor("SyntaxError"));
	addObject("TypeError", new ErrorConstructor("TypeError"));
	addObject("URIError", new ErrorConstructor("URIError"));
	addObject("Math", new MathObject());
	addObject("JSON", new JSONObject());
}

/*****************************************
 *
 * Chapter 15 - Global Functions
 *
 *****************************************/

/**
 * eval method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.1
 */
function EvalFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(EvalFunction, Base.FunctionTypeBase);
EvalFunction.prototype.call = function call(thisVal, args) {
	
	var x = args[0],
		prog,
		evalCtx,
		result,
		exception;
	
	// Step 1
	if (Base.type(x) !== "String") {
		return x;
	}
	
	// Step 2
	if (!(prog = AST.parseString(x.value))) {
		throw new Exceptions.SyntaxError();
	}
	
	// Step 3
	evalCtx = Base.createEvalContext(Runtime.getCurrentContext(), prog, 
		!!(prog[0] && prog[0][0].name === "directive" && prog[0][1] === "use strict"));
	Runtime.contextStack.push(evalCtx);
	
	// Step 4
	prog.useCurrentContext = true;
	result = RuleProcessor.processRule(prog);
	
	// Step 5
	Runtime.contextStack.pop();
	
	// Step 6
	if (result[0] === "normal") {
		return result[1] ? result[1] : new Base.UndefinedType();
	} else {
		if (result[1]) {
			if (result[1].className.match("Error$")) {
				exception = new Exceptions[result[1].className]();
				exception.name = result[1].get("name");
				exception.message = result[1].get("message");
				throw exception;
			} else {
				throw new Exceptions.Error(Base.toString(result[1]).value);
			}
		} else {
			throw new Exceptions.Error();
		}
	}
};

/**
 * parseInt method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.2
 */
function ParseIntFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(2), false, true);
}
util.inherits(ParseIntFunction, Base.FunctionTypeBase);
ParseIntFunction.prototype.call = function call(thisVal, args) {
	
	// Steps 1, 2, and 6
	var string = args[0],
		radix = args[1],
		s = Base.toString(string).value.trim(),
		r = radix && Base.type(radix) !== "Undefined" ? Base.toInt32(radix).value : 10;
		
	// Use the built-in method to perform the parseInt
	return new Base.NumberType(parseInt(s, r));
};

/**
 * parseFloat method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.3
 */
function ParseFloatFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(ParseFloatFunction, Base.FunctionTypeBase);
ParseFloatFunction.prototype.call = function call(thisVal, args) {
	
	// Steps 1 and 2
	var string = args[0],
		s = Base.toString(string).value.trim();
		
	// Use the built-in method to perform the parseFloat
	return new Base.NumberType(parseFloat(s));
};

/**
 * isNaN method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.4
 */
function IsNaNFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(IsNaNFunction, Base.FunctionTypeBase);
IsNaNFunction.prototype.call = function call(thisVal, args) {
		
	// Use the built-in method to perform the isNaN
	return new Base.BooleanType(isNaN(Base.toNumber(args[0]).value));
};

/**
 * isFinite method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.2.5
 */
function IsFiniteFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(IsFiniteFunction, Base.FunctionTypeBase);
IsFiniteFunction.prototype.call = function call(thisVal, args) {
		
	// Use the built-in method to perform the isFinite
	return new Base.BooleanType(isFinite(Base.toNumber(args[0]).value));
};

/**
 * decodeURI method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.3.1
 */
function DecodeURIFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(DecodeURIFunction, Base.FunctionTypeBase);
DecodeURIFunction.prototype.call = function call(thisVal, args) {
	
	// Use the built-in method to perform the decodeURI
	return new Base.StringType(decodeURI(Base.toString(args[0]).value));
};

/**
 * decodeURIComponent method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.3.2
 */
function DecodeURIComponentFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(DecodeURIComponentFunction, Base.FunctionTypeBase);
DecodeURIComponentFunction.prototype.call = function call(thisVal, args) {
	
	// Use the built-in method to perform the decodeURI
	return new Base.StringType(decodeURIComponent(Base.toString(args[0]).value));
};

/**
 * encodeURI method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.3.3
 */
function EncodeURIFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(EncodeURIFunction, Base.FunctionTypeBase);
EncodeURIFunction.prototype.call = function call(thisVal, args) {
	
	// Use the built-in method to perform the decodeURI
	return new Base.StringType(encodeURI(Base.toString(args[0]).value));
};

/**
 * encodeURIComponent method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.1.3.4
 */
function EncodeURIComponentFunction(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(EncodeURIComponentFunction, Base.FunctionTypeBase);
EncodeURIComponentFunction.prototype.call = function call(thisVal, args) {
	
	// Use the built-in method to perform the decodeURI
	return new Base.StringType(encodeURIComponent(Base.toString(args[0]).value));
};

/*****************************************
 *
 * Chapter 15 - Global Constructors
 *
 *****************************************/

// ******** Object Constructor ********

/**
 * getPrototypeOf() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectGetPrototypeOfFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(ObjectGetPrototypeOfFunc, Base.FunctionTypeBase);
ObjectGetPrototypeOfFunc.prototype.call = function call(thisVal, args) {
	var o = args[0];
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	return o.objectPrototype ? o.objectPrototype : new UndefinedType();
};

/**
 * getOwnPropertyDescriptor() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectGetOwnPropertyDescriptorFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(2), false, true);
}
util.inherits(ObjectGetOwnPropertyDescriptorFunc, Base.FunctionTypeBase);
ObjectGetOwnPropertyDescriptorFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p = args[1],
		name,
		desc;
	
	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	name = Base.toString(p).value;
	
	// Steps 3 and 4
	return Base.fromPropertyDescriptor(o.getOwnProperty(name));
};

/**
 * getOwnPropertyNames() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectGetOwnPropertyNamesFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(ObjectGetOwnPropertyNamesFunc, Base.FunctionTypeBase);
ObjectGetOwnPropertyNamesFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		array,
		n = 0,
		name;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	array = new Base.ArrayType();
	
	// Step 4
	for (name in o._properties) {
		array.defineOwnProperty(n, {
			value: name,
			writable: true,
			enumerable: true,
			configurable: true
		}, false, true);
		n++;
	}
	
	// Step 5
	return array;
};

/**
 * create() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectCreateFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectCreateFunc, Base.FunctionTypeBase);
ObjectCreateFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		properties = args[1],
		obj;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	obj = new Base.ObjectType();
	
	// Step 3
	obj.objectPrototype = o;
	
	// Step 4
	if (properties && Base.type(properties) !== "Undefined") {
		ObjectDefinePropertiesFunc.prototype.call(thisVal, [obj, properties]);
	}
	
	// Step 5
	return obj;
};

/**
 * defineProperties() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectDefinePropertyFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectDefinePropertyFunc, Base.FunctionTypeBase);
ObjectDefinePropertyFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p = args[1],
		attributes = args[2],
		obj,
		name,
		desc;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	name = Base.toString(p).value;
	
	// Step 3
	desc = Base.toPropertyDescriptor(attributes);
	
	// Step 4
	o.defineOwnProperty(name, desc, true);
	
	// Step 5
	return o;
};

/**
 * defineProperties() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectDefinePropertiesFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectDefinePropertiesFunc, Base.FunctionTypeBase);
ObjectDefinePropertiesFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		properties = args[1],
		props = Base.toObject(properties),
		names = Object.keys(props._properties),
		i = 0,
		len = names.length,
		p;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Steps 5 and 6
	for(; i < len; i++) {
		p = names[i];
		o.defineOwnProperty(p, Base.toPropertyDescriptor(props.get(p)), true);
	}
	
	// Step 7
	return o;
};

/**
 * seal() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectSealFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectSealFunc, Base.FunctionTypeBase);
ObjectSealFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p,
		desc;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	for(p in o._properties) {
		desc = o.getOwnProperty(p);
		desc.configurable = false;
		o.defineOwnProperty(p, desc, true);
	}
	
	// Step 3
	o.extensible = false;
	
	// Step 4
	return o;
};

/**
 * freeze() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectFreezeFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectFreezeFunc, Base.FunctionTypeBase);
ObjectFreezeFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p,
		desc;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	for(p in o._properties) {
		desc = o.getOwnProperty(p);
		if (Base.isDataDescriptor(desc)) {
			desc.writable = false;
		}
		desc.configurable = false;
		o.defineOwnProperty(p, desc, true);
	}
	
	// Step 3
	o.extensible = false;
	
	// Step 4
	return o;
};

/**
 * preventExtensions() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectPreventExtensionsFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectPreventExtensionsFunc, Base.FunctionTypeBase);
ObjectPreventExtensionsFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0];

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	o.extensible = false;
	
	// Step 3
	return o;
};

/**
 * isSealed() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectIsSealedFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectIsSealedFunc, Base.FunctionTypeBase);
ObjectIsSealedFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		p;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	for(p in o._properties) {
		if (o.getOwnProperty(p).configurable) {
			return new Base.BooleanType(false);
		}
	}
	
	// Step 3
	return new Base.BooleanType(!o.extensible);
};

/**
 * isFrozen() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectIsFrozenFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectIsFrozenFunc, Base.FunctionTypeBase);
ObjectIsFrozenFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		desc,
		p;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	for(p in o._properties) {
		desc = o.getOwnProperty(p);
		if ((Base.isDataDescriptor(desc) && desc.writable) || desc.configurable) {
			return new Base.BooleanType(false);
		}
	}
	
	// Step 3
	return new Base.BooleanType(!o.extensible);
};

/**
 * isExtensible() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectIsExtensibleFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectIsExtensibleFunc, Base.FunctionTypeBase);
ObjectIsExtensibleFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0];

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 2
	return new Base.BooleanType(o.extensible);
};

/**
 * keys() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ObjectKeysFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(ObjectKeysFunc, Base.FunctionTypeBase);
ObjectKeysFunc.prototype.call = function call(thisVal, args) {
	
	var o = args[0],
		array,
		index = 0,
		p;

	// Step 1
	if (Base.type(o) !== "Object") {
		throw new Exceptions.TypeError();
	}
	
	// Step 3
	array = new Base.ArrayType();
	
	// Step 5
	for(p in o._properties) {
		if (o._properties[p].enumerable) {
			array.defineOwnProperty(index, {
				value: new Base.StringType(p),
				writable: true,
				enumerable: true,
				configurable: true
			}, false);
			index++;
		}
	}
	
	// Step 6
	return array;
};

/**
 * Object constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2
 */
function ObjectConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
	
	this.put("getPrototypeOf", new ObjectGetPrototypeOfFunc(), false, true);
	this.put("getOwnPropertyDescriptor", new ObjectGetOwnPropertyDescriptorFunc(), false, true);
	this.put("getOwnPropertyNames", new ObjectGetOwnPropertyNamesFunc(), false, true);
	this.put("create", new ObjectCreateFunc(), false, true);
	this.put("defineProperty", new ObjectDefinePropertyFunc(), false, true);
	this.put("defineProperties", new ObjectDefinePropertiesFunc(), false, true);
	this.put("seal", new ObjectSealFunc(), false, true);
	this.put("freeze", new ObjectFreezeFunc(), false, true);
	this.put("preventExtensions", new ObjectPreventExtensionsFunc(), false, true);
	this.put("isSealed", new ObjectIsSealedFunc(), false, true);
	this.put("isFrozen", new ObjectIsFrozenFunc(), false, true);
	this.put("isExtensible", new ObjectIsExtensibleFunc(), false, true);
	this.put("keys", new ObjectKeysFunc(), false, true);
}
util.inherits(ObjectConstructor, Base.FunctionTypeBase);
ObjectConstructor.prototype.call = function call(thisVal, args) {
	
	var value = args[0];
	
	// Step 1
	if (!value || Base.isType(value, ["Null", "Undefined"])) {
		return new Base.ObjectType();
	}
	
	// Step 2
	return Base.toObject(value);
};
ObjectConstructor.prototype.construct = function call(args) {
	
	var value = args[0],
		obj;
	
	// Step 1
	if (value && !Base.isType(value, ["Undefined", "Null"])) {
		if (Base.type(value) === "Object") {
			return value;
		} else {
			return Base.toObject(value);
		}
	}
	
	// Steps 3-8
	return new Base.ObjectType();
};

// ******** Function Constructor ********

/**
 * Function constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function FunctionConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(FunctionConstructor, Base.FunctionTypeBase);
FunctionConstructor.prototype.call = function call(thisVal, args) {
	return FunctionConstructor.prototype.construct.call(this, args);
};
FunctionConstructor.prototype.construct = function call(args) {
	
	var argCount = args.length,
		p = "",
		parsedParameters,
		body,
		k = 1,
		i = 0,
		len;
	
	// Step 3
	if (argCount === 0) {
		body = new Base.StringType();

	// Step 4
	} else if (argCount === 1) {
		body = args[0];
		
	// Step 5
	} else if (argCount > 1) {
		p = Base.toString(args[0]).value;
		while (k < argCount - 1) {
			p += "," + Base.toString(args[k]).value;
			k++;
		}
		body = args[k];
	}
	
	// Step 6
	body = Base.toString(body).value;
	
	// Step 7
	p = AST.parseString("function temp(" + p + "){}");
	if (!p) {
		throw new Exceptions.SyntaxError();
	}
	p = p[1][0][2];
	
	// Step 8
	body = AST.parseString("function temp(){" + body + "}");
	if (!body) {
		throw new Exceptions.SyntaxError();
	}
	body = body[1][0][3];
	
	// Step 10
	return new Base.FunctionType(p, body, Runtime.getGlobalContext().lexicalEnvironment, 
		!!(body[0] && body[0][0].name === "directive" && [0][1] === "use strict"));
};

// ******** Array Constructor ********

/**
 * isArray() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function ArrayIsArrayFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(ArrayIsArrayFunc, Base.FunctionTypeBase);
ArrayIsArrayFunc.prototype.call = function call(thisVal, args) {
	
	var arg = args[0];
	
	// Steps 1 and 2
	return new Base.BooleanType(Base.type(arg) === "Object" && arg.className === "Array");
};

/**
 * Array constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function ArrayConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
	
	this.put("isArray", new ArrayIsArrayFunc(), false, true);
}
util.inherits(ArrayConstructor, Base.FunctionTypeBase);
ArrayConstructor.prototype.call = function call(thisVal, args) {
	return ArrayConstructor.prototype.construct.call(this, args);
};
ArrayConstructor.prototype.construct = function call(args) {
	
	var array = new Base.ArrayType(),
		len,
		i = 0;
	
	if (args.length === 1) {
		len = args[0];
		if (type(len) === "Number") {
			if (len.value === Base.toUint32(len).value) {
				array.put("length", Base.toUint32(len), true);
			} else {
				throw new Exceptions.RangeError();
			}
		} else {
			array.put("length", new Base.NumberType(1), true);
			array.put("0", len, true);
		}
	} else if (args.length > 1){
		len = args.length;
		array.put("length", new Base.NumberType(len), true);
		for(; i < len; i++) {
			array.put(i, args[i], true);
		}
	}
	
	return array;
};

// ******** String Constructor ********

/**
 * isArray() prototype method
 * 
 * @private
 * @see ECMA-262 Spec Chapter 15.2.3.2
 */
function StringFromCharCodeFunc(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(1), false, true);
}
util.inherits(StringFromCharCodeFunc, Base.FunctionTypeBase);
StringFromCharCodeFunc.prototype.call = function call(thisVal, args) {
	
	var i = 0,
		len = args.length;
	
	// Convert the array to something we can apply()
	for(; i < len; i++) {
		args[i] = Base.toUint16(args[i]).value;
	}
	
	// Use the built-in match method to perform the match
	return new Base.StringType(String.fromCharCode.apply(this, args));
};

/**
 * String constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function StringConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
	
	this.put("fromCharCode", new StringFromCharCodeFunc(), false, true);
}
util.inherits(StringConstructor, Base.FunctionTypeBase);
StringConstructor.prototype.call = function call(thisVal, args) {
	
	var value = args[0];
	
	if (!value) {
		return new Base.StringType();
	}
	return Base.toString(value);
};
StringConstructor.prototype.construct = function call(args) {
	
	var value = args[0],
		obj = new Base.ObjectType();
	
	obj.className = "String";
	obj.primitiveValue = value ? Base.toString(value).value : "";
	obj.objectPrototype = new Base.StringPrototypeType();
	
	return obj;
};

// ******** Boolean Constructor ********

/**
 * Boolean constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function BooleanConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(BooleanConstructor, Base.FunctionTypeBase);
BooleanConstructor.prototype.call = function call(thisVal, args) {
	return Base.toBoolean(args[0]);
};
BooleanConstructor.prototype.construct = function call(args) {
	
	var value = args[0],
		obj = new Base.ObjectType();
	
	obj.className = "Boolean";
	obj.primitiveValue = value ? Base.toBoolean(value).value : "";
	obj.objectPrototype = new Base.BooleanPrototypeType();
		
	return obj;
	
};

// ******** Number Constructor ********

/**
 * Number constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function NumberConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);

	this.put("MAX_VALUE", new Base.NumberType(Number.MAX_VALUE), false, true);
	this.put("MIN_VALUE", new Base.NumberType(Number.MIN_VALUE), false, true);
	this.put("NaN", new Base.NumberType(NaN), false, true);
	this.put("NEGATIVE_INFINITY", new Base.NumberType(Number.NEGATIVE_INFINITY), false, true);
	this.put("POSITIVE_INFINITY", new Base.NumberType(Number.POSITIVE_INFINITY), false, true);
}
util.inherits(NumberConstructor, Base.FunctionTypeBase);
NumberConstructor.prototype.call = function call(thisVal, args) {
	return Base.toNumber(args[0]);
};
NumberConstructor.prototype.construct = function call(args) {
	
	var value = args[0],
		obj = new Base.ObjectType();
	
	obj.className = "Number";
	obj.primitiveValue = value ? Base.toNumber(value).value : "";
	obj.objectPrototype = new Base.NumberPrototypeType();
		
	return obj;
};

// ******** RegExp Constructor ********

/**
 * RegExp constructor function
 * 
 * @private
 * @see ECMA-262 Spec Chapter 13.2
 */
function RegExpConstructor(className) {
	Base.ObjectType.call(this, className || "Function");
	this.put("length", new Base.NumberType(0), false, true);
}
util.inherits(RegExpConstructor, Base.FunctionTypeBase);
RegExpConstructor.prototype.call = function call(thisVal, args) {
	
	var pattern = args[0],
		flags = args[1];
	
	if (type(pattern) === "Object" && pattern.className === "RegExp") {
		return pattern;
	}
	
	return RegExpConstructor.prototype.construct(args);
};
RegExpConstructor.prototype.construct = function call(args) {
	
	var obj,
		pattern = args[0],
		flags = args[1],
		p,
		f;
	
	// Parse the parameters
	if (Base.type(pattern) === "Object" && pattern.className === "RegExp") {
		if (flags && Base.type(flags) !== "Undefined") {
			throw new Exceptions.TypeError();
		}
		p = pattern._pattern;
		f = pattern._flags;
	} else {
		p = pattern && Base.type(pattern) !== "Undefined" ? Base.toString(pattern).value : "";
		f = flags && Base.type(flags) !== "Undefined" ? Base.toString(flags).value : "";
	}
	
	// Create the regex object
	return new Base.RegExpType(p, f);
};

// ******** Date Type Class ********

{'fraction_non_alphanumeric': 0.16996503236366342, 'fraction_numerical': 0.016274830741760286, 'mean_word_length': 4.435749671418462, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 48, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '52642', 'n_tokens_mistral': 18742, 'n_tokens_neox': 17448, 'n_words': 4000}