cfproperty tag lucee allows non quoted properties
Description
Attachments
- 19 Sep 2024, 01:56 AM
Activity
Brad Wood September 19, 2024 at 1:56 AM
Thinking a little further on this-- how we parse the values really boils down to whether we consider a script property to be
a first-class construct
just a generic-tag-in-script construct
Both have a concept of key="value"
pairs, but they follow different parsing rules. First-class constructs (which consists of classes, interfaces, functions, and properties) have annotations, but tags-in-script (such as cfheader()
or header xxx;
have attributes. The naming may seem arbitrary, but they each have different rules.
annotations follow the rules I described above. They are essentially part of the metadata of your class or function or interface and their values can only be literals. Unquoted annotations are just strings.
attributes are not baked statically into a function or a class and are evaluated at runtime. Their attribute values can be any valid expression. Unquoted attributes are considered variable expressions.
Ex:
function foo() brad=wood {
}
The annotation value wood
is a string, not a variable.
var myValue = "text/html"
// tag-in-script <cfheader>
header name="Content-Type" value=myValue;
The attribute value myValue
is a variable, evaluated at runtime.
While there is a <CFProperty>
tag in CFML tag-based syntax, the script counterpart is a bit of a snowflake, allowing “shortcut” syntaxes like
property String typedShortcutWithDefault default="myDefaultValue2";
As such, we don’t use a generic tag-in-script rule to match it as a component, but instead have a first-class parser rule, that treats it as a construct having annotations, not attributes since it’s not really a cfproperty “tag” in the script context.
So, back to Lucee-- Lucee allows unquoted values in script property constructs, and it treats them as strings, not variables.
property name=myProperty default=myDefaultValue type=string;
Therefore, it feels like property is NOT being treated like a tag-in-script with attributes, but like a first-class construct with literal annotations.
So, I went back and tested your actual example from the ticket
property name="chain" type="array" default=ArrayNew(1);
and I’ve found that it doesn’t work as you claimed! In my tests using Lucee 5.4.4, the default value on my property is the string "ArrayNew(1)"
So I guess that calls into question the entire bug report here
In related news, I have fixed property default values like
property name="chain" type="array" default="#ArrayNew(1)#";
to work now, so I’ll close this ticket and if there’s still actual incompat with Lucee in regards to unquoted defaults that I’m not seeing, you can create a new ticket with a more specific repro case.
Alex Skinner September 17, 2024 at 11:03 PM
The actual code that we have erroring is the property specifying a default of either structNew() or ArrayNew(1) without the ““
But the docs do specify that it should be a literal
Brad Wood September 17, 2024 at 10:53 PM
Ok, so this really doesn’t have to do with the quotes or lack of quotes per se. In our parser in general, attributes are allowed to be any literal value, and identifier, or an fqn, which could be
string
array
struct
boolean
number
foobar (identifier – string with no quotes)
foo.bar.baz (fqn)
So right off, someFunction()
is not a literal value so the parser will refuse to even parse that code. Properties don’t really have any “special” parsing outside of the “shortcut” syntax. Attributes/annotations for a property are subject to the same rules as any other tag-in-script. I had never seen code like this before and didn’t realize it was even valid:
property name="foo" default=myExpr;
That poses a significant parsing issue since it’s now no longer clear if myExpr
is a variable to be evaluated or an unquoted string? Keep in mind this is also valid CF code
property name="myProperty" type=string;
Note the string
attribute value is not intended to be an expressions that’s evaluated, but rather an quoted literal.
So, the second example should, in theory, work. It just lands in some weeds of BoxLang I haven’t quite finalized yet.
property name="foo" default="#myExpr#";
Properties are stored statically in the definition of the class, and they are evaluated when the class is first loaded, which happens in a bit of a vacuum that doesn’t have access to any particular context by which to lookup variables or access information about the request or its scopes. This is why the second option errors because the generated code in the static initializer of the class is looking for a Box context to use for the runtime evaluation, but it can’t find one. I can fix this, but it requires some refactoring of how and where the code lives to initializes the defaut
value for properties when the class is created.
Brad Wood September 17, 2024 at 9:55 PM
Please show the stacktraces in your tickets. Just saying “doesn’t like it” really doesn’t help me much
Alex Skinner September 17, 2024 at 12:59 PM
Additionally it seems that it doesn’t like it if its quoted and has hashes either
property name="viewlet" type="string" default="";
property name="chain" type="array" default="#ArrayNew(1)#";
This also fails to transpire
I’m not sure whether this is Lucee specific but Lucee allows the following in a CFC
e.g.
component accessors=true {
property name="viewlet" type="string" default="";
property name="chain" type="array" default=ArrayNew(1);
Note the second property is not wrapped in ““