Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View File

@ -0,0 +1,31 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package cs.internal;
@:unsafe @:keep @:native('haxe.lang.BoxedPointer') @:nativeGen class BoxedPointer {
@:readonly public var value(default, null):Pointer<Dynamic>;
public function new(val) {
this.value = val;
}
}

View File

@ -0,0 +1,311 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package cs.internal;
@:native('haxe.lang.FieldHashConflict')
@:nativeGen @:keep
final class FieldHashConflict {
@:readOnly public var hash(default, never):Int;
@:readOnly public var name(default, never):String;
public var value:Dynamic;
public var next:FieldHashConflict;
public function new(hash, name, value:Dynamic, next) {
untyped this.hash = hash;
untyped this.name = name;
this.value = value;
this.next = next;
}
}
@:native('haxe.lang.FieldLookup')
@:classCode("#pragma warning disable 628\n")
@:nativeGen @:keep @:static
final class FieldLookup {
@:protected private static var fieldIds:cs.NativeArray<Int>;
@:protected private static var fields:cs.NativeArray<String>;
@:protected private static var length:Int;
static function __init__() {
length = fieldIds.Length;
}
private static function addFields(nids:cs.NativeArray<Int>, nfields:cs.NativeArray<String>):Void {
// first see if we need to add anything
var cids = fieldIds, cfields = fields;
var nlen = nids.Length;
var clen = length;
if (nfields.Length != nlen)
throw 'Different fields length: $nlen and ${nfields.Length}';
// TODO optimize
var needsChange = false;
for (i in nids) {
if (findHash(i, cids, clen) < 0) {
needsChange = true;
break;
}
}
// if we do, lock and merge
if (needsChange) {
cs.Lib.lock(FieldLookup, {
// trace(cs.Lib.array(nids), cs.Lib.array(cids));
var ansIds = new cs.NativeArray(clen + nlen),
ansFields = new cs.NativeArray(clen + nlen);
var ci = 0, ni = 0, ansi = 0;
while (ci < clen && ni < nlen) {
if (cids[ci] < nids[ni]) {
ansIds[ansi] = cids[ci];
ansFields[ansi] = cfields[ci];
++ci;
} else {
ansIds[ansi] = nids[ni];
ansFields[ansi] = nfields[ni];
++ni;
}
++ansi;
}
if (ci < clen) {
cs.system.Array.Copy(cids, ci, ansIds, ansi, clen - ci);
cs.system.Array.Copy(cfields, ci, ansFields, ansi, clen - ci);
ansi += clen - ci;
}
if (ni < nlen) {
cs.system.Array.Copy(nids, ni, ansIds, ansi, nlen - ni);
cs.system.Array.Copy(nfields, ni, ansFields, ansi, nlen - ni);
ansi += nlen - ni;
}
// trace(cs.Lib.array(ansIds));
fieldIds = ansIds;
fields = ansFields;
length = ansi;
});
}
}
// s cannot be null here
private static inline function doHash(s:String):Int {
var acc = 0; // alloc_int
for (i in 0...s.length) {
acc = ((223 * (acc >> 1) + cast(s[i], Int)) << 1);
}
return acc >>> 1; // always positive
}
public static function lookupHash(key:Int):String {
var ids = fieldIds;
var min = 0;
var max = length;
while (min < max) {
var mid = min + Std.int((max - min) / 2);
var imid = ids[mid];
if (key < imid) {
max = mid;
} else if (key > imid) {
min = mid + 1;
} else {
return fields[mid];
}
}
// if not found, it's definitely an error
throw "Field not found for hash " + key;
}
public static function hash(s:String):Int {
if (s == null)
return 0;
var key = doHash(s);
var ids = fieldIds, fld = fields;
var min = 0;
var max = length;
var len = length;
while (min < max) {
var mid = Std.int(min + (max - min) / 2); // overflow safe
var imid = ids[mid];
if (key < imid) {
max = mid;
} else if (key > imid) {
min = mid + 1;
} else {
var field = fld[mid];
if (field != s)
return ~key; // special case
return key;
}
}
// if not found, min holds the value where we should insert the key
// ensure thread safety:
cs.Lib.lock(FieldLookup, {
if (len != length) // race condition which will very rarely happen - other thread modified sooner.
return hash(s); // since we already own the lock, this second try will always succeed
fieldIds = insertInt(fieldIds, length, min, key);
fields = insertString(fields, length, min, s);
++length;
});
return key;
}
public static function findHash(hash:Int, hashs:cs.NativeArray<Int>, length:Int):Int {
var min = 0;
var max = length;
while (min < max) {
var mid = Std.int((max + min) / 2);
var imid = hashs[mid];
if (hash < imid) {
max = mid;
} else if (hash > imid) {
min = mid + 1;
} else {
return mid;
}
}
// if not found, return a negative value of where it should be inserted
return ~min;
}
public static function removeInt(a:cs.NativeArray<Int>, length:Int, pos:Int) {
cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1);
a[length - 1] = 0;
}
public static function removeFloat(a:cs.NativeArray<Float>, length:Int, pos:Int) {
cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1);
a[length - 1] = 0;
}
public static function removeDynamic(a:cs.NativeArray<Dynamic>, length:Int, pos:Int) {
cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1);
a[length - 1] = null;
}
extern static inline function __insert<T>(a:cs.NativeArray<T>, length:Int, pos:Int, x:T):cs.NativeArray<T> {
var capacity = a.Length;
if (pos == length) {
if (capacity == length) {
var newarr = new NativeArray((length << 1) + 1);
a.CopyTo(newarr, 0);
a = newarr;
}
} else if (pos == 0) {
if (capacity == length) {
var newarr = new NativeArray((length << 1) + 1);
cs.system.Array.Copy(a, 0, newarr, 1, length);
a = newarr;
} else {
cs.system.Array.Copy(a, 0, a, 1, length);
}
} else {
if (capacity == length) {
var newarr = new NativeArray((length << 1) + 1);
cs.system.Array.Copy(a, 0, newarr, 0, pos);
cs.system.Array.Copy(a, pos, newarr, pos + 1, length - pos);
a = newarr;
} else {
cs.system.Array.Copy(a, pos, a, pos + 1, length - pos);
cs.system.Array.Copy(a, 0, a, 0, pos);
}
}
a[pos] = x;
return a;
}
public static function insertInt(a:cs.NativeArray<Int>, length:Int, pos:Int, x:Int):cs.NativeArray<Int>
return __insert(a, length, pos, x);
public static function insertFloat(a:cs.NativeArray<Float>, length:Int, pos:Int, x:Float):cs.NativeArray<Float>
return __insert(a, length, pos, x);
public static function insertDynamic(a:cs.NativeArray<Dynamic>, length:Int, pos:Int, x:Dynamic):cs.NativeArray<Dynamic>
return __insert(a, length, pos, x);
public static function insertString(a:cs.NativeArray<String>, length:Int, pos:Int, x:String):cs.NativeArray<String>
return __insert(a, length, pos, x);
public static function getHashConflict(head:FieldHashConflict, hash:Int, name:String):FieldHashConflict {
while (head != null) {
if (head.hash == hash && head.name == name) {
return head;
}
head = head.next;
}
return null;
}
public static function setHashConflict(head:cs.Ref<FieldHashConflict>, hash:Int, name:String, value:Dynamic):Void {
var node = head;
while (node != null) {
if (node.hash == hash && node.name == name) {
node.value = value;
return;
}
node = node.next;
}
head = new FieldHashConflict(hash, name, value, head);
}
public static function deleteHashConflict(head:cs.Ref<FieldHashConflict>, hash:Int, name:String):Bool {
// no conflicting fields at all
if (head == null) {
return false;
}
// list head is conflicting - just point it to the next one
if (head.hash == hash && head.name == name) {
head = head.next;
return true;
}
// loop through the list, removing node if there's one
var prev = head, node = head.next;
while (node != null) {
if (node.hash == hash && node.name == name) {
prev.next = node.next;
return true;
}
node = node.next;
}
// not found
return false;
}
public static function addHashConflictNames(head:FieldHashConflict, arr:Array<String>):Void {
while (head != null) {
arr.push(head.name);
head = head.next;
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package cs.internal;
/**
These classes are automatically generated by the compiler. They are only
here so there is an option for e.g. defining them as externs if you are compiling
in modules (untested).
**/
@:keep @:abstract @:nativeGen @:native("haxe.lang.Function") class Function {
function new(arity:Int, type:Int) {}
}
@:keep @:nativeGen @:native("haxe.lang.VarArgsBase") private class VarArgsBase extends Function {
public function __hx_invokeDynamic(dynArgs:cs.NativeArray<Dynamic>):Dynamic {
throw "Abstract implementation";
}
}
@:keep @:nativeGen @:native('haxe.lang.VarArgsFunction') class VarArgsFunction extends VarArgsBase {
private var fun:Array<Dynamic>->Dynamic;
public function new(fun) {
super(-1, -1);
this.fun = fun;
}
override public function __hx_invokeDynamic(dynArgs:cs.NativeArray<Dynamic>):Dynamic {
return fun(dynArgs == null ? [] : cs.Lib.array(dynArgs));
}
}
@:keep @:nativeGen @:native('haxe.lang.Closure') class Closure extends VarArgsBase {
private var obj:Dynamic;
private var field:String;
private var hash:Int;
public function new(obj:Dynamic, field, hash) {
super(-1, -1);
this.obj = obj;
this.field = field;
this.hash = hash;
}
override public function __hx_invokeDynamic(dynArgs:cs.NativeArray<Dynamic>):Dynamic {
return Runtime.callField(obj, field, hash, dynArgs);
}
public function Equals(obj:Dynamic):Bool {
var c = cs.Lib.as(obj, Closure);
if (c == null)
return false;
return (c.obj == this.obj && c.field == this.field);
}
public function GetHashCode():Int {
return obj.GetHashCode() ^ untyped field.GetHashCode();
}
}

View File

@ -0,0 +1,317 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package cs.internal;
import cs.system.Type;
import haxe.ds.Vector;
import cs.internal.FieldLookup;
private typedef StdType = std.Type;
@:keep @:native('haxe.lang.HxObject')
class HxObject implements IHxObject {
public function __hx_deleteField(field:String, hash:Int):Bool {
return false;
}
}
@:keep @:native('haxe.lang.IHxObject')
interface IHxObject {}
#if core_api_serialize
@:meta(System.Serializable)
#end
@:keep @:native('haxe.lang.DynamicObject')
class DynamicObject extends HxObject {
@:skipReflection var __hx_hashes:NativeArray<Int>;
@:skipReflection var __hx_dynamics:NativeArray<Dynamic>;
@:skipReflection var __hx_hashes_f:NativeArray<Int>;
@:skipReflection var __hx_dynamics_f:NativeArray<Float>;
@:skipReflection var __hx_length:Int;
@:skipReflection var __hx_length_f:Int;
@:skipReflection var __hx_conflicts:FieldHashConflict;
@:skipReflection static var __hx_toString_depth = 0;
@:overload public function new() {
this.__hx_hashes = new NativeArray(0);
this.__hx_dynamics = new NativeArray(0);
this.__hx_hashes_f = new NativeArray(0);
this.__hx_dynamics_f = new NativeArray(0);
this.__hx_conflicts = null;
}
@:overload public function new(hashes:NativeArray<Int>, dynamics:NativeArray<Dynamic>, hashes_f:NativeArray<Int>, dynamics_f:NativeArray<Float>) {
this.__hx_hashes = hashes;
this.__hx_dynamics = dynamics;
this.__hx_hashes_f = hashes_f;
this.__hx_dynamics_f = dynamics_f;
this.__hx_length = hashes.length;
this.__hx_length_f = hashes_f.length;
this.__hx_conflicts = null;
}
override public function __hx_deleteField(field:String, hash:Int):Bool {
if (hash < 0) {
return FieldLookup.deleteHashConflict(this.__hx_conflicts, hash, field);
}
var res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length);
if (res >= 0) {
FieldLookup.removeInt(this.__hx_hashes, this.__hx_length, res);
FieldLookup.removeDynamic(this.__hx_dynamics, this.__hx_length, res);
this.__hx_length--;
return true;
}
res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f);
if (res >= 0) {
FieldLookup.removeInt(this.__hx_hashes_f, this.__hx_length_f, res);
FieldLookup.removeFloat(this.__hx_dynamics_f, this.__hx_length_f, res);
this.__hx_length_f--;
return true;
}
return false;
}
public function __hx_getField(field:String, hash:Int, throwErrors:Bool, isCheck:Bool, handleProperties:Bool):Dynamic {
if (hash < 0) {
var conflict = FieldLookup.getHashConflict(this.__hx_conflicts, hash, field);
if (conflict != null) {
return conflict.value;
}
}
var res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length);
if (res >= 0) {
return this.__hx_dynamics[res];
}
res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f);
if (res >= 0) {
return this.__hx_dynamics_f[res];
}
return isCheck ? Runtime.undefined : null;
}
public function __hx_setField(field:String, hash:Int, value:Dynamic, handleProperties:Bool):Dynamic {
if (hash < 0) {
FieldLookup.setHashConflict(this.__hx_conflicts, hash, field, value);
return value;
}
var res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length);
if (res >= 0) {
return this.__hx_dynamics[res] = value;
} else {
var res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f);
if (res >= 0) {
if (Std.isOfType(value, Float)) {
return this.__hx_dynamics_f[res] = value;
}
FieldLookup.removeInt(this.__hx_hashes_f, this.__hx_length_f, res);
FieldLookup.removeFloat(this.__hx_dynamics_f, this.__hx_length_f, res);
this.__hx_length_f--;
}
}
this.__hx_hashes = FieldLookup.insertInt(this.__hx_hashes, this.__hx_length, ~(res), hash);
this.__hx_dynamics = FieldLookup.insertDynamic(this.__hx_dynamics, this.__hx_length, ~(res), value);
this.__hx_length++;
return value;
}
public function __hx_getField_f(field:String, hash:Int, throwErrors:Bool, handleProperties:Bool):Float {
if (hash < 0) {
var conflict = FieldLookup.getHashConflict(this.__hx_conflicts, hash, field);
if (conflict != null) {
return conflict.value;
}
}
var res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f);
if (res >= 0) {
return this.__hx_dynamics_f[res];
}
res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length);
if (res >= 0) {
return this.__hx_dynamics[res];
}
return 0.0;
}
public function __hx_setField_f(field:String, hash:Int, value:Float, handleProperties:Bool):Float {
if (hash < 0) {
FieldLookup.setHashConflict(this.__hx_conflicts, hash, field, value);
return value;
}
var res = FieldLookup.findHash(hash, this.__hx_hashes_f, this.__hx_length_f);
if (res >= 0) {
return this.__hx_dynamics_f[res] = value;
} else {
var res = FieldLookup.findHash(hash, this.__hx_hashes, this.__hx_length);
if (res >= 0) {
// return this.__hx_dynamics[res] = value;
FieldLookup.removeInt(this.__hx_hashes, this.__hx_length, res);
FieldLookup.removeDynamic(this.__hx_dynamics, this.__hx_length, res);
this.__hx_length--;
}
}
this.__hx_hashes_f = FieldLookup.insertInt(this.__hx_hashes_f, this.__hx_length_f, ~(res), hash);
this.__hx_dynamics_f = FieldLookup.insertFloat(this.__hx_dynamics_f, this.__hx_length_f, ~(res), value);
this.__hx_length_f++;
return value;
}
public function __hx_getFields(baseArr:Array<String>):Void {
for (i in 0...this.__hx_length) {
baseArr.push(FieldLookup.lookupHash(this.__hx_hashes[i]));
}
for (i in 0...this.__hx_length_f) {
baseArr.push(FieldLookup.lookupHash(this.__hx_hashes_f[i]));
}
FieldLookup.addHashConflictNames(this.__hx_conflicts, baseArr);
}
public function __hx_invokeField(field:String, hash:Int, dynargs:NativeArray<Dynamic>):Dynamic {
if (field == "toString") {
return this.toString();
}
var fn:Function = this.__hx_getField(field, hash, false, false, false);
if (fn == null) {
throw 'Cannot invoke field $field: It does not exist';
}
return untyped fn.__hx_invokeDynamic(dynargs);
}
@:skipReflection public function toString() {
if (__hx_toString_depth >= 5) {
return "...";
}
++__hx_toString_depth;
try {
var s = __hx_toString();
--__hx_toString_depth;
return s;
} catch (e:Dynamic) {
--__hx_toString_depth;
throw(e);
}
}
@:skipReflection public function __hx_toString():String {
var ts = Reflect.field(this, "toString");
if (ts != null)
return ts();
var ret = new StringBuf();
ret.add("{");
var first = true;
for (f in Reflect.fields(this)) {
if (first)
first = false;
else
ret.add(",");
ret.add(" ");
ret.add(f);
ret.add(" : ");
ret.add(Reflect.field(this, f));
}
if (!first)
ret.add(" ");
ret.add("}");
return ret.toString();
}
}
#if !erase_generics
@:keep @:native('haxe.lang.IGenericObject') interface IGenericObject {}
@:nativeGen @:keep @:native('haxe.lang.GenericInterface') class GenericInterface extends cs.system.Attribute {
@:readOnly public var generic(default, never):cs.system.Type;
public function new(generic) {
super();
untyped this.generic = generic;
}
}
#end
@:keep
@:native('haxe.lang.Enum')
@:nativeGen
#if core_api_serialize
@:meta(System.Serializable)
#end
class HxEnum {
@:readOnly var _hx_index(default, never):Int;
@:protected function new(index:Int) {
untyped this._hx_index = index;
}
public function getTag():String {
return throw new haxe.exceptions.NotImplementedException();
}
public function getParams():Array<{}> {
return [];
}
public function toString():String {
return getTag();
}
@:protected static function paramsToString(tag:String, params:Vector<Dynamic>):String {
var ret = new StringBuf();
ret.add(tag);
ret.add("(");
var first = true;
for (p in params) {
if (first)
first = false;
else
ret.add(",");
ret.add(p);
}
ret.add(")");
return ret.toString();
}
@:protected static function paramsGetHashCode(index:Int, params:Vector<Dynamic>):Int {
var h:Int = 19;
if (params != null)
for (p in params) {
h = h * 31;
if (p != null)
untyped h += p.GetHashCode();
}
h += index;
return h;
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package cs.internal;
@:classCode('//This function is here to be used with Reflection, when the haxe.lang.Null type is known
public static haxe.lang.Null<T> _ofDynamic(object obj) {
if (obj == null) {
return new haxe.lang.Null<T>(default(T), false);
} else if (typeof(T).Equals(typeof(double))) {
return new haxe.lang.Null<T>((T) (object) haxe.lang.Runtime.toDouble(obj), true);
} else if (typeof(T).Equals(typeof(int))) {
return new haxe.lang.Null<T>((T) (object) haxe.lang.Runtime.toInt(obj), true);
} else {
return new haxe.lang.Null<T>((T) obj, true);
}
}
public static implicit operator haxe.lang.Null<T>(T val) {
return new haxe.lang.Null<T>(val, true);
}
public static implicit operator Null<T>(__NoValue__ noValue) {
return new haxe.lang.Null<T>(default(T), false);
}
public sealed class __NoValue__ {
private __NoValue__() {}
}
override public string ToString() {
if (!hasValue) return "null";
else return value.ToString();
}
')
#if core_api_serialize
@:meta(System.Serializable)
#end
@:keep @:struct @:nativeGen @:native("haxe.lang.Null") private class Nullable<T> {
@:readOnly public var value(default, never):T;
@:readOnly public var hasValue(default, never):Bool;
public function new(v:T, hasValue:Bool) {
if (hasValue && cs.system.Object.ReferenceEquals(v, null)) {
hasValue = false;
}
untyped this.value = v;
untyped this.hasValue = hasValue;
}
@:functionCode('if (obj == null) {
return new haxe.lang.Null<D>(default(D), false);
} else if (typeof(D).Equals(typeof(double))) {
return new haxe.lang.Null<D>((D) (object) haxe.lang.Runtime.toDouble(obj), true);
} else if (typeof(D).Equals(typeof(int))) {
return new haxe.lang.Null<D>((D) (object) haxe.lang.Runtime.toInt(obj), true);
} else {
return new haxe.lang.Null<D>((D) obj, true);
}')
public static function ofDynamic<D>(obj:Dynamic):Nullable<D> {
return null;
}
public function toDynamic():Dynamic {
if (this.hasValue)
return value;
return null;
}
}

View File

@ -0,0 +1,712 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package cs.internal;
import cs.Lib;
import cs.Lib.*;
import cs.NativeArray;
import cs.StdTypes;
import cs.system.Activator;
import cs.system.IConvertible;
import cs.system.IComparable;
import cs.system.reflection.MethodBase;
import cs.system.reflection.MethodInfo;
import cs.system.reflection.*;
import cs.system.Type;
import cs.system.Object;
/**
This class is meant for internal compiler use only. It provides the Haxe runtime
compatibility to the host language.
**/
@:nativeGen
@:native('haxe.lang.Runtime')
@:access(String)
@:classCode('
public static object getField(haxe.lang.HxObject obj, string field, int fieldHash, bool throwErrors)
{
if (obj == null && !throwErrors) return null;
return obj.__hx_getField(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, throwErrors, false, false);
}
public static double getField_f(haxe.lang.HxObject obj, string field, int fieldHash, bool throwErrors)
{
if (obj == null && !throwErrors) return 0.0;
return obj.__hx_getField_f(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, throwErrors, false);
}
public static object setField(haxe.lang.HxObject obj, string field, int fieldHash, object value)
{
return obj.__hx_setField(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, value, false);
}
public static double setField_f(haxe.lang.HxObject obj, string field, int fieldHash, double value)
{
return obj.__hx_setField_f(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, value, false);
}
public static object callField(haxe.lang.HxObject obj, string field, int fieldHash, object[] args)
{
return obj.__hx_invokeField(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, args);
}
')
@:keep class Runtime {
@:readOnly public static var undefined(default, never):Dynamic = new cs.system.Object();
public static function closure(obj:Dynamic, hash:Int, field:String):Dynamic {
return new cs.internal.Function.Closure(obj, field, hash);
}
public static function eq(v1:Dynamic, v2:Dynamic):Bool {
if (Object.ReferenceEquals(v1, v2))
return true;
if (Object.ReferenceEquals(v1, null) || Object.ReferenceEquals(v2, null))
return false;
var v1c = Lib.as(v1, IConvertible);
if (v1c != null) {
var v2c = Lib.as(v2, IConvertible);
if (v2c == null) {
return false;
}
var t1 = v1c.GetTypeCode(), t2 = v2c.GetTypeCode();
if (t1 == t2)
return Object._Equals(v1c, v2c);
if (t1 == cs.system.TypeCode.String || t2 == cs.system.TypeCode.String)
return false;
switch [t1, t2] {
case [Decimal, _] | [_, Decimal]:
return v1c.ToDecimal(null) == v2c.ToDecimal(null);
case [Int64, _] | [_, Int64]:
return v1c.ToInt64(null) == v2c.ToInt64(null);
case [UInt64 | DateTime, _] | [_, UInt64 | DateTime]:
return v1c.ToUInt64(null) == v2c.ToUInt64(null);
case [Double | Single, _] | [_, Double | Single]:
return v1c.ToDouble(null) == v2c.ToDouble(null);
case _:
return v1c.ToInt32(null) == v2c.ToInt32(null);
}
}
var v1v = Lib.as(v1, cs.system.ValueType);
if (v1v != null) {
return v1.Equals(v2);
#if !erase_generics
}
else {
var v1t = Lib.as(v1, Type);
if (v1t != null) {
var v2t = Lib.as(v2, Type);
if (v2t != null)
return typeEq(v1t, v2t);
return false;
}
#end
}
return false;
}
public static function refEq(v1:{}, v2:{}):Bool {
#if !erase_generics
if (Std.isOfType(v1, Type))
return typeEq(Lib.as(v1, Type), Lib.as(v2, Type));
#end
return Object.ReferenceEquals(v1, v2);
}
public static function toDouble(obj:Dynamic):Float {
return (obj == null) ? .0 : Std.isOfType(obj, Float) ? cast obj : Lib.as(obj, IConvertible).ToDouble(null);
}
public static function toInt(obj:Dynamic):Int {
return (obj == null) ? 0 : Std.isOfType(obj, Int) ? cast obj : Lib.as(obj, IConvertible).ToInt32(null);
}
#if erase_generics
public static function toLong(obj:Dynamic):Int64 {
return (obj == null) ? 0 : Std.isOfType(obj, Int64) ? cast obj : Lib.as(obj, IConvertible).ToInt64(null);
}
#end
public static function isInt(obj:Dynamic):Bool {
var cv1 = Lib.as(obj, IConvertible);
if (cv1 != null) {
switch (cv1.GetTypeCode()) {
case Double:
var d:Float = cast obj;
return d >= cs.system.Int32.MinValue && d <= cs.system.Int32.MaxValue && d == (cast(d, Int));
case UInt32, Int32:
return true;
default:
return false;
}
}
return false;
}
public static function isUInt(obj:Dynamic):Bool {
var cv1 = Lib.as(obj, IConvertible);
if (cv1 != null) {
switch (cv1.GetTypeCode()) {
case Double:
var d:Float = cast obj;
return d >= cs.system.UInt32.MinValue && d <= cs.system.UInt32.MaxValue && d == (cast(d, UInt));
case UInt32:
return true;
default:
return false;
}
}
return false;
}
public static function compare(v1:Dynamic, v2:Dynamic):Int {
if (Object.ReferenceEquals(v1, v2))
return 0;
if (Object.ReferenceEquals(v1, null))
return -1;
if (Object.ReferenceEquals(v2, null))
return 1;
var cv1 = Lib.as(v1, IConvertible);
if (cv1 != null) {
var cv2 = Lib.as(v2, IConvertible);
if (cv2 == null) {
throw new cs.system.ArgumentException("Cannot compare " + getNativeType(v1).ToString() + " and " + getNativeType(v2).ToString());
}
switch (cv1.GetTypeCode()) {
case cs.system.TypeCode.String:
if (cv2.GetTypeCode() != cs.system.TypeCode.String)
throw new cs.system.ArgumentException("Cannot compare " + getNativeType(v1).ToString() + " and " + getNativeType(v2).ToString());
var s1 = Lib.as(v1, String);
var s2 = Lib.as(v2, String);
return String.Compare(s1, s2, cs.system.StringComparison.Ordinal);
case cs.system.TypeCode.Double:
var d1:Float = cast v1, d2:Float = cv2.ToDouble(null);
return (d1 < d2) ? -1 : (d1 > d2) ? 1 : 0;
default:
var d1d = cv1.ToDouble(null);
var d2d = cv2.ToDouble(null);
return (d1d < d2d) ? -1 : (d1d > d2d) ? 1 : 0;
}
}
var c1 = Lib.as(v1, IComparable);
var c2 = Lib.as(v2, IComparable);
if (c1 == null || c2 == null) {
throw new cs.system.ArgumentException("Cannot compare " + getNativeType(v1).ToString() + " and " + getNativeType(v2).ToString());
}
return c1.CompareTo(c2);
}
public static function plus(v1:Dynamic, v2:Dynamic):Dynamic {
if (Std.isOfType(v1, String) || Std.isOfType(v2, String))
return Std.string(v1) + Std.string(v2);
if (v1 == null) {
if (v2 == null)
return null;
v1 = 0;
} else if (v2 == null)
v2 = 0;
var cv1 = Lib.as(v1, IConvertible);
if (cv1 != null) {
var cv2 = Lib.as(v2, IConvertible);
if (cv2 == null) {
throw new cs.system.ArgumentException("Cannot dynamically add " + cs.Lib.getNativeType(v1).ToString() + " and "
+ cs.Lib.getNativeType(v2).ToString());
}
return cv1.ToDouble(null) + cv2.ToDouble(null);
}
throw new cs.system.ArgumentException("Cannot dynamically add " + v1 + " and " + v2);
}
public static function slowGetField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic {
if (obj == null)
if (throwErrors)
throw new cs.system.NullReferenceException("Cannot access field \'" + field + "\' of null.");
else
return null;
var t = Lib.as(obj, cs.system.Type);
var bf = if (t == null) {
var s = Lib.as(obj, String);
if (s != null)
return cs.internal.StringExt.StringRefl.handleGetField(s, field, throwErrors);
t = obj.GetType();
new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy;
} else {
if (t == Lib.toNativeType(String) && field == "fromCharCode")
return new cs.internal.Function.Closure(StringExt, field, 0);
obj = null;
new cs.Flags(BindingFlags.Static) | BindingFlags.Public;
}
var f = t.GetField(field, bf);
if (f != null) {
return unbox(f.GetValue(obj));
} else {
var prop = t.GetProperty(field, bf);
if (prop == null) {
var m = t.GetMember(field, bf);
if (m.length == 0 && (field == "__get" || field == "__set"))
m = t.GetMember(field == "__get" ? "get_Item" : "set_Item", bf);
if (m.Length > 0) {
return new cs.internal.Function.Closure(obj != null ? obj : t, field, 0);
} else {
// COM object handling
if (t.IsCOMObject) {
try {
return t.InvokeMember(field, BindingFlags.GetProperty, null, obj, new cs.NativeArray(0));
} catch (e:cs.system.Exception) {
// Closures of COM objects not supported currently
}
}
if (throwErrors)
throw "Cannot access field \'" + field + "\'.";
else
return null;
}
}
return unbox(prop.GetValue(obj, null));
}
}
public static function slowHasField(obj:Dynamic, field:String):Bool {
if (obj == null)
return false;
var t = Lib.as(obj, cs.system.Type);
var bf = if (t == null) {
var s = Lib.as(obj, String);
if (s != null)
return cs.internal.StringExt.StringRefl.handleGetField(s, field, false) != null;
t = obj.GetType();
new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy;
} else {
if (t == Lib.toNativeType(String))
return field == "fromCharCode";
obj = null;
new cs.Flags(BindingFlags.Static) | BindingFlags.Public;
}
var mi = t.GetMember(field, bf);
return mi != null && mi.length > 0;
}
public static function slowSetField(obj:Dynamic, field:String, value:Dynamic):Dynamic {
if (obj == null)
throw new cs.system.NullReferenceException("Cannot access field \'" + field + "\' of null.");
var t = Lib.as(obj, cs.system.Type);
var bf = if (t == null) {
t = obj.GetType();
new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy;
} else {
obj = null;
new cs.Flags(BindingFlags.Static) | BindingFlags.Public;
}
var f = t.GetField(field, bf);
if (f != null) {
if (f.FieldType.ToString().StartsWith("haxe.lang.Null")) {
value = mkNullable(value, f.FieldType);
}
if (value != null
&& Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value))
&& !Object.ReferenceEquals(t, f.FieldType)) {
var ic = Lib.as(value, IConvertible);
value = ic.ToType(f.FieldType, null);
}
f.SetValue(obj, value);
return value;
} else {
var prop = t.GetProperty(field, bf);
if (prop == null) {
// COM object handling
if (t.IsCOMObject) {
try {
return t.InvokeMember(field, BindingFlags.SetProperty, null, obj, cs.NativeArray.make(value));
} catch (e:cs.system.Exception) {
// Closures of COM objects not supported currently
}
}
throw "Field \'" + field + "\' not found for writing from Class " + t;
}
if (prop.PropertyType.ToString().StartsWith("haxe.lang.Null")) {
value = mkNullable(value, prop.PropertyType);
}
if (Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value))
&& !Object.ReferenceEquals(t, prop.PropertyType)) {
var ic = Lib.as(value, IConvertible);
value = ic.ToType(prop.PropertyType, null);
}
prop.SetValue(obj, value, null);
return value;
}
}
public static function callMethod(obj:Dynamic, methods:NativeArray<MethodBase>, methodLength:Int, args:cs.NativeArray<Dynamic>):Dynamic {
if (methodLength == 0)
throw "No available methods";
var length = args.length;
var oargs:NativeArray<Dynamic> = new NativeArray(length);
var ts:NativeArray<Type> = new NativeArray(length);
var rates:NativeArray<Int> = new NativeArray(methods.Length);
for (i in 0...length) {
oargs[i] = args[i];
if (args[i] != null)
ts[i] = Lib.getNativeType(args[i]);
}
var last = 0;
// first filter by number of parameters and if it is assignable
if (methodLength > 1) {
for (i in 0...methodLength) {
var params = methods[i].GetParameters();
if (params.Length != length) {
continue;
} else {
var fits = true, crate = 0;
for (i in 0...params.Length) {
var param = params[i].ParameterType;
var strParam = param + "";
if (param.IsAssignableFrom(ts[i]) || (ts[i] == null && !param.IsValueType)) {
// if it is directly assignable, we'll give it top rate
continue;
} else if (untyped strParam.StartsWith("haxe.lang.Null")
|| ((oargs[i] == null || Std.isOfType(oargs[i], IConvertible))
&& cast(untyped __typeof__(IConvertible), Type).IsAssignableFrom(param))) {
// if it needs conversion, give a penalty. TODO rate penalty
crate++;
continue;
} else if (!param.ContainsGenericParameters) { // generics don't appear as assignable, but may be in the end. no rate there.
fits = false;
break;
}
}
if (fits) {
rates[last] = crate;
methods[last++] = methods[i];
}
}
}
methodLength = last;
} else if (methodLength == 1 && methods[0].GetParameters().Length != length) {
methodLength = 0;
}
// At this time, we should be left with only one method.
// Of course, realistically, we can be left with plenty of methods, if there are lots of variants with IConvertible
// But at this time we still aren't rating the best methods
// FIXME rate best methods
if (methodLength == 0)
throw "Invalid calling parameters for method " + methods[0].Name;
var best = cs.system.Double.PositiveInfinity;
var bestMethod = 0;
for (i in 0...methodLength) {
if (rates[i] < best) {
bestMethod = i;
best = rates[i];
}
}
methods[0] = methods[bestMethod];
var params = methods[0].GetParameters();
for (i in 0...params.Length) {
var param = params[i].ParameterType;
var strParam = param + "", arg = oargs[i];
if (StringTools.startsWith(strParam, "haxe.lang.Null")) {
oargs[i] = mkNullable(arg, param);
} else if (cast(untyped __typeof__(IConvertible), Type).IsAssignableFrom(param)) {
if (arg == null) {
if (param.IsValueType)
oargs[i] = Activator.CreateInstance(param);
} else if (!cs.Lib.getNativeType(arg).IsAssignableFrom(param)) {
oargs[i] = cast(arg, IConvertible).ToType(param, null);
}
}
}
if (methods[0].ContainsGenericParameters && Std.isOfType(methods[0], cs.system.reflection.MethodInfo)) {
var m:MethodInfo = cast methods[0];
var tgs = m.GetGenericArguments();
for (i in 0...tgs.Length) {
tgs[i] = untyped __typeof__(Dynamic);
}
m = m.MakeGenericMethod(tgs);
var retg = try
m.Invoke(obj, oargs)
catch(e:TargetInvocationException)
throw e.InnerException;
return cs.internal.Runtime.unbox(retg);
}
var m = methods[0];
if (obj == null && Std.isOfType(m, cs.system.reflection.ConstructorInfo)) {
var ret = try
cast(m, cs.system.reflection.ConstructorInfo).Invoke(oargs)
catch(e:TargetInvocationException)
throw e.InnerException;
return unbox(ret);
}
var ret = try
m.Invoke(obj, oargs)
catch(e:TargetInvocationException)
throw e.InnerException;
return unbox(ret);
}
public static function unbox(dyn:Dynamic):Dynamic {
if (dyn != null && untyped (Lib.getNativeType(dyn) + "").StartsWith("haxe.lang.Null")) {
return dyn.toDynamic();
} else {
return dyn;
}
}
#if !erase_generics
@:functionCode('
if (nullableType.ContainsGenericParameters)
return haxe.lang.Null<object>.ofDynamic<object>(obj);
return nullableType.GetMethod("_ofDynamic").Invoke(null, new object[] { obj });
')
public static function mkNullable(obj:Dynamic, nullableType:Type):Dynamic {
return null;
}
#else
public static function mkNullable(obj:Dynamic, nullable:Type):Dynamic {
return obj; // do nothing
}
#end
public static function slowCallField(obj:Dynamic, field:String, args:cs.NativeArray<Dynamic>):Dynamic {
if (field == "toString" && (args == null || args.length == 0)) {
return obj.ToString();
}
if (args == null)
args = new cs.NativeArray(0);
var bf:BindingFlags;
var t = Lib.as(obj, cs.system.Type);
if (t == null) {
var s = Lib.as(obj, String);
if (s != null)
return cs.internal.StringExt.StringRefl.handleCallField(untyped s, untyped field, args);
t = untyped obj.GetType();
bf = new Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy;
} else {
if (t == Lib.toNativeType(String) && field == 'fromCharCode')
return cs.internal.StringExt.fromCharCode(toInt(args[0]));
obj = null;
bf = new Flags(BindingFlags.Static) | BindingFlags.Public;
}
var mis:NativeArray<MethodBase> = untyped t.GetMethods(bf);
var last = 0;
for (i in 0...mis.Length) {
var name = mis[i].Name;
if (name == field)
mis[last++] = mis[i];
}
if (last == 0 && (field == "__get" || field == "__set")) {
field = field == "__get" ? "get_Item" : "set_Item";
for (i in 0...mis.Length) {
var name = mis[i].Name;
if (name == field) {
mis[last++] = mis[i];
}
}
}
if (last == 0 && t.IsCOMObject)
return t.InvokeMember(field, BindingFlags.InvokeMethod, null, obj, args);
if (last == 0) {
throw 'Method "$field" not found on type $t';
}
return Runtime.callMethod(obj, mis, last, args);
}
public static function callField(obj:Dynamic, field:String, fieldHash:Int, args:cs.NativeArray<Dynamic>):Dynamic {
var hxObj = Lib.as(obj, HxObject);
if (hxObj != null)
return untyped hxObj.__hx_invokeField(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, args);
return slowCallField(obj, field, args);
}
public static function getField(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Dynamic {
var hxObj = Lib.as(obj, HxObject);
if (hxObj != null)
return untyped hxObj.__hx_getField(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, throwErrors, false, false);
return slowGetField(obj, field, throwErrors);
}
public static function getField_f(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Float {
var hxObj = Lib.as(obj, HxObject);
if (hxObj != null)
return untyped hxObj.__hx_getField_f(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, throwErrors, false);
return toDouble(slowGetField(obj, field, throwErrors));
}
public static function setField(obj:Dynamic, field:String, fieldHash:Int, value:Dynamic):Dynamic {
var hxObj = Lib.as(obj, HxObject);
if (hxObj != null)
return untyped hxObj.__hx_setField(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, value, false);
return slowSetField(obj, field, value);
}
public static function setField_f(obj:Dynamic, field:String, fieldHash:Int, value:Float):Float {
var hxObj = Lib.as(obj, HxObject);
if (hxObj != null)
return untyped hxObj.__hx_setField_f(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, value, false);
return toDouble(slowSetField(obj, field, value));
}
public static function toString(obj:Dynamic):String {
if (obj == null)
return null;
if (Std.isOfType(obj, Bool))
if (obj)
return "true";
else
return "false";
return untyped obj.ToString();
}
#if erase_generics
inline
#end
public static function typeEq(t1:Type, t2:Type):Bool {
if (t1 == null || t2 == null)
return t1 == t2;
#if !erase_generics
var t1i = t1.IsInterface, t2i = t2.IsInterface;
if (t1i != t2i) {
if (t1i) {
var g = getGenericAttr(t1);
if (g != null)
t1 = g.generic;
} else {
var g = getGenericAttr(t2);
if (g != null)
t2 = g.generic;
}
}
#end
if (t1.GetGenericArguments().Length > 0)
t1 = t1.GetGenericTypeDefinition();
if (t2.GetGenericArguments().Length > 0)
t2 = t2.GetGenericTypeDefinition();
return Object.ReferenceEquals(t1, t2);
}
#if !erase_generics
public static function getGenericAttr(t:cs.system.Type):cs.internal.HxObject.GenericInterface {
for (attr in t.GetCustomAttributes(true))
if (Std.isOfType(attr, cs.internal.HxObject.GenericInterface))
return cast attr;
return null;
}
#end
#if !erase_generics
@:functionCode('
if (obj is To)
return (To) obj;
else if (obj == null)
return default(To);
if (typeof(To) == typeof(double))
return (To)(object) toDouble(obj);
else if (typeof(To) == typeof(int))
return (To)(object) toInt(obj);
else if (typeof(To) == typeof(float))
return (To)(object)(float)toDouble(obj);
else if (typeof(To) == typeof(long))
return (To)(object)(long)toDouble(obj);
else
return (To) obj;
')
public static function genericCast<To>(obj:Dynamic):To {
return null;
}
#end
@:functionCode('
return (s1 == null ? "null" : s1) + (s2 == null ? "null" : s2);
')
public static function concat(s1:String, s2:String):String {
return null;
}
public static function toBool(dyn:Dynamic):Bool {
return if (dyn == null) false else untyped __cs__("(bool){0}", dyn);
}
// TODO: change from genericCast to getConverter, so we don't need to handle extra boxing associated with it
/*@:functionCode('
if (typeof(To).TypeHandle == typeof(double).TypeHandle)
return (System.Converter<object,To>) new System.Converter<object,double>(toDouble);
else if (typeof(To).TypeHandle == typeof(double).TypeHandle)
return (System.Converter<object,To>) new System.Converter<object,double>(toDouble);
else
return (System.Converter<object, To>) delegate(object obj) { return (To) obj; };
')
public static function getConverter<To>():cs.system.Converter<Dynamic,To>
{
return null;
}*/
}
@:nativeGen
@:keep @:native("haxe.lang.EmptyObject") enum EmptyObject {
EMPTY;
}

View File

@ -0,0 +1,223 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package cs.internal;
import cs.internal.Function;
private typedef NativeString = cs.system.String;
@:keep @:nativeGen @:native("haxe.lang.StringExt") class StringExt {
@:readOnly static var empty(default, never) = new NativeString(cast 0, 0);
public static function charAt(me:NativeString, index:Int):NativeString {
if (cast(index, UInt) >= me.Length)
return empty;
else
return new NativeString(me[index], 1);
}
public static function charCodeAt(me:NativeString, index:Int):Null<Int> {
if (cast(index, UInt) >= me.Length)
return null;
else
return cast(me[index], Int);
}
public static function indexOf(me:NativeString, str:String, ?startIndex:Int):Int {
var sIndex:Int = startIndex != null ? startIndex : 0;
if(str == '') {
if(sIndex < 0) {
sIndex = me.Length + sIndex;
if(sIndex < 0) sIndex = 0;
}
return sIndex > me.Length ? me.Length : sIndex;
}
if (sIndex >= me.Length)
return -1;
return @:privateAccess me.IndexOf(str, sIndex, cs.system.StringComparison.Ordinal);
}
public static function lastIndexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int {
var sIndex:Int = startIndex == null ? me.Length - 1 : startIndex;
if (sIndex >= me.Length)
sIndex = me.Length - 1;
else if (sIndex < 0)
return -1;
if (str.Length == 0) {
return startIndex == null || startIndex > me.Length ? me.Length : startIndex;
}
// TestBaseTypes.hx@133 fix
if (startIndex != null) {
// if the number of letters between start index and the length of the string
// is less than the length of a searched substring - shift start index to the
// left by the difference to avoid OOB access later and save some work
var d = me.Length - sIndex - str.Length;
if (d < 0) {
sIndex += d;
}
var i = sIndex + 1;
while (i-- > 0) {
var found = true;
for (j in 0...str.Length) {
if (me[i + j] != str[j]) {
found = false;
break;
}
}
if (found)
return i;
}
return -1;
} else {
return me.LastIndexOf(untyped str, sIndex, cs.system.StringComparison.Ordinal);
}
return -1;
}
public static function split(me:NativeString, delimiter:NativeString):Array<String> {
var native:NativeArray<String>;
if (delimiter.Length == 0) {
var len = me.Length;
native = new NativeArray(len);
for (i in 0...len)
native[i] = untyped new NativeString(me[i], 1);
} else {
var str = new NativeArray<String>(1);
str[0] = cast delimiter;
native = me.Split(str, cs.system.StringSplitOptions.None);
}
return cs.Lib.array(native);
}
public static function substr(me:NativeString, pos:Int, ?len:Int):String {
var meLen = me.Length;
var targetLen = meLen;
if (len != null) {
targetLen = len;
if (targetLen == 0 || (pos != 0 && targetLen < 0))
return "";
}
if (pos < 0) {
pos = meLen + pos;
if (pos < 0)
pos = 0;
} else if (targetLen < 0) {
targetLen = meLen + targetLen - pos;
}
if (pos + targetLen > meLen) {
targetLen = meLen - pos;
}
if (pos < 0 || targetLen <= 0)
return "";
return me.Substring(pos, targetLen);
}
public static function substring(me:NativeString, startIndex:Int, ?endIndex:Int):String {
var len = me.Length;
var endIdx:Int;
if (endIndex == null)
endIdx = len;
else if ((endIdx = endIndex) < 0)
endIdx = 0;
else if (endIdx > len)
endIdx = len;
if (startIndex < 0)
startIndex = 0;
else if (startIndex > len)
startIndex = len;
if (startIndex > endIdx) {
var tmp = startIndex;
startIndex = endIdx;
endIdx = tmp;
}
return me.Substring(startIndex, endIdx - startIndex);
}
public static function toString(me:NativeString):NativeString {
return me;
}
public static function toLowerCase(me:NativeString):String {
return me.ToLowerInvariant();
}
public static function toUpperCase(me:NativeString):String {
return me.ToUpperInvariant();
}
public static function toNativeString(me:NativeString):NativeString {
return me;
}
public static function fromCharCode(code:Int):String {
return cs.system.Char.ConvertFromUtf32(code);
// return new NativeString( cast(code,cs.StdTypes.Char16), 1 );
}
}
@:keep @:nativeGen @:native('haxe.lang.StringRefl') class StringRefl {
public static var fields = [
"length", "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring"
];
public static function handleGetField(str:String, f:String, throwErrors:Bool):Dynamic {
switch (f) {
case "length":
return str.length;
case "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring":
return new Closure(str, f, 0);
default:
if (throwErrors)
throw "Field not found: '" + f + "' in String";
else
return null;
}
}
public static function handleCallField(str:NativeString, f:String, args:cs.NativeArray<Dynamic>):Dynamic {
var _args:cs.NativeArray<Dynamic>;
if (args == null) {
_args = cs.NativeArray.make(str);
} else {
_args = new cs.NativeArray(args.length + 1);
for (i in 0...args.length)
_args[i + 1] = args[i];
_args[0] = str;
}
return Runtime.slowCallField(StringExt, f, _args);
}
}