Skip to content

Instantly share code, notes, and snippets.

@kg
Created July 8, 2011 19:15
Show Gist options
  • Save kg/1072575 to your computer and use it in GitHub Desktop.
Save kg/1072575 to your computer and use it in GitHub Desktop.
JSIL.Core
"use strict";
if (typeof (JSIL) !== "undefined")
throw new Error("JSIL.Core included twice");
var JSIL = {
__FullName__ : "JSIL"
};
// Safari does not provide Function.prototype.bind, and we need it.
if (typeof (Function.prototype.bind) !== "function") {
// Implementation from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
Function.prototype.bind = function( obj ) {
var slice = [].slice,
args = slice.call(arguments, 1),
self = this,
nop = function () {},
bound = function () {
return self.apply( this instanceof nop ? this : ( obj || {} ),
args.concat( slice.call(arguments) ) );
};
nop.prototype = self.prototype;
bound.prototype = new nop();
return bound;
};
}
JSIL.GlobalNamespace = this;
JSIL.PrivateNamespaces = {};
var $private = null;
JSIL.DeclareAssembly = function (assemblyName) {
var existing = JSIL.PrivateNamespaces[assemblyName];
if (typeof (existing) !== "undefined")
return $private = existing;
// Create a new private global namespace for the new assembly
var result = Object.create(JSIL.GlobalNamespace);
try {
Object.defineProperty(result, "toString", {
configurable: true,
enumerable: true,
value: function () {
return assemblyName;
}
});
} catch (e) {
}
return JSIL.PrivateNamespaces[assemblyName] = $private = result;
};
var $jsilcore = JSIL.DeclareAssembly("JSIL.Core");
$jsilcore.nextTypeId = 0;
JSIL.EscapeName = function (name) {
return name.replace("`", "$b").replace(".", "_").replace("<", "$l").replace(">", "$g");
};
JSIL.SplitRegex = new RegExp("[\.\/\+]");
JSIL.GetParentName = function (name) {
var parts = JSIL.SplitName(name);
return name.substr(0, name.length - (parts[parts.length - 1].length + 1));
};
JSIL.GetLocalName = function (name) {
var parts = JSIL.SplitName(name);
return parts[parts.length - 1];
};
JSIL.SplitName = function (name) {
if (typeof (name) !== "string")
JSIL.Host.error(new Error("Not a name: " + name));
return name.split(JSIL.SplitRegex);
};
JSIL.ResolvedName = function (parent, parentName, key, localName) {
this.parent = parent;
this.parentName = parentName;
this.key = key;
this.localName = localName;
}
JSIL.ResolvedName.prototype.exists = function () {
return typeof(this.parent[this.key]) !== "undefined";
}
JSIL.ResolvedName.prototype.get = function () {
return this.parent[this.key];
}
JSIL.ResolvedName.prototype.del = function () {
try {
delete this.parent[this.key];
} catch (e) {
}
}
JSIL.ResolvedName.prototype.set = function (value) {
this.parent[this.key] = value;
}
JSIL.ResolvedName.prototype.define = function (declaration) {
Object.defineProperty(this.parent, this.key, declaration);
}
JSIL.ResolveName = function (root, name) {
var parts = JSIL.SplitName(name);
var current = root;
if (typeof (root) === "undefined")
throw new Error("Invalid search root");
for (var i = 0, l = parts.length - 1; i < l; i++) {
var key = JSIL.EscapeName(parts[i]);
var next = current[key];
if (typeof (next) === "undefined") {
var namespaceName;
if (current === JSIL.GlobalNamespace)
namespaceName = "<global>";
else {
try {
namespaceName = current.toString();
} catch (e) {
namespaceName = "<unknown>";
}
}
throw new Error("Could not find the name '" + key + "' in the namespace '" + namespaceName + "'.");
}
current = next;
}
var localName = parts[parts.length - 1];
return new JSIL.ResolvedName(
current, name.substr(0, name.length - (localName.length + 1)),
JSIL.EscapeName(localName), localName
);
};
JSIL.DeclareNamespace = function (name, sealed) {
if (typeof (sealed) === "undefined")
sealed = true;
var resolved = JSIL.ResolveName(JSIL.GlobalNamespace, name);
if (!resolved.exists())
resolved.define({
enumerable: true,
configurable: !sealed,
value: {
__FullName__: name,
toString: function () {
return name;
}
}
});
var resolved = JSIL.ResolveName($private, name);
if (!resolved.exists())
resolved.define({
enumerable: true,
configurable: !sealed,
value: {
__FullName__: name,
toString: function () {
return name;
}
}
});
}
JSIL.DeclareNamespace("System");
JSIL.DeclareNamespace("System.Collections");
JSIL.DeclareNamespace("System.Collections.Generic");
JSIL.DeclareNamespace("System.Array", false);
JSIL.DeclareNamespace("System.Delegate", false);
JSIL.DeclareNamespace("System.Enum", false);
JSIL.DeclareNamespace("System.MulticastDelegate", false);
JSIL.DeclareNamespace("System.Console", false);
JSIL.DeclareNamespace("System.Text");
JSIL.DeclareNamespace("System.Threading");
JSIL.DeclareNamespace("System.Threading.Interlocked", false);
JSIL.DeclareNamespace("System.Threading.Monitor", false);
JSIL.DeclareNamespace("System.Globalization", false);
JSIL.DeclareNamespace("System.Environment", false);
JSIL.DeclareNamespace("System.Runtime", false);
JSIL.DeclareNamespace("System.Runtime.InteropServices", false);
JSIL.DeclareNamespace("JSIL.Array");
JSIL.DeclareNamespace("JSIL.Delegate");
JSIL.DeclareNamespace("JSIL.Dynamic");
JSIL.DeclareNamespace("JSIL.MulticastDelegate");
// Hack
JSIL.DeclareNamespace("Property");
// You can change these fields, but you shouldn't need to in practice
JSIL.DeclareNamespace("JSIL.HostType", false);
JSIL.HostType.IsBrowser = (typeof (window) !== "undefined") && (typeof (navigator) !== "undefined");
// Redefine this class at runtime or override its members to change the behavior of JSIL builtins.
JSIL.DeclareNamespace("JSIL.Host", false);
JSIL.Host.getCanvas = function () {
throw new Error("No canvas implementation");
};
JSIL.Host.logWrite = function (text) {
if (typeof (console) !== "undefined")
Function.prototype.apply.call(console.log, console, arguments);
else if (JSIL.HostType.IsBrowser)
window.alert(text);
else
putstr(text);
};
JSIL.Host.logWriteLine = function (text) {
if (typeof (console) !== "undefined")
Function.prototype.apply.call(console.log, console, arguments);
else if (JSIL.HostType.IsBrowser)
window.alert(text);
else
print(text);
};
JSIL.Host.warning = function (text) {
if (typeof (console) !== "undefined")
Function.prototype.apply.call(console.warn, console, arguments);
else
JSIL.Host.logWriteLine(Array.prototype.join.call(arguments, ""));
};
JSIL.Host.error = function (exception, text) {
var rest = Array.prototype.slice.call(arguments, 1);
rest.push(exception);
var stack = null;
try {
stack = exception.stack;
} catch (e) {
stack = null;
}
if ((typeof (stack) !== "undefined") && (stack !== null)) {
if (stack.indexOf(String(exception)) >= 0)
rest.pop();
rest.push(stack);
}
if (typeof (console) !== "undefined") {
Function.prototype.apply.call(console.error, console, rest);
}
JSIL.Host.throwException(exception);
}
JSIL.Host.throwException = function (e) {
throw e;
};
JSIL.Host.warnedAboutRunLater = false;
JSIL.Host.pendingRunLaterItems = [];
JSIL.Host.runLaterCallback = function () {
var items = JSIL.Host.pendingRunLaterItems;
while (items.length > 0) {
var item = items.shift();
item();
}
}
// This can fail to run the specified action if the host hasn't implemented it, so you should
// only use this to run performance improvements, not things you depend on
JSIL.Host.runLater = function (action) {
if (typeof (setTimeout) === "function") {
var needEnqueue = JSIL.Host.pendingRunLaterItems.length <= 0;
JSIL.Host.pendingRunLaterItems.push(action);
if (needEnqueue)
setTimeout(JSIL.Host.runLaterCallback, 0);
}
};
JSIL.UntranslatableNode = function (nodeType) {
JSIL.Host.error(new Error("An ILAst node of type " + nodeType + " could not be translated."));
};
JSIL.UntranslatableFunction = function (functionName) {
return function () {
JSIL.Host.error(new Error("The function '" + functionName + "' could not be translated."));
};
};
JSIL.UntranslatableInstruction = function (instruction, operand) {
if (typeof (operand) !== "undefined")
JSIL.Host.error(new Error("A MSIL instruction of type " + instruction + " with an operand of type " + operand + " could not be translated."));
else
JSIL.Host.error(new Error("A MSIL instruction of type " + instruction + " could not be translated."));
};
JSIL.IgnoredMember = function (memberName) {
JSIL.Host.error(new Error("An attempt was made to reference the member '" + memberName + "', but it was explicitly ignored during translation."));
};
JSIL.MakeExternalMemberStub = function (namespaceName, memberName, inheritedMember) {
var state = {
alreadyWarned: false
};
var result;
if (typeof (inheritedMember) === "function") {
result = function () {
if (!state.alreadyWarned) {
JSIL.Host.warning("The external method '" + memberName + "' of type '" + namespaceName + "' has not been implemented; calling inherited method.");
state.alreadyWarned = true;
}
return Function.prototype.apply.call(inheritedMember, this, arguments);
};
} else {
result = function () {
JSIL.Host.error(new Error("The external method '" + memberName + "' of type '" + namespaceName + "' has not been implemented."));
};
}
result.__IsPlaceholder__ = true;
return result;
}
JSIL.ExternalMembers = function (namespace/*, ...memberNames */) {
if (typeof (namespace) === "undefined") {
JSIL.Host.error(new Error("External members declared in undefined namespace"));
return;
}
var namespaceName = JSIL.GetTypeName(namespace);
for (var i = 1, l = arguments.length; i < l; i++) {
var memberName = arguments[i];
var memberValue = namespace[memberName];
if (!namespace.hasOwnProperty(memberName)) {
Object.defineProperty(
namespace, memberName, {
enumerable: true,
configurable: true,
value: JSIL.MakeExternalMemberStub(namespaceName, memberName, memberValue)
}
);
}
}
}
JSIL.QueueTypeInitializer = function (type, initializer) {
if (type.__TypeInitialized__) {
initializer(type);
} else {
type.__Initializers__.push(initializer);
}
};
JSIL.Initialize = function () {
// Seal all registered names so that their static constructors run on use
var arn = JSIL.AllRegisteredNames;
for (var i = 0, l = arn.length; i < l; i++)
arn[i].sealed = true;
};
JSIL.GenericParameter = function (name) {
this.name = name;
};
JSIL.GenericParameter.prototype.get = function (context) {
return context[this.name];
};
JSIL.GenericParameter.prototype.toString = function () {
return "<Generic Parameter " + this.name + ">";
};
JSIL.TypeRef = function (context, name, genericArguments) {
if (arguments.length === 1) {
this.context = null;
this.typeName = null;
this.genericArguments = null;
this.cachedReference = arguments[0];
} else {
if (typeof (name) === "string") {
this.context = context;
this.typeName = name;
this.genericArguments = genericArguments || [];
this.cachedReference = null;
} else {
JSIL.Host.error(new Error("Invalid type reference"), context, name);
}
}
};
JSIL.TypeRef.prototype.toString = function () {
if (this.typeName === null)
return JSIL.GetTypeName(this.cachedReference);
else
return "<TypeRef " + this.typeName + ">";
};
JSIL.TypeRef.prototype.get = function () {
if (this.cachedReference !== null)
return this.cachedReference;
var result = JSIL.ResolveName(this.context, this.typeName);
if (!result.exists())
throw new Error("The name '" + this.typeName + "' does not exist.");
this.cachedReference = result.get();
if (this.genericArguments.length > 0) {
var ga = this.genericArguments;
for (var i = 0, l = ga.length; i < l; i++) {
var arg = ga[i];
if (typeof (arg) === "string")
ga[i] = arg = new JSIL.TypeRef(this.context, arg).get();
}
this.cachedReference = this.cachedReference.Of.apply(this.cachedReference, ga);
}
return this.cachedReference;
};
JSIL.New = function (type, constructorName, args) {
if (type.__IsNativeType__ || false) {
var ctor = type.prototype[constructorName];
return ctor.apply(null, args);
} else {
var proto = type.prototype;
var result = Object.create(proto);
}
if ((type.__TypeInitialized__ || false) === false)
JSIL.InitializeType(type);
JSIL.InitializeStructFields(result, type);
if (!type.__IsReferenceType__ && (args.length == 0)) {
} else {
var ctor = proto[constructorName];
ctor.apply(result, args);
}
return result;
}
JSIL.CloneObject = function (obj) {
if ((typeof (obj) === "undefined") || (obj === null))
throw new Error("Cloning a non-object");
return Object.create(obj);
};
JSIL.AllRegisteredNames = [];
JSIL.RegisterName = function (name, privateNamespace, isPublic, creator, initializer) {
var privateName = JSIL.ResolveName(privateNamespace, name);
if (isPublic)
var publicName = JSIL.ResolveName(JSIL.GlobalNamespace, name);
var localName = privateName.localName;
if (privateName.exists()) {
JSIL.DuplicateDefinitionWarning(name);
return;
}
var state = {
creator: creator,
initializer: initializer,
sealed: false
};
JSIL.AllRegisteredNames.push(state);
var getter = function () {
var result;
if (typeof (state.creator) === "function") {
var cf = state.creator;
delete state.creator;
state.value = result = cf();
} else {
result = state.value;
}
if (typeof (state.initializer) === "function") {
var ifn = state.initializer;
delete state.initializer;
ifn(result);
}
if (state.sealed) {
state.sealed = false;
JSIL.InitializeType(result);
JSIL.Host.runLater(function () {
privateName.del();
privateName.set(result);
if (isPublic) {
publicName.del();
publicName.set(result);
}
});
}
return result;
};
var decl = {
enumerable: true,
configurable: true,
get: getter
};
privateName.define(decl);
if (isPublic)
publicName.define(decl);
};
JSIL.MakeProto = function (baseType, target, typeName, isReferenceType) {
if (typeof (baseType) === "undefined") {
throw new Error("The base type of '" + typeName + "' is not defined");
} else if (typeof (baseType) === "string") {
baseType = new JSIL.TypeRef($private, baseType);
} else if (Object.getPrototypeOf(baseType) !== JSIL.TypeRef.prototype) {
baseType = new JSIL.TypeRef(baseType);
}
var baseTypeInstance = null;
try {
// If we call .Of on the base type before it's got all its static members defined, the resulting
// closed type will be missing static members.
var ga = baseType.genericArguments || [];
if (ga.length == 0)
baseTypeInstance = baseType.get();
} catch (e) {
baseTypeInstance = null;
}
if (baseTypeInstance === null) {
var prototype = {};
prototype.__DeferredBaseType__ = baseType;
} else {
var prototype = JSIL.CloneObject(baseTypeInstance.prototype);
prototype.__BaseType__ = baseTypeInstance;
}
prototype.__ShortName__ = JSIL.GetLocalName(typeName);
prototype.__FullName__ = typeName;
prototype.__IsReferenceType__ = Boolean(isReferenceType);
return prototype;
};
JSIL.MakeProperty = function (parent, name, getter, setter) {
var descriptor = {
configurable: true,
enumerable: true
};
if (typeof (getter) === "function")
descriptor["get"] = getter;
if (typeof (setter) === "function")
descriptor["set"] = setter;
Object.defineProperty(parent, name, descriptor);
};
JSIL.MakeGenericProperty = function (parent, name, getter, setter) {
var props;
if (parent.hasOwnProperty("__GenericProperties__")) {
props = parent.__GenericProperties__;
} else {
props = parent.__GenericProperties__ = [];
}
props.push([name, getter, setter]);
};
JSIL.MakeNumericType = function (baseType, typeName, isIntegral) {
JSIL.MakeType(baseType, typeName, false, true);
var resolved = JSIL.ResolveName(JSIL.GlobalNamespace, typeName);
resolved.get().__IsNumeric__ = true;
resolved.get().prototype.__IsNumeric__ = true;
resolved.get().__IsIntegral__ = isIntegral;
resolved.get().prototype.__IsIntegral__ = isIntegral;
};
JSIL.MakeIndirectProperty = function (target, key, source) {
var getter = function () {
return source[key];
};
var setter = function (value) {
// Remove the indirect property
delete target[key];
// Set on result instead of self so that the value is unique to this specialized type instance
target[key] = value;
};
Object.defineProperty(target, key, {
configurable: true,
enumerable: true,
get: getter,
set: setter
});
}
JSIL.TypeObjectPrototype = {};
JSIL.TypeObjectPrototype.__GenericArguments__ = [];
JSIL.TypeObjectPrototype.toString = function () {
return JSIL.GetTypeName(this);
};
JSIL.TypeObjectPrototype.Of = function () {
// This whole function would be 100x simpler if you could provide a prototype when constructing a function. Javascript sucks so much.
var self = this;
var ga = this.__GenericArguments__;
var ofCache = this.__OfCache__;
var cacheKey = arguments[0].__TypeId__;
for (var i = 1, l = arguments.length; i < l; i++)
cacheKey += "," + arguments[i].__TypeId__;
if ((typeof (ofCache) === "undefined") || (ofCache === null))
this.__OfCache__ = ofCache = [];
if (arguments.length != ga.length)
throw new Error("Invalid number of generic arguments for type '" + JSIL.GetTypeName(this) + "' (got " + arguments.length + ", expected " + ga.length + ")");
// If we do not return the same exact closed type instance from every call to Of(...), derivation checks will fail
var result = ofCache[cacheKey] || null;
if (result !== null)
return result;
result = function () {
var ctorArguments = Array.prototype.slice.call(arguments);
return Function.prototype.apply.call(self, this, ctorArguments);
};
// Prevents recursion when Of is called indirectly during initialization of the new closed type
ofCache[cacheKey] = result;
var ignoredNames = [
"__Self__", "__TypeInitialized__", "__IsClosed__",
"prototype", "Of", "toString", "__FullName__"
];
for (var k in this) {
if (ignoredNames.indexOf(k) !== -1)
continue;
JSIL.MakeIndirectProperty(result, k, self);
}
var fullName = this.__FullName__ + "<" + Array.prototype.join.call(arguments, ", ") + ">";
result.__TypeId__ = ++$jsilcore.nextTypeId;
result.__FullName__ = fullName;
result.toString = function () {
return fullName;
};
result.__Self__ = result;
result.__IsClosed__ = true;
result.prototype = Object.create(this.prototype);
// This is important: It's possible for recursion to cause the initializer to run while we're defining properties.
// We prevent this from happening by forcing the initialized state to true.
result.__TypeInitialized__ = true;
for (var i = 0, l = arguments.length; i < l; i++) {
var key = ga[i];
var decl = {
configurable: false,
enumerable: true,
value: arguments[i]
};
Object.defineProperty(result, key, decl);
Object.defineProperty(result.prototype, key, decl);
}
JSIL.InstantiateGenericProperties(result);
// Force the initialized state back to false and, if the outer type is initialized, initialize the inner type.
result.__TypeInitialized__ = false;
if (this.__TypeInitialized__)
JSIL.InitializeType(result);
return result;
};
JSIL.InstantiateGenericProperties = function (obj) {
var target = obj;
while (obj !== null) {
var gps = obj.__GenericProperties__ || [];
for (var i = 0, l = gps.length; i < l; i++) {
var gp = gps[i];
JSIL.MakeProperty(target, gp[0], gp[1], gp[2]);
}
obj = Object.getPrototypeOf(obj);
}
}
System.RuntimeType = Object.create(JSIL.TypeObjectPrototype);
System.RuntimeType.prototype = {}; // Fixes mscorlib translation generating members for RuntimeType
System.RuntimeType.__IsReferenceType__ = true;
System.RuntimeType.IsInterface = false;
System.RuntimeType.IsEnum = false;
System.RuntimeType.__TypeInitialized__ = false;
System.RuntimeType.__LockCount__ = 0;
System.RuntimeType.__FullName__ = null;
System.RuntimeType.__ShortName__ = null;
JSIL.InitializeStructFields = function (instance, typeObject) {
var sf = instance.__StructFields__;
if ((typeof (sf) !== "object") || (sf.length <= 0))
return;
for (var i = 0, l = sf.length; i < l; i++) {
var fieldName = sf[i][0];
var fieldType = sf[i][1];
if (typeof (fieldType) === "function") {
instance[fieldName] = new fieldType();
}
}
};
JSIL.CopyObjectValues = function (source, target) {
for (var k in source) {
if (!source.hasOwnProperty(k))
continue;
target[k] = source[k];
}
}
JSIL.CopyMembers = function (source, target) {
var sf = source.__StructFields__;
if (typeof (sf) != "object")
sf = [];
for (var key in source) {
if (!source.hasOwnProperty(key))
continue;
target[key] = source[key];
}
for (var i = 0, l = sf.length; i < l; i++) {
var fieldName = sf[i][0];
var value;
if (
source.hasOwnProperty(fieldName) &&
typeof ((value = target[fieldName]).MemberwiseClone) === "function"
) {
target[fieldName] = value.MemberwiseClone();
}
}
}
JSIL.InitializeType = function (type) {
if (typeof (type) === "undefined")
throw new Error("Type is null");
if (type.__TypeInitialized__ || false)
return;
// Not entirely correct, but prevents recursive type initialization
type.__TypeInitialized__ = true;
if (
(typeof (type.prototype) !== "undefined") &&
(typeof (type.prototype.__DeferredBaseType__) !== "undefined")
) {
// The type was defined before its base class existed, so as a result, its prototype does
// not actually derive from the base class's prototype. We must simulate derivation by copying
// any missing members.
var baseRef = type.prototype.__DeferredBaseType__;
var baseType = baseRef.get();
type.prototype.__BaseType__ = baseType;
JSIL.InitializeType(baseType);
var src = baseType.prototype;
var indirectKeys = [];
// Scan through the original prototype chain to build a list of keys we need to transplant
// onto the new prototype object.
while (src !== null) {
for (var k in src) {
if (!src.hasOwnProperty(k))
continue;
else if (indirectKeys.indexOf(k) !== -1)
continue;
indirectKeys.push(k);
}
src = Object.getPrototypeOf(src);
}
// Make indirect copies of all the keys from the original prototype chain.
// These copies will hold the same value as the original prototype until assigned new values.
for (var i = 0, l = indirectKeys.length; i < l; i++) {
var k = indirectKeys[i];
// If the prototype has a member of this name already, we shouldn't replace it with an indirect copy.
// Note that hasOwnProperty isn't enough here. Not entirely sure why.
if (
type.prototype.hasOwnProperty(k) ||
(typeof (type.prototype[k]) !== "undefined")
) {
continue;
}
JSIL.MakeIndirectProperty(type.prototype, k, baseType.prototype);
}
// JSIL.Host.logWriteLine("Warning: Replacing prototype of type '" + JSIL.GetTypeName(type) + "'");
}
var ti = type.__Initializers__ || [];
while (ti.length > 0) {
var initializer = ti.unshift();
if (typeof (initializer) === "function")
initializer(type);
};
if (type.__IsClosed__) {
if (typeof (type._cctor) == "function") {
try {
type._cctor();
} catch (e) {
JSIL.Host.error(e, "Unhandled exception in static constructor for type " + JSIL.GetTypeName(type));
}
}
if (typeof (type._cctor2) == "function") {
try {
type._cctor2();
} catch (e) {
JSIL.Host.error(e, "Unhandled exception in static constructor for type " + JSIL.GetTypeName(type));
}
}
}
if (
(typeof (type.prototype) !== "undefined") &&
(typeof (type.prototype.__BaseType__) !== "undefined")
) {
JSIL.InitializeType(type.prototype.__BaseType__);
}
if (typeof (type.__OfCache__) !== "undefined") {
var oc = type.__OfCache__;
for (var k in oc) {
if (!oc.hasOwnProperty(k))
continue;
JSIL.InitializeType(oc[k]);
}
}
};
JSIL.ShadowedTypeWarning = function (fullName) {
// JSIL.Host.warning("Type ", fullName, " is shadowed by another type of the same name.");
};
JSIL.DuplicateDefinitionWarning = function (fullName) {
// JSIL.Host.warning("Type ", fullName, " is defined multiple times.");
};
JSIL.MakeStaticClass = function (fullName, isPublic, genericArguments, initializer) {
if (typeof (isPublic) === "undefined")
JSIL.Host.error(new Error("Must specify isPublic"));
var resolved = JSIL.ResolveName($private, fullName);
var localName = resolved.localName;
if (resolved.exists()) {
JSIL.DuplicateDefinitionWarning(fullName);
return;
}
var typeObject = JSIL.CloneObject(System.RuntimeType);
typeObject.GetType = function () {
return typeObject;
};
typeObject.FullName = typeObject.__FullName__ = fullName;
typeObject.__TypeId__ = ++$jsilcore.nextTypeId;
typeObject.__ShortName__ = localName;
typeObject.__IsStatic__ = true;
typeObject.__Initializers__ = [];
typeObject.__TypeInitialized__ = false;
typeObject.__GenericArguments__ = genericArguments || [];
if (typeObject.__GenericArguments__.length > 0) {
typeObject.Of = JSIL.TypeObjectPrototype.Of.bind(typeObject);
typeObject.__IsClosed__ = false;
} else {
typeObject.__IsClosed__ = true;
}
JSIL.RegisterName(fullName, $private, isPublic, function () { return typeObject; }, initializer);
}
JSIL.MakeType = function (baseType, fullName, isReferenceType, isPublic, genericArguments, initializer) {
if (typeof (isPublic) === "undefined")
JSIL.Host.error(new Error("Must specify isPublic"));
var resolved = JSIL.ResolveName($private, fullName);
var localName = resolved.localName;
if (resolved.exists()) {
JSIL.DuplicateDefinitionWarning(fullName);
return;
}
var typeObject = function () {
if ((typeObject.__TypeInitialized__ || false) === false)
JSIL.InitializeType(typeObject);
JSIL.InitializeStructFields(this, typeObject);
var args = arguments;
if (args === null)
args = [];
if (!typeObject.__IsReferenceType__ && (args.length == 0))
return;
if (typeof (this._ctor) != "undefined")
this._ctor.apply(this, args);
};
typeObject.__TypeId__ = ++$jsilcore.nextTypeId;
typeObject.__IsArray__ = false;
typeObject.__Initializers__ = [];
typeObject.__TypeInitialized__ = false;
typeObject.__IsNativeType__ = false;
typeObject.__IsReferenceType__ = isReferenceType;
typeObject.__Context__ = $private;
typeObject.__Self__ = typeObject;
typeObject.FullName = typeObject.__FullName__ = fullName;
typeObject.__ShortName__ = localName;
typeObject.__LockCount__ = 0;
typeObject.__GenericArguments__ = genericArguments || [];
if (typeObject.__GenericArguments__.length > 0) {
typeObject.Of = JSIL.TypeObjectPrototype.Of.bind(typeObject);
typeObject.__IsClosed__ = false;
} else {
typeObject.__IsClosed__ = true;
}
typeObject.toString = function () {
return fullName;
};
typeObject.prototype = JSIL.MakeProto(baseType, typeObject, fullName, false);
typeObject.prototype.__ShortName__ = localName;
typeObject.prototype.__Interfaces__ = [];
typeObject.prototype.GetType = function () {
return typeObject;
};
JSIL.RegisterName(fullName, $private, isPublic, function () { return typeObject; }, initializer);
};
JSIL.MakeClass = function (baseType, fullName, isPublic, genericArguments, initializer) {
JSIL.MakeType(baseType, fullName, true, isPublic, genericArguments, initializer);
};
JSIL.MakeStruct = function (fullName, isPublic, genericArguments, initializer) {
JSIL.MakeType("System.ValueType", fullName, false, isPublic, genericArguments, initializer);
};
JSIL.MakeInterface = function (fullName, genericArguments, members) {
var resolved = JSIL.ResolveName($private, fullName);
var localName = resolved.localName;
if (resolved.exists()) {
JSIL.DuplicateDefinitionWarning(fullName);
return;
}
var typeObject = function() {
throw new Error("Cannot construct an instance of an interface");
};
typeObject.__TypeId__ = ++$jsilcore.nextTypeId;
typeObject.__Members__ = members;
typeObject.__ShortName__ = localName;
typeObject.FullName = typeObject.__FullName__ = fullName;
typeObject.__GenericArguments__ = genericArguments || [];
typeObject.IsInterface = true;
typeObject.Of = function () {
return typeObject;
};
typeObject.prototype = JSIL.CloneObject(JSIL.Interface.prototype);
resolved.set(typeObject);
resolved = JSIL.ResolveName(JSIL.GlobalNamespace, fullName);
if (!resolved.exists()) {
resolved.set(typeObject);
} else {
JSIL.ShadowedTypeWarning(fullName);
}
};
JSIL.MakeEnumValue = function (enumType, value, key) {
var obj = new Number(value);
if (key !== null)
obj.toString = function () {
return key;
};
else
obj.toString = function () {
return value.toString();
}
obj.GetType = function () {
return enumType;
};
obj.value = value;
obj.name = key;
return obj;
}
JSIL.MakeEnum = function (fullName, members, isFlagsEnum) {
var resolved = JSIL.ResolveName($private, fullName);
var localName = resolved.localName;
if (resolved.exists()) {
JSIL.DuplicateDefinitionWarning(fullName);
return;
}
var enumType = System.Enum;
var prototype = JSIL.CloneObject(enumType.prototype);
prototype.__BaseType__ = enumType;
prototype.__ShortName__ = localName;
prototype.__FullName__ = fullName;
var result = {
prototype: prototype,
__BaseType__: enumType,
__FullName__: fullName,
FullName: fullName,
Name: localName,
IsEnum: true,
__TypeId__: ++$jsilcore.nextTypeId,
__IsFlagsEnum__: isFlagsEnum,
__ValueToName__: {}
};
result.Of = function () {
return result;
}
result.CheckType = function (v) {
if (typeof (v.GetType) === "function")
if (v.GetType() === result)
return true;
return false;
};
for (var key in members) {
if (!members.hasOwnProperty(key))
continue;
var value = Math.floor(members[key]);
result.__ValueToName__[value] = key;
result[key] = JSIL.MakeEnumValue(result, value, key);
}
var decl = {
configurable: true,
enumerable: true,
value: result
};
resolved.define(decl);
resolved = JSIL.ResolveName(JSIL.GlobalNamespace, fullName);
if (!resolved.exists()) {
resolved.define(decl);
} else {
JSIL.ShadowedTypeWarning(fullName);
}
};
JSIL.MakeInterfaceMemberGetter = function (thisReference, name) {
return function () {
return thisReference[name];
};
};
JSIL.ImplementInterfaces = function (type, interfacesToImplement) {
var interfaces = type.prototype.__Interfaces__;
if (typeof (interfaces) === "undefined") {
type.prototype.__Interfaces__ = interfaces = [];
}
var typeName = JSIL.GetTypeName(type);
var missingMembers = [];
var hasOwnPropertyRecursive = function (target, name) {
while (!target.hasOwnProperty(name)) {
target = Object.getPrototypeOf(target);
if ((typeof (target) === "undefined") || (target === null))
return false;
}
return target.hasOwnProperty(name);
};
var getOwnDescriptorRecursive = function (target, name) {
while (!target.hasOwnProperty(name)) {
target = Object.getPrototypeOf(target);
if ((typeof (target) === "undefined") || (target === null))
return null;
}
return Object.getOwnPropertyDescriptor(target, name);
};
__interfaces__:
for (var i = 0, l = interfacesToImplement.length; i < l; i++) {
var iface = interfacesToImplement[i];
if (typeof (iface) === "undefined") {
JSIL.Host.warning("Type ", typeName, " implements an undefined interface.");
continue __interfaces__;
} else if (typeof (iface) === "string") {
var resolved = JSIL.ResolveName(
type.__Context__ || JSIL.GlobalNamespace, iface
);
if (resolved.exists())
iface = resolved.get();
else {
JSIL.Host.warning("Type ", typeName, " implements an undefined interface named '", iface, "'.");
continue __interfaces__;
}
}
var ifaceName = JSIL.GetTypeName(iface);
if (iface.IsInterface !== true) {
JSIL.Host.warning("Type ", ifaceName, " is not an interface.");
continue __interfaces__;
}
// In cases where an interface method (IInterface_MethodName) is implemented by a regular method
// (MethodName), we make a copy of the regular method with the name of the interface method, so
// that attempts to directly invoke the interface method will still work.
var members = iface.__Members__;
var proto = type.prototype;
if (
(ifaceName.indexOf("Enumerator") !== -1) &&
(typeName.indexOf("Enumerator") !== -1) &&
(typeName.indexOf("List") !== -1)
) {
ifaceName = ifaceName;
}
__members__:
for (var key in members) {
if (!members.hasOwnProperty(key))
continue __members__;
var memberType = members[key];
var qualifiedName = JSIL.EscapeName(iface.__ShortName__ + "." + key);
var hasShort = hasOwnPropertyRecursive(proto, key);
var hasQualified = hasOwnPropertyRecursive(proto, qualifiedName);
if (memberType === Function) {
var shortImpl = proto[key];
var qualifiedImpl = proto[qualifiedName];
} else if (memberType === Property) {
var shortImpl = getOwnDescriptorRecursive(proto, key);
var qualifiedImpl = getOwnDescriptorRecursive(proto, qualifiedName);
}
if (
hasShort &&
(typeof(shortImpl.__IsPlaceholder__) !== "undefined") &&
Boolean(shortImpl.__IsPlaceholder__)
) {
hasShort = false;
}
if (
hasQualified &&
(typeof(qualifiedImpl.__IsPlaceholder__) !== "undefined") &&
Boolean(qualifiedImpl.__IsPlaceholder__)
) {
hasQualified = false;
}
if (!hasShort && !hasQualified) {
missingMembers.push(qualifiedName);
continue __members__;
}
if (!hasQualified) {
if (memberType === Function) {
Object.defineProperty(proto, qualifiedName, {
configurable: true,
enumerable: true,
get: JSIL.MakeInterfaceMemberGetter(proto, key)
});
} else if (memberType === Property) {
Object.defineProperty(proto, qualifiedName, shortImpl);
}
}
}
if (interfaces.indexOf(iface) < 0)
interfaces.push(iface);
}
if (missingMembers.length > 0) {
JSIL.Host.warning("Type ", JSIL.GetTypeName(type), " is missing implementation of interface member(s): ", missingMembers.join(", "));
}
};
JSIL.CheckDerivation = function (haystack, needle) {
var proto = haystack;
while (proto != null) {
if (proto === needle)
return true;
proto = Object.getPrototypeOf(proto);
}
return false;
};
JSIL.CheckType = function (value, expectedType, bypassCustomCheckMethod) {
if (typeof (expectedType) === "undefined") {
JSIL.Host.warning("Warning: Comparing value against an undefined type: ", value);
return false;
}
if (typeof (value) === "undefined")
return false;
else if (value === null)
return false;
if (expectedType.IsInterface === true) {
var interfaces = value.__Interfaces__;
while (JSIL.IsArray(interfaces)) {
for (var i = 0; i < interfaces.length; i++) {
if (interfaces[i] === expectedType)
return true;
}
value = Object.getPrototypeOf(value);
interfaces = value.__Interfaces__;
}
return false;
} else if (expectedType.IsEnum === true) {
return expectedType.CheckType(value);
}
var ct = expectedType.CheckType;
if (
(typeof (ct) != "undefined") &&
!Boolean(bypassCustomCheckMethod)
) {
if (ct(value))
return true;
}
var expectedProto = expectedType.prototype;
if ((typeof (expectedProto) === "undefined") ||
(typeof (expectedProto) === "null"))
return false;
if (typeof (value) === "object") {
if (JSIL.CheckDerivation(Object.getPrototypeOf(value), expectedProto))
return true;
}
return false;
};
JSIL.IsArray = function (value) {
if ((typeof (value) === "object") && (value !== null) && (Object.getPrototypeOf(value) === Array.prototype)) {
var length = null;
try {
length = value.length;
} catch (e) {
}
if (typeof (length) === "number")
return true;
}
return false;
};
JSIL.GetType = function (value) {
var result;
if ((typeof (value) !== "undefined") && (typeof (value.GetType) === "function"))
return value.GetType();
var type = typeof (value);
switch (type) {
case "string":
return System.String;
case "number":
return System.Double;
default:
if (JSIL.IsArray(value))
return System.Array;
break;
}
return System.Object;
}
JSIL.GetTypeName = function (value) {
if (typeof (value) === "undefined" || value === null)
return "System.Object";
var result = value.__FullName__;
if ((typeof (result) === "undefined") && (typeof (value.prototype) !== "undefined"))
result = value.prototype.__FullName__;
if (typeof (result) === "string")
return result;
else if (typeof (result) === "undefined")
result = typeof (value);
if (result === "string")
return "System.String";
else if (result === "number")
return "System.Double";
else if (JSIL.IsArray(value))
return "System.Array";
else if (result === "object" || result === "undefined")
return "System.Object";
return result;
}
JSIL.TryCast = function (value, expectedType) {
if (expectedType.__IsReferenceType__ === false)
throw new System.InvalidCastException("Cannot TryCast a value type");
if (JSIL.CheckType(value, expectedType))
return value;
else
return null;
};
JSIL.Cast = function (value, expectedType) {
if (value === null)
return null;
if (expectedType.IsEnum) {
var result = JSIL.MakeEnumValue(expectedType, value, null);
} else if (JSIL.CheckType(value, expectedType)) {
// If the user is casting to an integral type like Int32, we need to floor the value since JS stores all numbers as double
if (JSIL.CheckDerivation(expectedType.prototype, Number.prototype) && (expectedType.prototype.__IsIntegral__)) {
return Math.floor(value);
}
return value;
} else
throw new System.InvalidCastException("Unable to cast object of type '" + JSIL.GetTypeName(value) + "' to type '" + JSIL.GetTypeName(expectedType) + "'.");
};
JSIL.Coalesce = function (lhs, rhs) {
if (lhs == null)
return rhs;
else
return lhs;
};
JSIL.Dynamic.Cast = function (value, expectedType) {
return value;
};
JSIL.FakeGenericMethod = function (argumentNames, body) {
var result = function () {
};
};
JSIL.GenericMethod = function (argumentNames, body) {
var result = function () {
if (arguments.length !== argumentNames.length)
throw new Error("Invalid number of generic arguments for method (got " + arguments.length + ", expected " + argumentNames.length + ")");
var outerThis = this;
var genericArguments = arguments;
return function () {
var invokeArguments = [];
for (var i = 0, l = genericArguments.length; i < l; i++)
invokeArguments.push(genericArguments[i]);
for (var i = 0, l = arguments.length; i < l; i++)
invokeArguments.push(arguments[i]);
return body.apply(outerThis, invokeArguments);
};
};
result.__IsGenericMethod__ = true;
result.toString = function () {
return "<Unbound Generic Method>";
};
return result;
};
JSIL.FindOverload = function (prototype, args, name, overloads) {
var l = args.length;
find_overload:
for (var i = 0; i < overloads.length; i++) {
var overloadArgs = overloads[i][1];
if (overloadArgs.length != l)
continue find_overload;
for (var j = 0; j < l; j++) {
var expectedType = overloadArgs[j];
var arg = args[j];
if (expectedType.__IsReferenceType__ && (arg === null)) {
} else if (!JSIL.CheckType(arg, expectedType)) {
continue find_overload;
}
}
var overloadName = name + "$" + String(overloads[i][0]);
var overloadMethod;
if (typeof (overloadName) === "function") {
overloadMethod = overloadName;
} else {
overloadMethod = prototype[overloadName];
if (typeof (overloadMethod) === "undefined")
throw new Error("No method named '" + overloadName + "' could be found.");
}
return overloadMethod;
}
return null;
};
JSIL.OverloadedMethod = function (type, name, overloads) {
if (overloads.length < 1)
return type[name] = null;
else if (overloads.length < 2) {
var overload = overloads[0][0];
if (typeof (overload) === "function")
return type[name] = overload;
else
return type[name] = type[overload];
}
for (var i = 0; i < overloads.length; i++) {
if (overloads[i][0] === name)
throw new Error("Recursive definition of overloaded method " + JSIL.GetTypeName(type) + "." + name);
}
var result = function () {
var args = Array.prototype.slice.call(arguments);
var method = JSIL.FindOverload(type, args, name, overloads);
if (method === null)
throw new Error("No overload of '" + name + "' matching the argument list '" + String(args) + "' could be found.");
else
return method.apply(this, args);
};
Object.defineProperty(
type, name, {
configurable: true,
enumerable: true,
value: result
}
);
return result;
};
JSIL.OverloadedGenericMethod = function (type, name, overloads) {
if (overloads.length < 1)
return type[name] = null;
else if (overloads.length < 2) {
var overload = overloads[0][0];
if (typeof (overload) === "function")
return type[name] = overload;
else
return type[name] = type[overload];
}
for (var i = 0; i < overloads.length; i++) {
if (overloads[i][0] === name)
throw new Error("Recursive definition of overloaded generic method " + JSIL.GetTypeName(type) + "." + name);
}
var result = function () {
var genericArguments = Array.prototype.slice.call(arguments);
return function () {
var invokeArguments = Array.prototype.slice.call(arguments);
var method = JSIL.FindOverload(type, invokeArguments, name, overloads);
if (method === null)
throw new Error("No overload of '" + name + "<" + genericArguments.join(", ") + ">' matching the argument list '" + String(invokeArguments) + "' could be found.");
else
return method.apply(this, genericArguments).apply(this, invokeArguments);
};
};
Object.defineProperty(
type, name, {
configurable: true,
enumerable: true,
value: result
}
);
return result;
};
JSIL.MakeClass(Object, "System.Object", true, [], function ($) {
$.CheckType = function (value) {
return true;
};
$.prototype.Equals = function (rhs) {
return this === rhs;
};
$.prototype.MemberwiseClone = function () {
var result = Object.create(Object.getPrototypeOf(this));
JSIL.CopyMembers(this, result);
return result;
};
$.prototype.__Initialize__ = function (initializer) {
if (JSIL.IsArray(initializer)) {
JSIL.CollectionInitializer.prototype.Apply.call(initializer, this);
return this;
} else if (JSIL.CheckType(initializer, JSIL.CollectionInitializer)) {
initializer.Apply(this);
return this;
}
for (var key in initializer) {
if (!initializer.hasOwnProperty(key))
continue;
var value = initializer[key];
if (JSIL.CheckType(value, JSIL.CollectionInitializer)) {
value.Apply(this[key]);
} else {
this[key] = value;
}
}
return this;
};
$.CheckType = function (value) {
return (typeof (value) === "object");
};
$.prototype.__LockCount__ = 0;
$.prototype.__StructFields__ = [];
$.prototype._ctor = function () {};
$.prototype.GetType = function () {
return System.Object;
};
$.prototype.toString = function ToString() {
return JSIL.GetTypeName(this);
};
});
JSIL.MakeClass("System.Object", "JSIL.AnyType", true, [], function ($) {
$.CheckType = function (value) {
return true;
};
});
JSIL.MakeClass("System.Object", "JSIL.AnyValueType", true, [], function ($) {
$.CheckType = function (value) {
return true;
};
});
JSIL.MakeClass("System.Object", "JSIL.Reference", true);
JSIL.MakeClass("JSIL.Reference", "JSIL.Variable", true);
JSIL.MakeClass("JSIL.Reference", "JSIL.MemberReference", true);
JSIL.Reference.__ExpectedType__ = System.Object;
JSIL.Reference.Types = {};
JSIL.Reference.Of = function (type) {
if (typeof (type) === "undefined")
throw new Error("Undefined reference type");
var elementName = JSIL.GetTypeName(type);
var compositeType = JSIL.Reference.Types[elementName];
if (typeof (compositeType) === "undefined") {
var typeName = "ref " + elementName;
compositeType = JSIL.CloneObject(JSIL.Reference);
compositeType.CheckType = function (value) {
var isReference = JSIL.CheckType(value, JSIL.Reference, true);
var isRightType = JSIL.CheckType(value.value, type, false);
if (!isRightType && (type === System.Object) && (value.value === null))
isRightType = true;
return isReference && isRightType;
};
compositeType.toString = function () {
return typeName;
};
compositeType.prototype = JSIL.MakeProto(JSIL.Reference, compositeType, typeName, true);
compositeType.FullName = compositeType.__FullName__ = typeName;
compositeType.__TypeId__ = ++$jsilcore.nextTypeId;
JSIL.Reference.Types[elementName] = compositeType;
}
return compositeType;
};
JSIL.Variable.prototype._ctor = function (value) {
this.value = value;
};
JSIL.MemberReference.prototype._ctor = function (object, memberName) {
this.object = object;
this.memberName = memberName;
};
JSIL.MemberReference.prototype.get_value = function () {
return this.object[this.memberName];
};
JSIL.MemberReference.prototype.set_value = function (value) {
this.object[this.memberName] = value;
}
Object.defineProperty(JSIL.MemberReference.prototype, "value", {
get: JSIL.MemberReference.prototype.get_value,
set: JSIL.MemberReference.prototype.set_value,
configurable: false,
enumerable: false
});
JSIL.MakeClass("System.Object", "JSIL.CollectionInitializer", true);
JSIL.CollectionInitializer.prototype._ctor = function () {
this.values = Array.prototype.slice.call(arguments);
};
JSIL.CollectionInitializer.prototype.Apply = function (target) {
var values;
// This method is designed to support being applied to a regular array as well
if (this.hasOwnProperty("values"))
values = this.values;
else
values = this;
for (var i = 0, l = values.length; i < l; i++)
target.Add(values[i]);
};
JSIL.MakeClass("System.Object", "System.ValueType", true);
System.ValueType.prototype.Equals = function (rhs) {
if (this === rhs)
return true;
if ((rhs === null) || (rhs === undefined))
return false;
for (var key in this) {
if (!this.hasOwnProperty(key))
continue;
var valueLhs = this[key];
var valueRhs = rhs[key];
if ((valueLhs === null) || (valueLhs === undefined)) {
if (valueLhs !== valueRhs)
return false;
} else if (typeof (valueLhs.Equals) === "function") {
if (!valueLhs.Equals(valueRhs))
return false;
} else if (valueLhs !== valueRhs) {
return false;
}
}
return true;
};
JSIL.Interface = function () { };
JSIL.Interface.prototype = JSIL.MakeProto(Object, JSIL.Interface, "JSIL.Interface", true);
JSIL.Interface.prototype.Of = function (T) {
return this;
};
JSIL.MakeInterface("System.IDisposable", [], {
"Dispose": Function
});
JSIL.MakeInterface("System.IEquatable`1", ["T"], {
"Equals": Function
});
JSIL.MakeInterface("System.Collections.IEnumerator", [], {
"MoveNext": Function,
"get_Current": Function,
"Reset": Function,
"Current": Property
});
JSIL.MakeInterface("System.Collections.IEnumerable", [], {
"GetEnumerator": Function
});
JSIL.MakeInterface("System.Collections.Generic.IEnumerator`1", ["T"], {
"get_Current": Function,
"Current": Property
});
JSIL.MakeInterface("System.Collections.Generic.IEnumerable`1", ["T"], {
"GetEnumerator": Function
});
System.Enum.Parse = function (type, value) {
var num = Number(value);
if (isNaN(num)) {
return type[value];
} else {
var name = type.__ValueToName__[value];
if (typeof (name) === "undefined")
return value;
else
return type[name];
}
};
System.Enum.ToString = function (type, value) {
};
System.Enum.prototype = JSIL.MakeProto(System.Object, System.Enum, "System.Enum", false);
System.Enum.prototype.toString = function ToString() {
if (typeof (this.name) === "undefined") {
return this.value.toString();
} else {
return this.name;
}
};
System.Array.prototype = JSIL.MakeProto(System.Object, System.Array, "System.Array", true);
System.Array.prototype.GetLength = function () {
return this.length;
};
System.Array.prototype.GetLowerBound = function () {
return 0;
};
System.Array.prototype.GetUpperBound = function () {
return this.length - 1;
};
System.Array.__IsArray__ = true;
System.Array.Types = {};
System.Array.Of = function (type) {
if (typeof (type) === "undefined")
throw new Error("Attempting to create an array of an undefined type");
var elementName = JSIL.GetTypeName(type);
var compositeType = System.Array.Types[elementName];
if (typeof (compositeType) === "undefined") {
var typeName = elementName + "[]";
compositeType = JSIL.CloneObject(System.Array);
compositeType.FullName = compositeType.__FullName__ = typeName;
compositeType.__TypeId__ = ++$jsilcore.nextTypeId;
compositeType.__IsArray__ = true;
compositeType.prototype = JSIL.MakeProto(System.Array, compositeType, typeName, true);
compositeType.toString = function () {
return typeName;
};
System.Array.Types[elementName] = compositeType;
}
return compositeType;
};
System.Array.CheckType = function (value) {
return JSIL.IsArray(value);
}
JSIL.Array.New = function (type, sizeOrInitializer) {
if (Array.isArray(sizeOrInitializer)) {
// If non-numeric, assume array initializer
var result = new Array(sizeOrInitializer.length);
for (var i = 0; i < sizeOrInitializer.length; i++)
result[i] = sizeOrInitializer[i];
} else {
var size = Number(sizeOrInitializer);
var result = new Array(size);
var defaultValue = null;
if (type.__IsNumeric__)
defaultValue = 0;
for (var i = 0; i < size; i++)
result[i] = defaultValue;
}
/* Even worse, doing this deoptimizes all uses of the array in TraceMonkey. AUGH
// Can't do this the right way, because .prototype for arrays in JS is insanely busted
result.__FullName__ = type.__FullName__ + "[]";
result.toString = System.Object.prototype.toString;
*/
return result;
};
JSIL.Array.ShallowCopy = function (destination, source) {
if (Array.isArray(destination)) {
} else if (Array.isArray(destination._items)) {
destination = destination._items;
} else {
throw new Error("Destination must be an array");
}
if (Array.isArray(source)) {
} else if (Array.isArray(source._items)) {
source = source._items;
} else {
throw new Error("Source must be an array");
}
for (var i = 0, l = Math.min(source.length, destination.length); i < l; i++)
destination[i] = source[i];
};
JSIL.MultidimensionalArray = function (type, dimensions, initializer) {
if (dimensions.length < 2)
throw new Error("Must have at least two dimensions: " + String(dimensions));
var totalSize = dimensions[0];
for (var i = 1; i < dimensions.length; i++)
totalSize *= dimensions[i];
this._dimensions = dimensions;
var items = this._items = new Array(totalSize);
Object.defineProperty(
this, "length", {
value: totalSize,
configurable: true,
enumerable: true
}
);
var defaultValue = null;
if (type.__IsNumeric__)
defaultValue = 0;
if (JSIL.IsArray(initializer)) {
JSIL.Array.ShallowCopy(items, initializer);
} else {
for (var i = 0; i < totalSize; i++)
items[i] = defaultValue;
}
switch (dimensions.length) {
case 2:
var height = this.length0 = dimensions[0];
var width = this.length1 = dimensions[1];
this.Get = function (y, x) {
return items[(y * width) + x];
};
this.GetReference = function (y, x) {
return new JSIL.MemberReference(items, (y * width) + x);
};
this.Set = function (y, x, value) {
items[(y * width) + x] = value;
};
this.GetLength = function (i) {
if (i == 0)
return height;
else
return width;
};
this.GetUpperBound = function (i) {
if (i == 0)
return height - 1;
else
return width - 1;
};
break;
case 3:
var depth = this.length0 = dimensions[0];
var height = this.length1 = dimensions[1];
var width = this.length2 = dimensions[2];
var heightxwidth = height * width;
this.Get = function (z, y, x) {
return items[(z * heightxwidth) + (y * width) + x];
};
this.GetReference = function (z, y, x) {
return new JSIL.MemberReference(items, (z * heightxwidth) + (y * width) + x);
};
this.Set = function (z, y, x, value) {
items[(z * heightxwidth) + (y * width) + x] = value;
};
this.GetLength = function (i) {
if (i == 0)
return depth;
else if (i == 1)
return height;
else
return width;
};
this.GetUpperBound = function (i) {
if (i == 0)
return depth - 1;
else if (i == 1)
return height - 1;
else
return width - 1;
};
break;
}
}
JSIL.MultidimensionalArray.prototype = JSIL.CloneObject(System.Array.prototype);
JSIL.MultidimensionalArray.prototype.GetLowerBound = function (i) {
return 0;
};
JSIL.MultidimensionalArray.New = function (type) {
var initializer = arguments[arguments.length - 1];
var numDimensions = arguments.length - 1;
if (JSIL.IsArray(initializer))
numDimensions -= 1;
else
initializer = null;
if (numDimensions < 1)
throw new Error("Must provide at least one dimension");
else if ((numDimensions == 1) && (initializer === null))
return System.Array.New(type, arguments[1]);
var dimensions = Array.prototype.slice.call(arguments, 1, 1 + numDimensions);
if (initializer != null)
return new JSIL.MultidimensionalArray(type, dimensions, initializer);
else
return new JSIL.MultidimensionalArray(type, dimensions);
};
JSIL.MakeDelegateType = function (fullName, localName) {
if (typeof (JSIL.Delegate.Types[fullName]) !== "undefined")
return JSIL.Delegate.Types[fullName].__Self__;
var delegateType = System.MulticastDelegate;
var prototype = JSIL.CloneObject(delegateType.prototype);
prototype.__BaseType__ = delegateType;
prototype.__ShortName__ = localName;
prototype.FullName = prototype.__FullName__ = fullName;
var result = {
prototype: prototype,
__TypeId__: ++$jsilcore.nextTypeId,
__BaseType__: delegateType,
__FullName__: fullName,
CheckType: function (value) {
if (
(
(typeof (value) === "function") ||
(typeof (value) === "object")
) &&
(typeof (value.GetType) === "function") &&
(value.GetType() === result)
)
return true;
return false;
},
IsEnum: false,
};
result.Of = function () {
return result;
};
prototype.__Self__ = result;
JSIL.Delegate.Types[fullName] = prototype;
return result;
}
JSIL.MakeDelegate = function (fullName) {
try {
delete JSIL.Delegate.Types[fullName];
} catch (e) {
}
var result = JSIL.MakeDelegateType(fullName);
var decl = {
configurable: true,
enumerable: true,
value: result
};
var resolved = JSIL.ResolveName($private, fullName);
if (!resolved.exists())
resolved.define(decl);
resolved = JSIL.ResolveName(JSIL.GlobalNamespace, fullName);
if (!resolved.exists()) {
resolved.define(decl);
} else {
JSIL.ShadowedTypeWarning(fullName);
}
return result;
};
JSIL.Delegate.Types = {};
JSIL.Delegate.New = function (typeName, object, method) {
var existingType = JSIL.Delegate.Types[typeName];
if (typeof (existingType) === "undefined") {
JSIL.MakeDelegateType(typeName, JSIL.GetLocalName(typeName));
existingType = JSIL.Delegate.Types[typeName];
}
if ((typeof (method) === "undefined") &&
(typeof (object) === "function")
) {
method = object;
object = null;
if (JSIL.GetTypeName(method) == typeName)
return method;
}
var result = method.bind(object);
result.toString = function () {
return typeName;
};
result.GetType = function () {
return existingType.__Self__;
};
result.__object__ = object;
result.__method__ = method;
Object.seal(result);
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment