Skip to content

Commit

Permalink
Support compilation of array and list indexing with Integer in SpEL
Browse files Browse the repository at this point in the history
Prior to this commit, the Spring Expression Language (SpEL) failed to
compile an expression that indexed into an array or list using an
Integer.

This commit adds support for compilation of such expressions by
ensuring that an Integer is unboxed into an int in the compiled
bytecode.

See gh-32694
Closes gh-32908

(cherry picked from commit 079d53c)
  • Loading branch information
sbrannen committed May 27, 2024
1 parent 98aa03c commit 0f04052
Show file tree
Hide file tree
Showing 2 changed files with 456 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -226,6 +226,8 @@ public void generateCode(MethodVisitor mv, CodeFlow cf) {
cf.loadTarget(mv);
}

SpelNodeImpl index = this.children[0];

if (this.indexedType == IndexedType.ARRAY) {
int insn;
if ("D".equals(this.exitTypeDescriptor)) {
Expand Down Expand Up @@ -262,33 +264,29 @@ else if ("C".equals(this.exitTypeDescriptor)) {
//depthPlusOne(exitTypeDescriptor)+"Ljava/lang/Object;");
insn = AALOAD;
}
SpelNodeImpl index = this.children[0];
cf.enterCompilationScope();
index.generateCode(mv, cf);
cf.exitCompilationScope();

generateIndexCode(mv, cf, index, int.class);
mv.visitInsn(insn);
}

else if (this.indexedType == IndexedType.LIST) {
mv.visitTypeInsn(CHECKCAST, "java/util/List");
cf.enterCompilationScope();
this.children[0].generateCode(mv, cf);
cf.exitCompilationScope();
generateIndexCode(mv, cf, index, int.class);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;", true);
}

else if (this.indexedType == IndexedType.MAP) {
mv.visitTypeInsn(CHECKCAST, "java/util/Map");
// Special case when the key is an unquoted string literal that will be parsed as
// a property/field reference
if ((this.children[0] instanceof PropertyOrFieldReference)) {
if (index instanceof PropertyOrFieldReference) {
PropertyOrFieldReference reference = (PropertyOrFieldReference) this.children[0];
String mapKeyName = reference.getName();
mv.visitLdcInsn(mapKeyName);
}
else {
cf.enterCompilationScope();
this.children[0].generateCode(mv, cf);
index.generateCode(mv, cf);
cf.exitCompilationScope();
}
mv.visitMethodInsn(
Expand Down Expand Up @@ -325,6 +323,11 @@ else if (this.indexedType == IndexedType.OBJECT) {
cf.pushDescriptor(this.exitTypeDescriptor);
}

private void generateIndexCode(MethodVisitor mv, CodeFlow cf, SpelNodeImpl indexNode, Class<?> indexType) {
String indexDesc = CodeFlow.toDescriptor(indexType);
generateCodeForArgument(mv, cf, indexNode, indexDesc);
}

@Override
public String toStringAST() {
StringJoiner sj = new StringJoiner(",", "[", "]");
Expand Down
Loading

0 comments on commit 0f04052

Please sign in to comment.