Closed Bug 202201 Opened 23 years ago Closed 23 years ago

java.lang.String insances passed into Rhino have the "replace" function defined, different from NativeString's NativeRegExp

Categories

(Rhino Graveyard :: Core, defect)

defect
Not set
normal

Tracking

(Not tracked)

VERIFIED INVALID

People

(Reporter: mpg, Assigned: norrisboyd)

Details

User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0) Build Identifier: Rhino 1.5R4 In JavaScript implementation in IE if you pass a java.lang.String into the scripting engine you can call "replace(<regexp>, <replaceString>)" on the string and it is well-defined. In Rhino 1.5R4 (and previous builds) the native String replace(char, char) will be invoked, causing a crash. It attempts to convert the arguments to char(s) which won't work. org.mozilla.javascript.EvaluatorException: Cannot convert TSY to java.lang.Character (jxmlbboard0; line 395) at org.mozilla.javascript.DefaultErrorReporter.runtimeError (DefaultErrorReporter.java:76) at org.mozilla.javascript.Context.reportRuntimeError(Context.java:594) at org.mozilla.javascript.Context.reportRuntimeError(Context.java:632) at org.mozilla.javascript.Context.reportRuntimeError2(Context.java:614) at org.mozilla.javascript.NativeJavaObject.reportConversionError (NativeJavaObject.java:856) at org.mozilla.javascript.NativeJavaObject.toInteger (NativeJavaObject.java:830) at org.mozilla.javascript.NativeJavaObject.coerceToNumber (NativeJavaObject.java:671) at org.mozilla.javascript.NativeJavaObject.coerceType (NativeJavaObject.java:560) at org.mozilla.javascript.NativeJavaMethod.call (NativeJavaMethod.java:213) at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:2181) at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:2163) at org.mozilla.javascript.InterpretedFunction.call (InterpretedFunction.java:58) Here is the call stack of a "healthy" call to replace defined on JavaScript Strings (NativeString instances). Notice that the NativeJavaMethod does not occur in the call stack: Thread [JSInterpreter Worker:1] (Suspended) Context.getRegExpProxy() line: 2077 NativeString.checkReProxy(Context) line: 258 NativeString.execMethod(int, IdFunction, Context, Scriptable, Scriptable, Object[]) line: 244 IdFunction.call(Context, Scriptable, Scriptable, Object[]) line: 78 // this is good, thinks it's a JavaScript String object Interpreter.interpret(Context, Scriptable, Scriptable, Object[], double [], int, int, NativeFunction, InterpreterData) line: 2169 InterpretedFunction.call(Context, Scriptable, Scriptable, Object[]) line: 58 JSInterpreter$4.run() line: 342 Worker.run() line: 221 Thread.run() line: 536 [local variables unavailable] Reproducible: Always Steps to Reproduce: 1. Call a javascript method by passing a java.lang.String instance obtained from the Java VM (any instance of String will do). 2. In the JavaScript method, call replace(/blah/gi, "bluh") on the passed in argument. 3. Watch the fireworks (detailed above). Actual Results: It failed as described above. Expected Results: I think that either I need some kind of hook to tell Mozilla to make all strings into NativeStrings (somehow) or the Interpreter::interpret function should catch the attempt to invoke replace(NativeRegExp, String) and perform the NativeString replace function instead (which picks up the regular expression). We need to be compatible with older versions of java so we can't use the jdk1.4 and later regular expression aware versions of java.lang.String.
cc'ing Igor -
This is a feature, if you want to have the same behavior as MSIE does, in your application after Context.enter call: cx.getWrapFactory().setJavaPrimitiveWrap(false);
Status: NEW → RESOLVED
Closed: 23 years ago
Resolution: --- → INVALID
Thanks, this does work. A couple of comments. Firstly the comments to the method org.mozilla.javascript.WrapFactory.isJavaPrimitiveWrap are a bit misleading. It appears that "wrapping" means "make this object look like a JavaScript object". In fact "wrapping" means "make this object look like what it is, namely, a Java primitive instance". In otherwords, you need to "wrap" it to keep it from appearing differently. In otherwords, in order to have Java primitive instances appear as javaScript primitive instances (so "replace", which is defined on java.lang.String, but has different param. types than the JavaScript String.replace(<regular expression>, <replace expression>)) you need to NOT wrap it. What you mean is "Set the javaPrimitiveWrap to false so it's NOT wrapped to be made to appear like a Java primitive type". In other words, "wrapping" a Java primitive type makes it continue to appear like a java primitive type. Quite confusing I'd say. So therefore, the default value should be: javaPrimitiveWrap = false But great job, guys! This is a great debugger and scripting engine. Outstanding.
Patches for documentation are welcome, but note that in the method JavaDoc "wrap" means: put the object inside LiveConnect envelope so JavaScript can access the same public fields and methods of the objects that a Java code can do. Correspondingly "do not wrap" means that the object will be replaced by a JavaScript primitive type. Note that "wrapping" does not affects methods returning int, float etc. They are always replaced by JavaScript primitive types. The issue is what to do when a method returns an instance of String or Number.
Marking Verified -
Status: RESOLVED → VERIFIED
Targeting as resolved against 1.5R5
Target Milestone: --- → 1.5R5
You need to log in before you can comment on or make changes to this bug.