Skip to content

Commit

Permalink
Added generic parsing, rewrote how arrays are parsed
Browse files Browse the repository at this point in the history
  • Loading branch information
LatvianModder committed May 18, 2024
1 parent ccb8236 commit 6eb4d4c
Show file tree
Hide file tree
Showing 30 changed files with 911 additions and 967 deletions.
730 changes: 602 additions & 128 deletions src/main/java/dev/latvian/mods/rhino/Context.java

Large diffs are not rendered by default.

104 changes: 38 additions & 66 deletions src/main/java/dev/latvian/mods/rhino/NativeArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -407,86 +407,58 @@ private static void setRawElem(Context cx, Scriptable target, long index, Object
private static String toStringHelper(Context cx, Scriptable scope, Scriptable thisObj, boolean toLocale) {
Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj);

/* It's probably redundant to handle long lengths in this
* function; StringBuilders are limited to 2^31 in java.
*/
long length = getLengthProperty(cx, o, false);
int length = (int) getLengthProperty(cx, o, false);

StringBuilder result = new StringBuilder(256);

// whether to return '4,unquoted,5' or '[4, "quoted", 5]'
String separator;
if (length == 0) {
return "[]";
}

separator = ",";
StringBuilder result = new StringBuilder(256);
result.append('[');

boolean haslast = false;
long i = 0;
// make toSource print null and undefined values in recent versions
for (int i = 0; i < length; i++) {
if (i > 0) {
result.append(", ");
}
Object elem = getRawElem(o, i, cx);
if (elem == NOT_FOUND || elem == null || elem == Undefined.INSTANCE) {
continue;
}

boolean toplevel, iterating;
if (cx.iterating == null) {
toplevel = true;
iterating = false;
cx.iterating = new ObjToIntMap(31);
} else {
toplevel = false;
iterating = cx.iterating.has(o);
result.append(ScriptRuntime.uneval(cx, scope, elem));
}

// Make sure cx.iterating is set to null when done
// so we don't leak memory
try {
if (!iterating) {
// stop recursion
cx.iterating.put(o, 0);
result.append(']');

// make toSource print null and undefined values in recent versions
for (i = 0; i < length; i++) {
if (i > 0) {
result.append(separator);
}
Object elem = getRawElem(o, i, cx);
if (elem == NOT_FOUND || elem == null || elem == Undefined.INSTANCE) {
haslast = false;
continue;
}
haslast = true;
return result.toString();
}

if (false) {
result.append(ScriptRuntime.uneval(cx, scope, elem));
private static String toSource(Context cx, Scriptable scope, Scriptable thisObj) {
Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj);

} else if (elem instanceof String) {
result.append((String) elem);
int length = (int) getLengthProperty(cx, o, false);

} else {
if (toLocale) {
Callable fun;
Scriptable funThis;
fun = ScriptRuntime.getPropFunctionAndThis(cx, scope, elem, "toLocaleString");
funThis = cx.lastStoredScriptable();
elem = fun.call(cx, scope, funThis, ScriptRuntime.EMPTY_OBJECTS);
}
result.append(ScriptRuntime.toString(cx, elem));
}
}
if (length == 0) {
return "[]";
}

StringBuilder result = new StringBuilder(256);
result.append('[');

// processing of thisObj done, remove it from the recursion detector
// to allow thisObj to be again in the array later on
cx.iterating.remove(o);
for (int i = 0; i < length; i++) {
if (i > 0) {
result.append(", ");
}
} finally {
if (toplevel) {
cx.iterating = null;
Object elem = getRawElem(o, i, cx);
if (elem == NOT_FOUND || elem == null || elem == Undefined.INSTANCE) {
continue;
}
}

if (false) {
//for [,,].length behavior; we want toString to be symmetric.
if (!haslast && i > 0) {
result.append(", ]");
} else {
result.append(']');
}
result.append(ScriptRuntime.uneval(cx, scope, elem));
}

result.append(']');
return result.toString();
}

Expand Down Expand Up @@ -1741,7 +1713,7 @@ public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scrip
return toStringHelper(cx, scope, thisObj, true);

case Id_toSource:
return "not_supported";
return toSource(cx, scope, thisObj);

case Id_join:
return js_join(cx, scope, thisObj, args);
Expand Down
17 changes: 5 additions & 12 deletions src/main/java/dev/latvian/mods/rhino/NativeBoolean.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,11 @@ public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scrip
}
boolean value = ((NativeBoolean) thisObj).booleanValue;

switch (id) {

case Id_toString:
return value ? "true" : "false";

case Id_toSource:
return "not_supported";

case Id_valueOf:
return value;
}
throw new IllegalArgumentException(String.valueOf(id));
return switch (id) {
case Id_toString, Id_toSource -> value ? "true" : "false";
case Id_valueOf -> value;
default -> throw new IllegalArgumentException(String.valueOf(id));
};
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/latvian/mods/rhino/NativeDate.java
Original file line number Diff line number Diff line change
Expand Up @@ -1642,7 +1642,7 @@ public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scrip
return js_NaN_date_str;

case Id_toSource:
return "not_supported";
return "Date";

case Id_valueOf:
case Id_getTime:
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/latvian/mods/rhino/NativeError.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scrip
return js_toString(cx, thisObj);

case Id_toSource:
return "not_supported";
return "Error";

case ConstructorId_captureStackTrace:
js_captureStackTrace(cx, thisObj, args);
Expand Down
5 changes: 1 addition & 4 deletions src/main/java/dev/latvian/mods/rhino/NativeJavaClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,6 @@ private static Class<?> findNestedClass(Class<?> parentClass, String name) {

private Map<String, FieldAndMethods> staticFieldAndMethods;

public NativeJavaClass() {
}

public NativeJavaClass(Context cx, Scriptable scope, Class<?> cl) {
this(cx, scope, cl, false);
}
Expand Down Expand Up @@ -242,7 +239,7 @@ public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
// When running on Android create an InterfaceAdapter since our
// bytecode generation won't work on Dalvik VM.
if ("Dalvik".equals(System.getProperty("java.vm.name")) && classObject.isInterface()) {
Object obj = createInterfaceAdapter(cx, classObject, ScriptableObject.ensureScriptableObject(args[0], cx));
Object obj = cx.createInterfaceAdapter(classObject, classObject, ScriptableObject.ensureScriptableObject(args[0], cx));
return cx.wrapAsJavaObject(scope, obj, null, null);
}
// use JavaAdapter to construct a new class on the fly that
Expand Down
20 changes: 13 additions & 7 deletions src/main/java/dev/latvian/mods/rhino/NativeJavaMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.concurrent.CopyOnWriteArrayList;

/**
Expand Down Expand Up @@ -92,7 +93,7 @@ static int findFunction(Context cx, MemberBox[] methodsOrCtors, Object[] args) {
}
}
for (int j = 0; j != alength; ++j) {
if (!NativeJavaObject.canConvert(cx, args[j], member.argTypes[j])) {
if (!cx.canConvert(args[j], member.argTypes[j], member.genericArgTypes[j])) {
if (debug) {
printDebug("Rejecting (args can't convert) ", member, args);
}
Expand Down Expand Up @@ -124,7 +125,7 @@ static int findFunction(Context cx, MemberBox[] methodsOrCtors, Object[] args) {
}
}
for (int j = 0; j < alength; j++) {
if (!NativeJavaObject.canConvert(cx, args[j], member.argTypes[j])) {
if (!cx.canConvert(args[j], member.argTypes[j], member.genericArgTypes[j])) {
if (debug) {
printDebug("Rejecting (args can't convert) ", member, args);
}
Expand Down Expand Up @@ -153,7 +154,7 @@ static int findFunction(Context cx, MemberBox[] methodsOrCtors, Object[] args) {
bestFitIndex = extraBestFits[j];
}
MemberBox bestFit = methodsOrCtors[bestFitIndex];
int preference = preferSignature(cx, args, member.argTypes, member.vararg, bestFit.argTypes, bestFit.vararg);
int preference = preferSignature(cx, args, member.argTypes, member.genericArgTypes, member.vararg, bestFit.argTypes, bestFit.genericArgTypes, bestFit.vararg);
if (preference == PREFERENCE_AMBIGUOUS) {
break;
} else if (preference == PREFERENCE_FIRST_ARG) {
Expand Down Expand Up @@ -253,20 +254,25 @@ static int findFunction(Context cx, MemberBox[] methodsOrCtors, Object[] args) {
* Returns one of PREFERENCE_EQUAL, PREFERENCE_FIRST_ARG,
* PREFERENCE_SECOND_ARG, or PREFERENCE_AMBIGUOUS.
*/
private static int preferSignature(Context cx, Object[] args, Class<?>[] sig1, boolean vararg1, Class<?>[] sig2, boolean vararg2) {
private static int preferSignature(Context cx, Object[] args, Class<?>[] sig1, Type[] gsig1, boolean vararg1, Class<?>[] sig2, Type[] gsig2, boolean vararg2) {
int totalPreference = 0;
for (int j = 0; j < args.length; j++) {
Class<?> type1 = vararg1 && j >= sig1.length ? sig1[sig1.length - 1] : sig1[j];
Class<?> type2 = vararg2 && j >= sig2.length ? sig2[sig2.length - 1] : sig2[j];

if (type1 == type2) {
continue;
}

Type gType1 = vararg1 && j >= gsig1.length ? gsig1[gsig1.length - 1] : gsig1[j];
Type gType2 = vararg2 && j >= gsig2.length ? gsig2[gsig2.length - 1] : gsig2[j];

Object arg = args[j];

// Determine which of type1, type2 is easier to convert from arg.

int rank1 = NativeJavaObject.getConversionWeight(cx, arg, type1);
int rank2 = NativeJavaObject.getConversionWeight(cx, arg, type2);
int rank1 = cx.getConversionWeight(arg, type1, gType1);
int rank2 = cx.getConversionWeight(arg, type2, gType2);

int preference;
if (rank1 < rank2) {
Expand All @@ -275,7 +281,7 @@ private static int preferSignature(Context cx, Object[] args, Class<?>[] sig1, b
preference = PREFERENCE_SECOND_ARG;
} else {
// Equal ranks
if (rank1 == NativeJavaObject.CONVERSION_NONTRIVIAL) {
if (rank1 == Context.CONVERSION_NONTRIVIAL) {
if (type1.isAssignableFrom(type2)) {
preference = PREFERENCE_SECOND_ARG;
} else if (type2.isAssignableFrom(type1)) {
Expand Down
Loading

0 comments on commit 6eb4d4c

Please sign in to comment.