package org.dynjs.runtime;
import org.dynjs.debugger.js.DebuggerAPI;
import org.dynjs.runtime.builtins.*;
import org.dynjs.runtime.builtins.Math;
import org.dynjs.runtime.builtins.types.*;
import org.dynjs.runtime.builtins.types.error.V8StackGetter;
import org.dynjs.runtime.java.JSAdapter;
import org.dynjs.runtime.java.JavaPackage;
import java.util.ArrayList;
import java.util.List;
public class GlobalContext {
public static GlobalContext newGlobalContext(DynJS runtime) {
return new GlobalContext( runtime );
}
public static GlobalContext newGlobalContext(DynJS runtime, JSObject object) {
return new GlobalContext( runtime, object );
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
private final DynJS runtime;
private List<AbstractBuiltinType> builtinTypes = new ArrayList<>();
private JSObject objectPrototype;
private final JSObject object;
public GlobalContext(DynJS runtime) {
this( runtime, new DynObject() );
}
public GlobalContext(DynJS runtime, JSObject object) {
this.object = object;
this.runtime = runtime;
initialize();
}
private void initialize() {
defineReadOnlyGlobalProperty("__throwTypeError", new ThrowTypeError(this), false);
// ----------------------------------------
// Built-in types
// ----------------------------------------
registerBuiltinType("Object", new BuiltinObject(this));
this.objectPrototype = getPrototypeFor("Object");
this.object.setPrototype(this.objectPrototype);
registerBuiltinType("Function", new BuiltinFunction(this));
registerBuiltinType("Boolean", new BuiltinBoolean(this));
registerBuiltinType("Number", new BuiltinNumber(this));
registerBuiltinType("Array", new BuiltinArray(this));
registerBuiltinType("String", new BuiltinString(this));
registerBuiltinType("RegExp", new BuiltinRegExp(this));
registerBuiltinType("Date", new BuiltinDate(this));
registerBuiltinType("Error", new BuiltinError(this));
registerBuiltinType("ReferenceError", new BuiltinReferenceError(this));
registerBuiltinType("RangeError", new BuiltinRangeError(this));
registerBuiltinType("SyntaxError", new BuiltinSyntaxError(this));
registerBuiltinType("TypeError", new BuiltinTypeError(this));
registerBuiltinType("URIError", new BuiltinURIError(this));
registerBuiltinType("EvalError", new BuiltinEvalError(this));
if (this.runtime.getConfig().isRhinoCompatible()) {
registerBuiltinType("JSAdapter", new JSAdapter(this));
}
if(this.runtime.getConfig().isV8Compatible()) {
defineNonEnumerableProperty(this, "__v8StackGetter", new V8StackGetter(this));
}
initializeBuiltinTypes();
// ----------------------------------------
// Built-in global functions
// ----------------------------------------
defineReadOnlyGlobalProperty("undefined", Types.UNDEFINED, false);
defineGlobalProperty("parseFloat", new ParseFloat(this), true);
defineGlobalProperty("parseInt", new ParseInt(this), true);
defineGlobalProperty("eval", new Eval(this), true);
defineGlobalProperty("isNaN", new IsNaN(this), true);
defineGlobalProperty("isFinite", new IsFinite(this), true);
defineGlobalProperty("encodeURI", new EncodeUri(this), true);
defineGlobalProperty("decodeURI", new DecodeUri(this), true);
defineGlobalProperty("encodeURIComponent", new EncodeUriComponent(this), true);
defineGlobalProperty("decodeURIComponent", new DecodeUriComponent(this), true);
if (this.runtime.getConfig().isCommonJSCompatible()) {
defineGlobalProperty("require", new Require(this), true);
}
defineGlobalProperty("include", new Include(this), true);
defineGlobalProperty("load", new Include(this), true); // hackety hack
defineGlobalProperty("escape", new Escape(this), true);
defineGlobalProperty("unescape", new Unescape(this), true);
defineGlobalProperty("print", new Print(this), true);
defineReadOnlyGlobalProperty("dynjs", new DynJSBuiltin(this.runtime), false);
// ----------------------------------------
// Built-in global objects
// ----------------------------------------
this.object.put(null, "JSON", new JSON(this), false);
defineGlobalProperty("Math", new Math(this), true);
defineGlobalProperty("Intl", new Intl(this), true);
// ----------------------------------------
// Java integration
// ----------------------------------------
defineGlobalProperty("Packages", new JavaPackage(this, null), true );
defineGlobalProperty("java", new JavaPackage(this, "java"), true);
defineGlobalProperty("javax", new JavaPackage(this, "javax"), true);
defineGlobalProperty("org", new JavaPackage(this, "org"), true);
defineGlobalProperty("com", new JavaPackage(this, "com"), true);
defineGlobalProperty("io", new JavaPackage(this, "io"), true);
defineGlobalProperty("System", System.class, true);
}
private void registerBuiltinType(String name, final AbstractBuiltinType type) {
this.object.defineOwnProperty(null, name, PropertyDescriptor.newDataPropertyDescriptor(type, true, true, true), false);
this.object.defineOwnProperty(null, "__Builtin_" + name, PropertyDescriptor.newDataPropertyDescriptor(type, true, true, false), false);
this.builtinTypes.add(type);
}
private void defineGlobalProperty(final String name, final Object value) {
this.object.defineOwnProperty(null, name, PropertyDescriptor.newDataPropertyDescriptor(value, true, true, true), false);
}
private void defineGlobalProperty(final String name, final Object value, boolean enumerable) {
this.object.defineOwnProperty(null, name, PropertyDescriptor.newDataPropertyDescriptor(value, true, true, enumerable), false);
}
private void defineReadOnlyGlobalProperty(final String name, final Object value, boolean enumerable) {
this.object.defineOwnProperty(null, name, PropertyDescriptor.newDataPropertyDescriptor(value, false, false, enumerable), false);
}
public void defineNonEnumerableProperty(final GlobalContext globalContext, String name, final Object value) {
this.object.defineOwnProperty(null, name, PropertyDescriptor.newDataPropertyDescriptor(value, true, true, false), false);
}
private void initializeBuiltinTypes() {
for (AbstractBuiltinType each : this.builtinTypes) {
each.setPrototype(getPrototypeFor("Function"));
each.initialize(this);
}
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
public JSObject getObject() {
return this.object;
}
public JSObject getObjectPrototype() {
return this.objectPrototype;
}
public DynJS getRuntime() {
return this.runtime;
}
public JSObject getPrototypeFor(String type) {
Object typeObj = this.object.get(null, type);
if (typeObj == Types.UNDEFINED) {
return null;
}
Object prototype = ((JSObject) typeObj).get(null, "prototype");
if (prototype == Types.UNDEFINED) {
return null;
}
return (JSObject) prototype;
}
public JSFunction getThrowTypeError() {
return (JSFunction) this.object.get( null, "__throwTypeError" );
}
public JSFunction getType(String name) {
return (JSFunction) this.object.get( null, name );
}
}