Refactoring JSO implementation

This commit is contained in:
Alexey Andreev 2015-09-26 23:44:59 +03:00
parent bae388a778
commit 6986f1c02a
23 changed files with 84 additions and 77 deletions

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.function.Function; import java.util.function.Function;

View File

@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;
import org.teavm.javascript.RenderingContext; import org.teavm.javascript.RenderingContext;
import org.teavm.jso.plugin.JSODependencyListener.ExposedClass; import org.teavm.jso.impl.JSDependencyListener.ExposedClass;
import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodDescriptor;
import org.teavm.vm.BuildTarget; import org.teavm.vm.BuildTarget;
import org.teavm.vm.spi.RendererListener; import org.teavm.vm.spi.RendererListener;
@ -28,12 +28,12 @@ import org.teavm.vm.spi.RendererListener;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class JSOAliasRenderer implements RendererListener { class JSAliasRenderer implements RendererListener {
private static String variableChars = "abcdefghijklmnopqrstuvwxyz"; private static String variableChars = "abcdefghijklmnopqrstuvwxyz";
private JSODependencyListener dependencyListener; private JSDependencyListener dependencyListener;
private SourceWriter writer; private SourceWriter writer;
public JSOAliasRenderer(JSODependencyListener dependencyListener) { public JSAliasRenderer(JSDependencyListener dependencyListener) {
this.dependencyListener = dependencyListener; this.dependencyListener = dependencyListener;
} }

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.io.IOException; import java.io.IOException;
import org.mozilla.javascript.ast.AstNode; import org.mozilla.javascript.ast.AstNode;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.io.IOException; import java.io.IOException;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.io.IOException; import java.io.IOException;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.io.IOException; import java.io.IOException;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
@ -78,18 +78,18 @@ import org.teavm.model.util.ProgramUtils;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class JavascriptNativeProcessor { class JSClassProcessor {
private ClassReaderSource classSource; private ClassReaderSource classSource;
private Program program; private Program program;
private List<Instruction> replacement = new ArrayList<>(); private List<Instruction> replacement = new ArrayList<>();
private NativeJavascriptClassRepository nativeRepos; private JSTypeHelper typeHelper;
private Diagnostics diagnostics; private Diagnostics diagnostics;
private int methodIndexGenerator; private int methodIndexGenerator;
private Map<MethodReference, MethodReader> overridenMethodCache = new HashMap<>(); private Map<MethodReference, MethodReader> overridenMethodCache = new HashMap<>();
public JavascriptNativeProcessor(ClassReaderSource classSource) { public JSClassProcessor(ClassReaderSource classSource) {
this.classSource = classSource; this.classSource = classSource;
nativeRepos = new NativeJavascriptClassRepository(classSource); typeHelper = new JSTypeHelper(classSource);
} }
public ClassReaderSource getClassSource() { public ClassReaderSource getClassSource() {
@ -97,11 +97,11 @@ class JavascriptNativeProcessor {
} }
public boolean isNative(String className) { public boolean isNative(String className) {
return nativeRepos.isJavaScriptClass(className); return typeHelper.isJavaScriptClass(className);
} }
public boolean isNativeImplementation(String className) { public boolean isNativeImplementation(String className) {
return nativeRepos.isJavaScriptImplementation(className); return typeHelper.isJavaScriptImplementation(className);
} }
public void setDiagnostics(Diagnostics diagnostics) { public void setDiagnostics(Diagnostics diagnostics) {
@ -109,7 +109,7 @@ class JavascriptNativeProcessor {
} }
public MethodReference isFunctor(String className) { public MethodReference isFunctor(String className) {
if (!nativeRepos.isJavaScriptImplementation(className)) { if (!typeHelper.isJavaScriptImplementation(className)) {
return null; return null;
} }
ClassReader cls = classSource.get(className); ClassReader cls = classSource.get(className);
@ -138,7 +138,7 @@ class JavascriptNativeProcessor {
public void processClass(ClassHolder cls) { public void processClass(ClassHolder cls) {
Set<MethodDescriptor> preservedMethods = new HashSet<>(); Set<MethodDescriptor> preservedMethods = new HashSet<>();
for (String iface : cls.getInterfaces()) { for (String iface : cls.getInterfaces()) {
if (nativeRepos.isJavaScriptClass(iface)) { if (typeHelper.isJavaScriptClass(iface)) {
addPreservedMethods(iface, preservedMethods); addPreservedMethods(iface, preservedMethods);
} }
} }
@ -314,7 +314,7 @@ class JavascriptNativeProcessor {
return processJSBodyInvocation(repository, method, callLocation, invoke); return processJSBodyInvocation(repository, method, callLocation, invoke);
} }
if (!nativeRepos.isJavaScriptClass(invoke.getMethod().getClassName())) { if (!typeHelper.isJavaScriptClass(invoke.getMethod().getClassName())) {
return false; return false;
} }
@ -452,14 +452,14 @@ class JavascriptNativeProcessor {
name = redefinedMethodName.getString(); name = redefinedMethodName.getString();
} }
} }
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) { if (method.getResultType() != ValueType.VOID && !typeHelper.isSupportedType(method.getResultType())) {
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method " diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method "
+ "declaration", invoke.getMethod()); + "declaration", invoke.getMethod());
return false; return false;
} }
for (ValueType arg : method.getParameterTypes()) { for (ValueType arg : method.getParameterTypes()) {
if (!isSupportedType(arg)) { if (!typeHelper.isSupportedType(arg)) {
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method " diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method "
+ "or constructor declaration", invoke.getMethod()); + "or constructor declaration", invoke.getMethod());
return false; return false;
@ -521,12 +521,13 @@ class JavascriptNativeProcessor {
if (!isStatic) { if (!isStatic) {
ValueType paramType = ValueType.object(methodToProcess.getOwnerName()); ValueType paramType = ValueType.object(methodToProcess.getOwnerName());
paramTypes[offset++] = paramType; paramTypes[offset++] = paramType;
if (!isSupportedType(paramType)) { if (!typeHelper.isSupportedType(paramType)) {
diagnostics.error(location, "Non-static JSBody method {{m0}} is owned by non-JS class {{c1}}", diagnostics.error(location, "Non-static JSBody method {{m0}} is owned by non-JS class {{c1}}",
methodToProcess.getReference(), methodToProcess.getOwnerName()); methodToProcess.getReference(), methodToProcess.getOwnerName());
} }
} }
if (methodToProcess.getResultType() != ValueType.VOID && !isSupportedType(methodToProcess.getResultType())) { if (methodToProcess.getResultType() != ValueType.VOID
&& !typeHelper.isSupportedType(methodToProcess.getResultType())) {
diagnostics.error(location, "JSBody method {{m0}} returns unsupported type {{t1}}", diagnostics.error(location, "JSBody method {{m0}} returns unsupported type {{t1}}",
methodToProcess.getReference(), methodToProcess.getResultType()); methodToProcess.getReference(), methodToProcess.getResultType());
} }
@ -579,8 +580,9 @@ class JavascriptNativeProcessor {
} else { } else {
expr = rootNode; expr = rootNode;
} }
JavaInvocationValidator javaValidator = new JavaInvocationValidator(classSource, diagnostics); JavaInvocationProcessor javaInvocationProcessor = new JavaInvocationProcessor(typeHelper,
javaValidator.validate(location, expr); classSource, diagnostics);
javaInvocationProcessor.validate(location, expr);
repository.emitters.put(proxyMethod, new JSBodyAstEmitter(isStatic, expr, parameterNames)); repository.emitters.put(proxyMethod, new JSBodyAstEmitter(isStatic, expr, parameterNames));
} }
repository.methodMap.put(methodToProcess.getReference(), proxyMethod); repository.methodMap.put(methodToProcess.getReference(), proxyMethod);
@ -1078,7 +1080,7 @@ class JavascriptNativeProcessor {
} }
private boolean isProperGetter(MethodDescriptor desc) { private boolean isProperGetter(MethodDescriptor desc) {
if (desc.parameterCount() > 0 || !isSupportedType(desc.getResultType())) { if (desc.parameterCount() > 0 || !typeHelper.isSupportedType(desc.getResultType())) {
return false; return false;
} }
if (desc.getResultType().equals(ValueType.BOOLEAN)) { if (desc.getResultType().equals(ValueType.BOOLEAN)) {
@ -1090,7 +1092,7 @@ class JavascriptNativeProcessor {
} }
private boolean isProperSetter(MethodDescriptor desc) { private boolean isProperSetter(MethodDescriptor desc) {
if (desc.parameterCount() != 1 || !isSupportedType(desc.parameterType(0)) if (desc.parameterCount() != 1 || !typeHelper.isSupportedType(desc.parameterType(0))
|| desc.getResultType() != ValueType.VOID) { || desc.getResultType() != ValueType.VOID) {
return false; return false;
} }
@ -1106,13 +1108,13 @@ class JavascriptNativeProcessor {
} }
private boolean isProperGetIndexer(MethodDescriptor desc) { private boolean isProperGetIndexer(MethodDescriptor desc) {
return desc.parameterCount() == 1 && isSupportedType(desc.parameterType(0)) return desc.parameterCount() == 1 && typeHelper.isSupportedType(desc.parameterType(0))
&& isSupportedType(desc.getResultType()); && typeHelper.isSupportedType(desc.getResultType());
} }
private boolean isProperSetIndexer(MethodDescriptor desc) { private boolean isProperSetIndexer(MethodDescriptor desc) {
return desc.parameterCount() == 2 && isSupportedType(desc.parameterType(0)) return desc.parameterCount() == 2 && typeHelper.isSupportedType(desc.parameterType(0))
&& isSupportedType(desc.parameterType(0)) && desc.getResultType() == ValueType.VOID; && typeHelper.isSupportedType(desc.parameterType(0)) && desc.getResultType() == ValueType.VOID;
} }
private String cutPrefix(String name, int prefixLength) { private String cutPrefix(String name, int prefixLength) {
@ -1125,25 +1127,4 @@ class JavascriptNativeProcessor {
} }
return Character.toLowerCase(name.charAt(prefixLength)) + name.substring(prefixLength + 1); return Character.toLowerCase(name.charAt(prefixLength)) + name.substring(prefixLength + 1);
} }
private boolean isSupportedType(ValueType type) {
if (type == ValueType.VOID) {
return false;
}
if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) {
case LONG:
return false;
default:
return true;
}
} else if (type instanceof ValueType.Array) {
return isSupportedType(((ValueType.Array) type).getItemType());
} else if (type instanceof ValueType.Object) {
String typeName = ((ValueType.Object) type).getClassName();
return typeName.equals("java.lang.String") || nativeRepos.isJavaScriptClass(typeName);
} else {
return false;
}
}
} }

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -38,7 +38,7 @@ import org.teavm.model.MethodReader;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class JSODependencyListener extends AbstractDependencyListener { class JSDependencyListener extends AbstractDependencyListener {
private Map<String, ExposedClass> exposedClasses = new HashMap<>(); private Map<String, ExposedClass> exposedClasses = new HashMap<>();
private ClassReaderSource classSource; private ClassReaderSource classSource;
private DependencyAgent agent; private DependencyAgent agent;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.io.IOException; import java.io.IOException;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import org.teavm.vm.spi.TeaVMHost; import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin; import org.teavm.vm.spi.TeaVMPlugin;
@ -28,8 +28,8 @@ public class JSOPlugin implements TeaVMPlugin {
JSBodyRepository repository = new JSBodyRepository(); JSBodyRepository repository = new JSBodyRepository();
host.registerService(JSBodyRepository.class, repository); host.registerService(JSBodyRepository.class, repository);
host.add(new JSObjectClassTransformer(repository)); host.add(new JSObjectClassTransformer(repository));
JSODependencyListener dependencyListener = new JSODependencyListener(); JSDependencyListener dependencyListener = new JSDependencyListener();
JSOAliasRenderer aliasRenderer = new JSOAliasRenderer(dependencyListener); JSAliasRenderer aliasRenderer = new JSAliasRenderer(dependencyListener);
host.add(dependencyListener); host.add(dependencyListener);
host.add(aliasRenderer); host.add(aliasRenderer);
} }

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import org.teavm.diagnostics.Diagnostics; import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.ClassHolder; import org.teavm.model.ClassHolder;
@ -27,7 +27,7 @@ import org.teavm.model.MethodReference;
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class JSObjectClassTransformer implements ClassHolderTransformer { public class JSObjectClassTransformer implements ClassHolderTransformer {
private JavascriptNativeProcessor processor; private JSClassProcessor processor;
private JSBodyRepository repository; private JSBodyRepository repository;
public JSObjectClassTransformer(JSBodyRepository repository) { public JSObjectClassTransformer(JSBodyRepository repository) {
@ -37,7 +37,7 @@ public class JSObjectClassTransformer implements ClassHolderTransformer {
@Override @Override
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) { public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
if (processor == null || processor.getClassSource() != innerSource) { if (processor == null || processor.getClassSource() != innerSource) {
processor = new JavascriptNativeProcessor(innerSource); processor = new JSClassProcessor(innerSource);
} }
processor.setDiagnostics(diagnostics); processor.setDiagnostics(diagnostics);
processor.processClass(cls); processor.processClass(cls);

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import org.mozilla.javascript.CompilerEnvirons; import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.ErrorReporter; import org.mozilla.javascript.ErrorReporter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -21,17 +21,18 @@ import org.teavm.jso.JSObject;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource; import org.teavm.model.ClassReaderSource;
import org.teavm.model.ElementModifier; import org.teavm.model.ElementModifier;
import org.teavm.model.ValueType;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class NativeJavascriptClassRepository { class JSTypeHelper {
private ClassReaderSource classSource; private ClassReaderSource classSource;
private Map<String, Boolean> knownJavaScriptClasses = new HashMap<>(); private Map<String, Boolean> knownJavaScriptClasses = new HashMap<>();
private Map<String, Boolean> knownJavaScriptImplementations = new HashMap<>(); private Map<String, Boolean> knownJavaScriptImplementations = new HashMap<>();
public NativeJavascriptClassRepository(ClassReaderSource classSource) { public JSTypeHelper(ClassReaderSource classSource) {
this.classSource = classSource; this.classSource = classSource;
knownJavaScriptClasses.put(JSObject.class.getName(), true); knownJavaScriptClasses.put(JSObject.class.getName(), true);
} }
@ -82,4 +83,25 @@ class NativeJavascriptClassRepository {
} }
return cls.getInterfaces().stream().anyMatch(iface -> isJavaScriptClass(iface)); return cls.getInterfaces().stream().anyMatch(iface -> isJavaScriptClass(iface));
} }
public boolean isSupportedType(ValueType type) {
if (type == ValueType.VOID) {
return false;
}
if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) {
case LONG:
return false;
default:
return true;
}
} else if (type instanceof ValueType.Array) {
return isSupportedType(((ValueType.Array) type).getItemType());
} else if (type instanceof ValueType.Object) {
String typeName = ((ValueType.Object) type).getClassName();
return typeName.equals("java.lang.String") || isJavaScriptClass(typeName);
} else {
return false;
}
}
} }

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import org.mozilla.javascript.Token; import org.mozilla.javascript.Token;
import org.mozilla.javascript.ast.AstNode; import org.mozilla.javascript.ast.AstNode;
@ -34,12 +34,14 @@ import org.teavm.model.MethodReference;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class JavaInvocationValidator implements NodeVisitor { class JavaInvocationProcessor implements NodeVisitor {
private ClassReaderSource classSource; private ClassReaderSource classSource;
private JSTypeHelper typeHelper;
private Diagnostics diagnostics; private Diagnostics diagnostics;
private CallLocation location; private CallLocation location;
public JavaInvocationValidator(ClassReaderSource classSource, Diagnostics diagnostics) { public JavaInvocationProcessor(JSTypeHelper typeHelper, ClassReaderSource classSource, Diagnostics diagnostics) {
this.typeHelper = typeHelper;
this.classSource = classSource; this.classSource = classSource;
this.diagnostics = diagnostics; this.diagnostics = diagnostics;
} }

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import java.io.IOException; import java.io.IOException;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.jso.plugin; package org.teavm.jso.impl;
import org.mozilla.javascript.ErrorReporter; import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException; import org.mozilla.javascript.EvaluatorException;

View File

@ -1 +1 @@
org.teavm.jso.plugin.JSOPlugin org.teavm.jso.impl.JSOPlugin

View File

@ -25,6 +25,8 @@ import org.mozilla.javascript.Context;
import org.mozilla.javascript.ast.AstRoot; import org.mozilla.javascript.ast.AstRoot;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;
import org.teavm.codegen.SourceWriterBuilder; import org.teavm.codegen.SourceWriterBuilder;
import org.teavm.jso.impl.AstWriter;
import org.teavm.jso.impl.JSParser;
/** /**
* *