in boot/src/main/java/org/netbeans/html/boot/impl/FnUtils.java [200:479]
private boolean generateBody(boolean hasCode) {
if (bodyGenerated) {
return false;
}
bodyGenerated = true;
if (mv != null) {
AnnotationVisitor va = super.visitAnnotation("Lnet/java/html/js/JavaScriptBody;", false);
AnnotationVisitor varr = va.visitArray("args");
for (String argName : fia.args) {
varr.visit(null, argName);
}
varr.visitEnd();
va.visit("body", fia.body);
if (fia.javacall != null) {
va.visit("javacall", fia.javacall);
}
if (fia.wait4js != null) {
va.visit("wait4js", fia.wait4js);
}
if (fia.wait4java != null) {
va.visit("wait4java", fia.wait4java);
}
if (fia.keepAlive != null) {
va.visit("keepAlive", fia.keepAlive);
}
va.visitEnd();
}
String body;
List<String> args;
if ((fia.javacall())) {
body = callback(fia.body, fia.usePromise());
args = new ArrayList<>(fia.args);
args.add("vm");
} else {
body = fia.body;
args = fia.args;
}
super.visitFieldInsn(
Opcodes.GETSTATIC, FindInClass.this.name,
"$$fn$$" + name + "_" + found,
"Lorg/netbeans/html/boot/spi/Fn;"
);
super.visitInsn(Opcodes.DUP);
super.visitMethodInsn(
Opcodes.INVOKESTATIC,
"org/netbeans/html/boot/spi/Fn", "isValid",
"(Lorg/netbeans/html/boot/spi/Fn;)Z"
);
Label ifNotNull = new Label();
super.visitJumpInsn(Opcodes.IFNE, ifNotNull);
// init Fn
super.visitInsn(Opcodes.POP);
super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
super.visitInsn(fia.keepAlive() ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
super.visitLdcInsn(body);
super.visitIntInsn(Opcodes.SIPUSH, args.size());
super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String");
boolean needsVM = false;
for (int i = 0; i < args.size(); i++) {
assert !needsVM;
String argName = args.get(i);
needsVM = "vm".equals(argName);
super.visitInsn(Opcodes.DUP);
super.visitIntInsn(Opcodes.BIPUSH, i);
super.visitLdcInsn(argName);
super.visitInsn(Opcodes.AASTORE);
}
super.visitMethodInsn(Opcodes.INVOKESTATIC,
"org/netbeans/html/boot/spi/Fn", "define",
"(Ljava/lang/Class;ZLjava/lang/String;[Ljava/lang/String;)Lorg/netbeans/html/boot/spi/Fn;"
);
Label noPresenter = new Label();
super.visitInsn(Opcodes.DUP);
super.visitJumpInsn(Opcodes.IFNULL, noPresenter);
int cnt = resourcesCnt;
while (cnt > 0) {
String resource = resources[--cnt];
if (resource == null) {
continue;
}
super.visitLdcInsn(Type.getObjectType(FindInClass.this.name));
super.visitLdcInsn(resource);
super.visitMethodInsn(Opcodes.INVOKESTATIC,
"org/netbeans/html/boot/spi/Fn", "preload",
"(Lorg/netbeans/html/boot/spi/Fn;Ljava/lang/Class;Ljava/lang/String;)Lorg/netbeans/html/boot/spi/Fn;"
);
}
super.visitInsn(Opcodes.DUP);
super.visitFieldInsn(
Opcodes.PUTSTATIC, FindInClass.this.name,
"$$fn$$" + name + "_" + found,
"Lorg/netbeans/html/boot/spi/Fn;"
);
// end of Fn init
super.visitLabel(ifNotNull);
final int offset;
if ((access & Opcodes.ACC_STATIC) == 0) {
offset = 1;
super.visitIntInsn(Opcodes.ALOAD, 0);
} else {
offset = 0;
super.visitInsn(Opcodes.ACONST_NULL);
}
super.visitIntInsn(Opcodes.SIPUSH, args.size());
super.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
class SV extends SignatureVisitor {
private boolean nowReturn;
private Type returnType;
private int index;
private int loadIndex = offset;
public SV() {
super(Opcodes.ASM5);
}
@Override
public void visitBaseType(char descriptor) {
final Type t = Type.getType("" + descriptor);
if (nowReturn) {
returnType = t;
return;
}
FindInMethod.super.visitInsn(Opcodes.DUP);
FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
FindInMethod.super.visitVarInsn(t.getOpcode(Opcodes.ILOAD), loadIndex++);
String factory;
switch (descriptor) {
case 'I':
factory = "java/lang/Integer";
break;
case 'J':
factory = "java/lang/Long";
loadIndex++;
break;
case 'S':
factory = "java/lang/Short";
break;
case 'F':
factory = "java/lang/Float";
break;
case 'D':
factory = "java/lang/Double";
loadIndex++;
break;
case 'Z':
factory = "java/lang/Boolean";
break;
case 'C':
factory = "java/lang/Character";
break;
case 'B':
factory = "java/lang/Byte";
break;
default:
throw new IllegalStateException(t.toString());
}
FindInMethod.super.visitMethodInsn(Opcodes.INVOKESTATIC,
factory, "valueOf", "(" + descriptor + ")L" + factory + ";"
);
FindInMethod.super.visitInsn(Opcodes.AASTORE);
}
@Override
public SignatureVisitor visitArrayType() {
if (nowReturn) {
return new SignatureVisitor(Opcodes.ASM5) {
@Override
public void visitClassType(String name) {
returnType = Type.getType("[" + Type.getObjectType(name).getDescriptor());
}
@Override
public void visitBaseType(char descriptor) {
returnType = Type.getType("[" + descriptor);
}
};
}
loadObject();
return new SignatureWriter();
}
@Override
public void visitClassType(String name) {
if (nowReturn) {
returnType = Type.getObjectType(name);
return;
}
loadObject();
}
@Override
public SignatureVisitor visitReturnType() {
nowReturn = true;
return this;
}
private void loadObject() {
FindInMethod.super.visitInsn(Opcodes.DUP);
FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, index++);
FindInMethod.super.visitVarInsn(Opcodes.ALOAD, loadIndex++);
FindInMethod.super.visitInsn(Opcodes.AASTORE);
}
}
SV sv = new SV();
SignatureReader sr = new SignatureReader(desc);
sr.accept(sv);
if (needsVM) {
FindInMethod.super.visitInsn(Opcodes.DUP);
FindInMethod.super.visitIntInsn(Opcodes.SIPUSH, sv.index);
int lastSlash = FindInClass.this.name.lastIndexOf('/');
String jsCallbacks = FindInClass.this.name.substring(0, lastSlash + 1) + "$JsCallbacks$";
FindInMethod.super.visitFieldInsn(Opcodes.GETSTATIC, jsCallbacks, "VM", "L" + jsCallbacks + ";");
FindInMethod.super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, jsCallbacks, "current", "()L" + jsCallbacks + ";");
FindInMethod.super.visitInsn(Opcodes.AASTORE);
}
if (!fia.asyncJavaScript()) {
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"org/netbeans/html/boot/spi/Fn", "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
);
switch (sv.returnType.getSort()) {
case Type.VOID:
super.visitInsn(Opcodes.RETURN);
break;
case Type.ARRAY:
case Type.OBJECT:
super.visitTypeInsn(Opcodes.CHECKCAST, sv.returnType.getInternalName());
super.visitInsn(Opcodes.ARETURN);
break;
case Type.BOOLEAN: {
Label handleNullValue = new Label();
super.visitInsn(Opcodes.DUP);
super.visitJumpInsn(Opcodes.IFNULL, handleNullValue);
super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"java/lang/Boolean", "booleanValue", "()Z"
);
super.visitInsn(Opcodes.IRETURN);
super.visitLabel(handleNullValue);
super.visitInsn(Opcodes.ICONST_0);
super.visitInsn(Opcodes.IRETURN);
break;
}
default:
super.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"java/lang/Number", sv.returnType.getClassName() + "Value", "()" + sv.returnType.getDescriptor()
);
super.visitInsn(sv.returnType.getOpcode(Opcodes.IRETURN));
}
} else {
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"org/netbeans/html/boot/spi/Fn", "invokeLater", "(Ljava/lang/Object;[Ljava/lang/Object;)V"
);
super.visitInsn(Opcodes.RETURN);
}
super.visitLabel(noPresenter);
if (hasCode) {
super.visitCode();
} else {
super.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException");
super.visitInsn(Opcodes.DUP);
super.visitLdcInsn("No presenter active. Use BrwsrCtx.execute!");
super.visitMethodInsn(Opcodes.INVOKESPECIAL,
"java/lang/IllegalStateException", "<init>", "(Ljava/lang/String;)V"
);
this.visitInsn(Opcodes.ATHROW);
}
return true;
}