Skip to content

Commit

Permalink
NativeJavaClass: Add class literal support
Browse files Browse the repository at this point in the history
  • Loading branch information
camnwalter committed Oct 5, 2024
1 parent d2e2921 commit 0ceaea0
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 3 deletions.
12 changes: 9 additions & 3 deletions rhino/src/main/java/org/mozilla/javascript/NativeJavaClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ public String getClassName() {

@Override
public boolean has(String name, Scriptable start) {
return members.has(name, true) || javaClassPropertyName.equals(name);
return members.has(name, true)
|| javaClassPropertyName.equals(name)
|| "class".equals(name);
}

@Override
Expand All @@ -69,14 +71,18 @@ public Object get(String name, Scriptable start) {
}

if (members.has(name, true)) {
return members.get(this, name, javaObject, true);
Object member = members.get(this, name, javaObject, true);
// trying to access .class when there is an existing static setClass()
if (!("class".equals(name) && member == NOT_FOUND)) {
return member;
}
}

Context cx = Context.getContext();
Scriptable scope = ScriptableObject.getTopLevelScope(start);
WrapFactory wrapFactory = cx.getWrapFactory();

if (javaClassPropertyName.equals(name)) {
if (javaClassPropertyName.equals(name) || "class".equals(name)) {
return wrapFactory.wrap(cx, scope, javaObject, ScriptRuntime.ClassClass);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.javascript.tests;

import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.tools.shell.Global;

public class NativeJavaClassTest {
private final String importClass =
"importClass(Packages.org.mozilla.javascript.tests.NativeJavaClassTest)\n";
private final Global global = new Global();
private static int callCount = 0;

public NativeJavaClassTest() {
global.init(ContextFactory.getGlobal());
}

public static void setClass(Class<?> clazz) {
callCount++;
}

@Before
public void setUp() {
callCount = 0;
}

@Test
public void basicClass() {
try (Context cx = ContextFactory.getGlobal().enterContext()) {
Object result = runScript("java.lang.Object.class;");
assertEquals(Context.javaToJS(Object.class, global), result);
}
}

@Test
public void withSetClass() {
// setClass() still works
runScript(importClass + "NativeJavaClassTest.setClass(java.lang.Object.class);");
assertEquals(callCount, 1);

// "class =" is still an alias to setClass()
runScript(importClass + "NativeJavaClassTest.class = java.lang.Object.class;");
assertEquals(callCount, 2);
}

@Test
public void classWithStaticSetClass() {
try (Context cx = ContextFactory.getGlobal().enterContext()) {
Object result = runScript(importClass + "NativeJavaClassTest.class;");
assertEquals(Context.javaToJS(NativeJavaClassTest.class, global), result);

Object staticAccess = runScript(importClass + "NativeJavaClassTest.class;");
Object instanceAccess =
runScript(importClass + "new NativeJavaClassTest().getClass();");
assertEquals(staticAccess, instanceAccess);

// "class =" does not update the class property
result =
runScript(
importClass
+ "NativeJavaClassTest.class = java.lang.Object.class; NativeJavaClassTest.class");
assertEquals(Context.javaToJS(NativeJavaClassTest.class, global), result);
}
}

private Object runScript(final String scriptSourceText) {
return ContextFactory.getGlobal()
.call(context -> context.evaluateString(global, scriptSourceText, "", 1, null));
}
}

0 comments on commit 0ceaea0

Please sign in to comment.