@@ -380,7 +380,17 @@ public byte[] execute(String className) throws TransformerException {
380380 String [] interfaces = null ;
381381 if (isComponent (comp )) {
382382 parent = ComponentPageImpl .class .getName ();// "lucee/runtime/ComponentPage";
383- if (isSub ) interfaces = new String [] { SubPage .class .getName ().replace ('.' , '/' ) };
383+ List <TagProperty > exprDefProps = collectExpressionFormProperties (comp );
384+ boolean hasExprDefaults = !exprDefProps .isEmpty ();
385+ if (isSub && hasExprDefaults ) {
386+ interfaces = new String [] { SubPage .class .getName ().replace ('.' , '/' ), "lucee/runtime/component/ExpressionDefaultSeeder" };
387+ }
388+ else if (isSub ) {
389+ interfaces = new String [] { SubPage .class .getName ().replace ('.' , '/' ) };
390+ }
391+ else if (hasExprDefaults ) {
392+ interfaces = new String [] { "lucee/runtime/component/ExpressionDefaultSeeder" };
393+ }
384394 }
385395 else if (isInterface (comp )) parent = InterfacePageImpl .class .getName ();// "lucee/runtime/InterfacePage";
386396 parent = parent .replace ('.' , '/' );
@@ -1255,22 +1265,10 @@ else if (defaultExpr instanceof LitBooleanImpl) {
12551265 ga .invokeVirtual (Types .PROPERTY_IMPL , new Method ("setDefault" , Type .VOID_TYPE , new Type [] { Types .OBJECT }));
12561266 }
12571267 else {
1258- String source ;
1259- try {
1260- int start = defaultExpr .getStart ().pos ;
1261- int end = defaultExpr .getEnd ().pos ;
1262- // json() consumes opening { or [ before recording position; back up
1263- if (start > 0 ) {
1264- String peek = sourceCode .subCFMLString (start - 1 , 1 ).toString ();
1265- if (peek .length () == 1 && (peek .charAt (0 ) == '{' || peek .charAt (0 ) == '[' )) {
1266- start --;
1267- }
1268- }
1269- source = sourceCode .subCFMLString (start , end - start ).toString ();
1270- }
1271- catch (Exception e ) {
1272- source = "" ;
1273- }
1268+ // WIP: raw value includes attribute wrapping syntax (quotes + hashes); contract for
1269+ // metadata.default source TBD. See LDEV-6303-code-review.md for state.
1270+ String source = propDefaultAttr .getRawValue ();
1271+ if (source == null ) source = "" ;
12741272 Type EXPRESSION_DEFAULT = Type .getType ("Llucee/runtime/component/ExpressionDefault;" );
12751273 ga .loadLocal (propLocal );
12761274 ga .newInstance (EXPRESSION_DEFAULT );
@@ -1565,13 +1563,11 @@ else if (defaultExpr instanceof LitBooleanImpl) {
15651563
15661564 }
15671565
1568- private void writeOutSeedExpressionDefaults ( PageSource optionalPS , ConstrBytecodeContext constr , Map < LitString , Integer > keys , ClassWriter cw , TagCIObject component ,
1569- String name ) throws TransformerException {
1570- if (component == null || component .getBody () == null ) return ;
1566+ private static List < TagProperty > collectExpressionFormProperties ( TagCIObject component ) {
1567+ List < TagProperty > result = new ArrayList < TagProperty >();
1568+ if (component == null || component .getBody () == null ) return result ;
15711569 List <Statement > statements = component .getBody ().getStatements ();
1572- if (statements == null ) return ;
1573-
1574- List <TagProperty > exprDefProps = new ArrayList <TagProperty >();
1570+ if (statements == null ) return result ;
15751571 for (Statement stmt : statements ) {
15761572 if (!(stmt instanceof TagProperty )) continue ;
15771573 TagProperty tagProp = (TagProperty ) stmt ;
@@ -1581,37 +1577,27 @@ private void writeOutSeedExpressionDefaults(PageSource optionalPS, ConstrBytecod
15811577 if (defaultExpr instanceof LitStringImpl || defaultExpr instanceof LitNumberImpl || defaultExpr instanceof LitBooleanImpl ) continue ;
15821578 Attribute nameAttr = tagProp .getAttribute ("name" );
15831579 if (nameAttr == null || nameAttr .getValue () == null ) continue ;
1584- exprDefProps .add (tagProp );
1580+ result .add (tagProp );
15851581 }
1582+ return result ;
1583+ }
1584+
1585+ private void writeOutSeedExpressionDefaults (PageSource optionalPS , ConstrBytecodeContext constr , Map <LitString , Integer > keys , ClassWriter cw , TagCIObject component ,
1586+ String name ) throws TransformerException {
1587+ List <TagProperty > exprDefProps = collectExpressionFormProperties (component );
1588+ if (exprDefProps .isEmpty ()) return ;
15861589
1587- // Method shell always emitted on component classes — empty body is JIT no-op; ensures
1588- // presence-of-method is stable for ComponentImpl._duplicate's reflection lookup.
15891590 Method seedMethod = new Method ("_seedExpressionDefaults" , Types .VOID , new Type [] { Types .PAGE_CONTEXT });
1590- GeneratorAdapter ga = new GeneratorAdapter (Opcodes .ACC_PUBLIC + Opcodes . ACC_STATIC , seedMethod , null , new Type [] { Types .THROWABLE }, cw );
1591+ GeneratorAdapter ga = new GeneratorAdapter (Opcodes .ACC_PUBLIC , seedMethod , null , new Type [] { Types .THROWABLE }, cw );
15911592 BytecodeContext bc = new BytecodeContext (config , optionalPS , constr , this , keys , cw , name , ga , seedMethod , writeLog (), suppressWSbeforeArg , output , returnValue ,
15921593 sourceCode .getSourceOffset ());
15931594
1594- Method METHOD_VARIABLES_SCOPE = new Method ("variablesScope" , Types .VARIABLES , new Type [] {});
1595- Method METHOD_SET_EL = new Method ("setEL" , Types .OBJECT , new Type [] { Types .COLLECTION_KEY , Types .OBJECT });
1596-
15971595 for (TagProperty tagProp : exprDefProps ) {
15981596 Attribute nameAttr = tagProp .getAttribute ("name" );
15991597 Attribute defaultAttr = tagProp .getAttribute ("default" );
16001598 String propName = nameAttr .getValue () instanceof Literal ? ((Literal ) nameAttr .getValue ()).getString () : null ;
16011599 if (propName == null ) continue ;
1602- Expression defaultExpr = defaultAttr .getValue ();
1603-
1604- defaultExpr .writeOut (bc , Expression .MODE_REF );
1605- int defaultLocal = ga .newLocal (Types .OBJECT );
1606- ga .storeLocal (defaultLocal );
1607-
1608- ga .loadArg (0 );
1609- ga .invokeVirtual (Types .PAGE_CONTEXT , METHOD_VARIABLES_SCOPE );
1610- ga .push (propName );
1611- ga .invokeStatic (KEY_IMPL , KEY_INIT );
1612- ga .loadLocal (defaultLocal );
1613- ga .invokeInterface (Types .SCOPE , METHOD_SET_EL );
1614- ga .pop ();
1600+ TagProperty .emitExpressionEvalAndSet (bc , propName , defaultAttr .getValue ());
16151601 }
16161602
16171603 ga .returnValue ();
0 commit comments