From ed0f6b278ad993da9e48237bbd23517a73e22e22 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 5 Jun 2020 21:11:22 +0900 Subject: [PATCH 1/7] apply patch: NativeString will search String's method --- src/org/mozilla/javascript/NativeString.java | 54 ++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/org/mozilla/javascript/NativeString.java b/src/org/mozilla/javascript/NativeString.java index ca5d3b7eb4..8c3fcba206 100644 --- a/src/org/mozilla/javascript/NativeString.java +++ b/src/org/mozilla/javascript/NativeString.java @@ -12,6 +12,7 @@ import java.text.Collator; import java.text.Normalizer; import java.util.Locale; +import java.util.function.Function; import org.mozilla.javascript.regexp.NativeRegExp; @@ -126,6 +127,59 @@ protected void fillConstructorProperties(IdFunctionObject ctor) super.fillConstructorProperties(ctor); } + // ================================ fixRTM patch start ================================ + + @Override + public Object get(String name, Scriptable start) { + Object result = super.get(name, start); + if (result != NOT_FOUND) return result; + // get ctx + Context ctx = Context.getCurrentContext(); + if (ctx == null) return NOT_FOUND; + // get by object + result = ctx.getWrapFactory().wrapNewObject(ctx, ScriptableObject.getTopLevelScope(start), "") + .get(name, start); + if (result instanceof NativeJavaMethod) { + return new WrappedNativeFunction((NativeJavaMethod) result, + (obj) -> obj instanceof NativeString ? ((NativeString) obj).toCharSequence().toString() : null); + } + return result; + } + + private static class WrappedNativeFunction extends NativeJavaMethod { + private final NativeJavaMethod javaMethod; + private final Function unwrap; + + WrappedNativeFunction(NativeJavaMethod javaMethod, Function unwrap) { + super(javaMethod.methods, javaMethod.getFunctionName()); + this.javaMethod = javaMethod; + this.unwrap = unwrap; + } + + @Override + public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { + if (scope == null) + return javaMethod.call(cx, scope, thisObj, args); + + Object unwrapped = unwrap.apply(scope); + if (unwrapped instanceof Scriptable) + return javaMethod.call(cx, (Scriptable) unwrapped, thisObj, args); + if (unwrapped == null) + return javaMethod.call(cx, scope, thisObj, args); + + scope = cx.getWrapFactory().wrapNewObject(cx, ScriptableObject.getTopLevelScope(scope), unwrapped); + + return javaMethod.call(cx, scope, thisObj, args); + } + + @Override + public Object getDefaultValue(Class typeHint) { + return javaMethod.getDefaultValue(typeHint); + } + } + + // ================================ fixRTM patch end ================================ + @Override protected void initPrototypeId(int id) { From bea209ea9c8826e260df5e2b2b3da8e0f9f1fe31 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 5 Jun 2020 21:31:10 +0900 Subject: [PATCH 2/7] apply patch: decompile() for compiled script, should return raw script --- .../mozilla/javascript/NativeFunction.java | 14 +++++++ .../javascript/optimizer/ClassCompiler.java | 6 +++ .../mozilla/javascript/optimizer/Codegen.java | 37 ++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/org/mozilla/javascript/NativeFunction.java b/src/org/mozilla/javascript/NativeFunction.java index 97e5b05ba0..3f58474df5 100644 --- a/src/org/mozilla/javascript/NativeFunction.java +++ b/src/org/mozilla/javascript/NativeFunction.java @@ -23,6 +23,15 @@ public final void initScriptFunction(Context cx, Scriptable scope) ScriptRuntime.setFunctionProtoAndParent(this, scope); } + // ================================ fixRTM patch start ================================ + // for compiled script, should return raw script + + public String decompileRaw() { + return null; + } + + // ================================ fixRTM patch end ================================ + /** * @param indent How much to indent the decompiled result * @@ -31,6 +40,11 @@ public final void initScriptFunction(Context cx, Scriptable scope) @Override final String decompile(int indent, int flags) { + if (indent == 0 && flags == 0) { + String raw = decompileRaw(); + if (raw != null) + return raw; + } String encodedSource = getEncodedSource(); if (encodedSource == null) { return super.decompile(indent, flags); diff --git a/src/org/mozilla/javascript/optimizer/ClassCompiler.java b/src/org/mozilla/javascript/optimizer/ClassCompiler.java index d7c78ad376..266b88a630 100644 --- a/src/org/mozilla/javascript/optimizer/ClassCompiler.java +++ b/src/org/mozilla/javascript/optimizer/ClassCompiler.java @@ -156,6 +156,12 @@ public Object[] compileToClassFiles(String source, } Codegen codegen = new Codegen(); + + // ================================ fixRTM patch start ================================ + // for compiled script, should return raw script + codegen.sourceString = source; + // ================================ fixRTM patch end ================================ + codegen.setMainMethodClass(mainMethodClassName); byte[] scriptClassBytes = codegen.compileToClassFile(compilerEnv, scriptClassName, diff --git a/src/org/mozilla/javascript/optimizer/Codegen.java b/src/org/mozilla/javascript/optimizer/Codegen.java index f1f2b79f96..c20f63d9f2 100644 --- a/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/src/org/mozilla/javascript/optimizer/Codegen.java @@ -743,6 +743,13 @@ private void generateFunctionInit(ClassFileWriter cfw, cfw.stopMethod((short)3); } + // ================================ fixRTM patch start ================================ + // for compiled script, should return raw script + // no end comment. and commented for each canges + + // add sourceString + String sourceString; + private void generateNativeFunctionOverrides(ClassFileWriter cfw, String encodedSource) { @@ -766,13 +773,20 @@ private void generateNativeFunctionOverrides(ClassFileWriter cfw, final int Do_getParamOrVarName = 3; final int Do_getEncodedSource = 4; final int Do_getParamOrVarConst = 5; - final int SWITCH_COUNT = 6; + // add Do_decompileRaw + final int Do_decompileRaw = 6; + final int SWITCH_COUNT = 7; for (int methodIndex = 0; methodIndex != SWITCH_COUNT; ++methodIndex) { if (methodIndex == Do_getEncodedSource && encodedSource == null) { continue; } + // add condition for Do_decompileRaw + if (methodIndex == Do_decompileRaw && sourceString == null) { + continue; + } + // Generate: // prologue; // switch over function id to implement function-specific action @@ -811,6 +825,15 @@ private void generateNativeFunctionOverrides(ClassFileWriter cfw, ACC_PUBLIC); cfw.addPush(encodedSource); break; + + // add for Do_decompileRaw + case Do_decompileRaw: + methodLocals = 1; // Only this + cfw.startMethod("decompileRaw", "()Ljava/lang/String;", + ACC_PUBLIC); + cfw.addPush(sourceString); + break; + default: throw Kit.codeBug(); } @@ -951,6 +974,18 @@ private void generateNativeFunctionOverrides(ClassFileWriter cfw, "substring", "(II)Ljava/lang/String;"); cfw.add(ByteCode.ARETURN); + + // add for Do_decompileRaw + case Do_decompileRaw: + // Push number encoded source start and end + // to prepare for encodedSource.substring(start, end) + cfw.addPush(n.getAbsolutePosition()); + cfw.addPush(n.getAbsolutePosition() + n.getLength()); + cfw.addInvoke(ByteCode.INVOKEVIRTUAL, + "java/lang/String", + "substring", + "(II)Ljava/lang/String;"); + cfw.add(ByteCode.ARETURN); break; default: From 05d285a24a2d29f2b0255d335430d6f1f9d16a3e Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 5 Jun 2020 21:38:28 +0900 Subject: [PATCH 3/7] apply patch: Packages.some.Class.class should return java.lang.Class Object --- src/org/mozilla/javascript/NativeJavaClass.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/org/mozilla/javascript/NativeJavaClass.java b/src/org/mozilla/javascript/NativeJavaClass.java index 39316f8923..9e9bb28ca7 100644 --- a/src/org/mozilla/javascript/NativeJavaClass.java +++ b/src/org/mozilla/javascript/NativeJavaClass.java @@ -30,9 +30,16 @@ public class NativeJavaClass extends NativeJavaObject implements Function { private static final long serialVersionUID = -6460763940409461664L; + // ================================ fixRTM patch start ================================ + // Packages.some.Class.class should return java.lang.Class Object + // no end comment. and commented for each canges + // Special property for getting the underlying Java class object. static final String javaClassPropertyName = "__javaObject__"; + // add javaClassPropertyName2 + static final String javaClassPropertyName2 = "class"; + public NativeJavaClass() { } @@ -58,7 +65,9 @@ public String getClassName() { @Override public boolean has(String name, Scriptable start) { - return members.has(name, true) || javaClassPropertyName.equals(name); + // add condition for javaClassPropertyName2 + return members.has(name, true) || javaClassPropertyName.equals(name) + || javaClassPropertyName2.equals(name); } @Override @@ -84,7 +93,8 @@ public Object get(String name, Scriptable start) { Scriptable scope = ScriptableObject.getTopLevelScope(start); WrapFactory wrapFactory = cx.getWrapFactory(); - if (javaClassPropertyName.equals(name)) { + // add condition for javaClassPropertyName2 + if (javaClassPropertyName.equals(name) || javaClassPropertyName2.equals(name)) { return wrapFactory.wrap(cx, scope, javaObject, ScriptRuntime.ClassClass); } From 4418156a162807241eb94228a892a9737944444e Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sun, 7 Jun 2020 12:00:17 +0900 Subject: [PATCH 4/7] remove patch comment --- src/org/mozilla/javascript/NativeFunction.java | 5 ----- src/org/mozilla/javascript/NativeJavaClass.java | 7 ------- src/org/mozilla/javascript/NativeString.java | 4 ---- src/org/mozilla/javascript/optimizer/ClassCompiler.java | 4 +--- src/org/mozilla/javascript/optimizer/Codegen.java | 6 +----- 5 files changed, 2 insertions(+), 24 deletions(-) diff --git a/src/org/mozilla/javascript/NativeFunction.java b/src/org/mozilla/javascript/NativeFunction.java index 3f58474df5..618de2470e 100644 --- a/src/org/mozilla/javascript/NativeFunction.java +++ b/src/org/mozilla/javascript/NativeFunction.java @@ -23,15 +23,10 @@ public final void initScriptFunction(Context cx, Scriptable scope) ScriptRuntime.setFunctionProtoAndParent(this, scope); } - // ================================ fixRTM patch start ================================ - // for compiled script, should return raw script - public String decompileRaw() { return null; } - // ================================ fixRTM patch end ================================ - /** * @param indent How much to indent the decompiled result * diff --git a/src/org/mozilla/javascript/NativeJavaClass.java b/src/org/mozilla/javascript/NativeJavaClass.java index 9e9bb28ca7..d23e4c2b9c 100644 --- a/src/org/mozilla/javascript/NativeJavaClass.java +++ b/src/org/mozilla/javascript/NativeJavaClass.java @@ -30,14 +30,9 @@ public class NativeJavaClass extends NativeJavaObject implements Function { private static final long serialVersionUID = -6460763940409461664L; - // ================================ fixRTM patch start ================================ - // Packages.some.Class.class should return java.lang.Class Object - // no end comment. and commented for each canges - // Special property for getting the underlying Java class object. static final String javaClassPropertyName = "__javaObject__"; - // add javaClassPropertyName2 static final String javaClassPropertyName2 = "class"; public NativeJavaClass() { @@ -65,7 +60,6 @@ public String getClassName() { @Override public boolean has(String name, Scriptable start) { - // add condition for javaClassPropertyName2 return members.has(name, true) || javaClassPropertyName.equals(name) || javaClassPropertyName2.equals(name); } @@ -93,7 +87,6 @@ public Object get(String name, Scriptable start) { Scriptable scope = ScriptableObject.getTopLevelScope(start); WrapFactory wrapFactory = cx.getWrapFactory(); - // add condition for javaClassPropertyName2 if (javaClassPropertyName.equals(name) || javaClassPropertyName2.equals(name)) { return wrapFactory.wrap(cx, scope, javaObject, ScriptRuntime.ClassClass); diff --git a/src/org/mozilla/javascript/NativeString.java b/src/org/mozilla/javascript/NativeString.java index 8c3fcba206..9b02a2a4b5 100644 --- a/src/org/mozilla/javascript/NativeString.java +++ b/src/org/mozilla/javascript/NativeString.java @@ -127,8 +127,6 @@ protected void fillConstructorProperties(IdFunctionObject ctor) super.fillConstructorProperties(ctor); } - // ================================ fixRTM patch start ================================ - @Override public Object get(String name, Scriptable start) { Object result = super.get(name, start); @@ -178,8 +176,6 @@ public Object getDefaultValue(Class typeHint) { } } - // ================================ fixRTM patch end ================================ - @Override protected void initPrototypeId(int id) { diff --git a/src/org/mozilla/javascript/optimizer/ClassCompiler.java b/src/org/mozilla/javascript/optimizer/ClassCompiler.java index 266b88a630..441b5ca986 100644 --- a/src/org/mozilla/javascript/optimizer/ClassCompiler.java +++ b/src/org/mozilla/javascript/optimizer/ClassCompiler.java @@ -157,10 +157,8 @@ public Object[] compileToClassFiles(String source, Codegen codegen = new Codegen(); - // ================================ fixRTM patch start ================================ - // for compiled script, should return raw script + // to know real source code codegen.sourceString = source; - // ================================ fixRTM patch end ================================ codegen.setMainMethodClass(mainMethodClassName); byte[] scriptClassBytes diff --git a/src/org/mozilla/javascript/optimizer/Codegen.java b/src/org/mozilla/javascript/optimizer/Codegen.java index c20f63d9f2..031147b1de 100644 --- a/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/src/org/mozilla/javascript/optimizer/Codegen.java @@ -743,11 +743,7 @@ private void generateFunctionInit(ClassFileWriter cfw, cfw.stopMethod((short)3); } - // ================================ fixRTM patch start ================================ - // for compiled script, should return raw script - // no end comment. and commented for each canges - - // add sourceString + // to kwnow real source code String sourceString; private void generateNativeFunctionOverrides(ClassFileWriter cfw, From b1f3838b79cd3ffc165b49fea279b3dadb07f3ae Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sun, 7 Jun 2020 12:20:59 +0900 Subject: [PATCH 5/7] fix bugs --- src/org/mozilla/javascript/NativeString.java | 9 +++++---- src/org/mozilla/javascript/optimizer/Codegen.java | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/org/mozilla/javascript/NativeString.java b/src/org/mozilla/javascript/NativeString.java index 9b02a2a4b5..f5240da27f 100644 --- a/src/org/mozilla/javascript/NativeString.java +++ b/src/org/mozilla/javascript/NativeString.java @@ -131,6 +131,7 @@ protected void fillConstructorProperties(IdFunctionObject ctor) public Object get(String name, Scriptable start) { Object result = super.get(name, start); if (result != NOT_FOUND) return result; + if (name == "toString") return NOT_FOUND; // get ctx Context ctx = Context.getCurrentContext(); if (ctx == null) return NOT_FOUND; @@ -156,16 +157,16 @@ private static class WrappedNativeFunction extends NativeJavaMethod { @Override public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { - if (scope == null) + if (thisObj == null) return javaMethod.call(cx, scope, thisObj, args); - Object unwrapped = unwrap.apply(scope); + Object unwrapped = unwrap.apply(thisObj); if (unwrapped instanceof Scriptable) - return javaMethod.call(cx, (Scriptable) unwrapped, thisObj, args); + return javaMethod.call(cx, scope, (Scriptable) unwrapped, args); if (unwrapped == null) return javaMethod.call(cx, scope, thisObj, args); - scope = cx.getWrapFactory().wrapNewObject(cx, ScriptableObject.getTopLevelScope(scope), unwrapped); + thisObj = cx.getWrapFactory().wrapNewObject(cx, ScriptableObject.getTopLevelScope(scope), unwrapped); return javaMethod.call(cx, scope, thisObj, args); } diff --git a/src/org/mozilla/javascript/optimizer/Codegen.java b/src/org/mozilla/javascript/optimizer/Codegen.java index 031147b1de..815b263b48 100644 --- a/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/src/org/mozilla/javascript/optimizer/Codegen.java @@ -970,10 +970,11 @@ private void generateNativeFunctionOverrides(ClassFileWriter cfw, "substring", "(II)Ljava/lang/String;"); cfw.add(ByteCode.ARETURN); + break; // add for Do_decompileRaw case Do_decompileRaw: - // Push number encoded source start and end + // Push number source start and end // to prepare for encodedSource.substring(start, end) cfw.addPush(n.getAbsolutePosition()); cfw.addPush(n.getAbsolutePosition() + n.getLength()); From 37654e20d2921df1d609b527d7f415f6b1773ab7 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sun, 7 Jun 2020 12:47:11 +0900 Subject: [PATCH 6/7] add change notice to readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d5ca09388a..8974a7b124 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ Rhino is an implementation of JavaScript in Java. ## This repository is a fork of rhino for [fixRTM](https://github.com/anatawa12/fixRTM) Here is the list of difference from the original Rhino: +- NativeString will search String's method. +- toString for function return real function source code. +- Packages.some.Class.class should return java.lang.Class Object. ## License From 006f08efb0d9ffacc8ccead9d9cf70d07f5d8d2a Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sun, 7 Jun 2020 14:07:35 +0900 Subject: [PATCH 7/7] fix bug --- src/org/mozilla/javascript/NativeString.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/org/mozilla/javascript/NativeString.java b/src/org/mozilla/javascript/NativeString.java index f5240da27f..989dbbf0be 100644 --- a/src/org/mozilla/javascript/NativeString.java +++ b/src/org/mozilla/javascript/NativeString.java @@ -11,7 +11,10 @@ import java.text.Collator; import java.text.Normalizer; +import java.util.Arrays; +import java.util.HashSet; import java.util.Locale; +import java.util.Set; import java.util.function.Function; import org.mozilla.javascript.regexp.NativeRegExp; @@ -131,7 +134,7 @@ protected void fillConstructorProperties(IdFunctionObject ctor) public Object get(String name, Scriptable start) { Object result = super.get(name, start); if (result != NOT_FOUND) return result; - if (name == "toString") return NOT_FOUND; + if (StringMethod_names.contains(name)) return NOT_FOUND; // get ctx Context ctx = Context.getCurrentContext(); if (ctx == null) return NOT_FOUND; @@ -145,6 +148,15 @@ public Object get(String name, Scriptable start) { return result; } + private static final Set StringMethod_names = new HashSet<>(Arrays.asList( + "charAt", "charCodeAt", "codePointAt", "concat", "includes", "endsWith", "indexOf", "lastIndexOf", + "localeCompare", "match", "normalize", "padEnd", "padStart", "quote", "repeat", "replace", "search", + "slice", "split", "startsWith", "substr", "substring", "toLocaleLowerCase", "toLocaleUpperCase", + "toLowerCase", "toSource", "toUpperCase", "trim", "trimStart", "trimLeft", "trimEnd", + "trimRight", "anchor", "big", "blink", "bold", "fixed", "fontcolor", "fontsize", "italics", + "link", "small", "strike", "sub", "sup", "toString", "valueOf" + )); + private static class WrappedNativeFunction extends NativeJavaMethod { private final NativeJavaMethod javaMethod; private final Function unwrap;