-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
[2.0]: Properties of objects aren't being checked correctly by FES #7752
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi @davepagurek , I looked at the code to find out how the parsing logic is being written and I found that the function The issue lies in the line here: return (entry.tags || []).filter(t => t.title === 'param').map(node => {
const param = entry.params.find(param => param.name === node.name);
...
}); A very heuristic approach would be like, .filter(t => t.title === 'param' && !t.name.includes('.')) Of course, it will work, but then it is not based on structure, it will just be based on assumptions of how naming is being done. What I meant is, it will become a bold statement as - "If the parameter name contains a Instead, we can use, a set to build all the top-level parameter names defined in const signatureParamNames = new Set((entry.params || []).map(param => param.name)); and then .filter(t => t.title === 'param' && signatureParamNames.has(t.name))
.map(node => {
const param = (entry.params || []).find(param => param.name === node.name); I have also observed two other notable things in the existing function:
const param = entry.params.find(param => param.name === node.name); We should safely access
if (param) {
return {
...node,
description: param.description
};
} else {
return {
...node,
description: {
type: 'html',
value: node.description
}
};
} optimized one: return {
...node,
description: param?.description || {
type: 'html',
value: node.description
}
}; @ksen0 and @limzykenneth , would also love to hear your thoughts and feedback here. |
I have checked it too with the changes as discussed above, it is coming as expected: "textToModel": {
"overloads": [
[
"String",
"Number",
"Number",
"Number",
"Number",
"Object?"
]
]
} and yet another example with the below params as one of the overloads of /**
* @method createModel
* @param {String} modelString
* @param {String} [fileType]
* @param {Object} [options]
* @param {function(p5.Geometry)} [options.successCallback]
* @param {function(Event)} [options.failureCallback]
* @param {boolean} [options.normalize]
* @param {boolean} [options.flipU]
* @param {boolean} [options.flipV]
* @return {p5.Geometry} the <a href="#/p5.Geometry">p5.Geometry</a> object
*/ it is coming as: [
"String",
"String?",
"Object?"
] |
Hi @davepagurek , @ksen0 , @limzykenneth , |
Hi @IIITM-Jay! I think there are two things to address here. The first thing is to not treat nested properties like separate positional parameters, but the second is the ability to check those types at runtime. Because we need that second case, we will need to do more than filter out the nested parameter types -- I think we'll have to pass that data into FES still. So the idea would be to turn the textToModel overloads from this: "textToModel": {
"overloads": [
[
"String",
"Number",
"Number",
"Number",
"Number",
"Object?"
]
]
} ...to something like this (as an example syntax): "textToModel": {
"overloads": [
[
"String",
"Number",
"Number",
"Number",
"Number",
"{ extrude: Number?, sampleFactor: Number? }?"
]
]
} ...and then parse that out and check it in FES here:
(Another possible approach to avoid stringifying and then re-parsing could be to change the parameterData.json format to include more structure, similar to what we see in the data.json output of To do so, I think you'll have to identify which properties are nested properties. We don't need to worry too much about efficiency since this is only run once at compile time (end users of p5.js don't incur that cost, just us when building the library) so we can favour simplicity for now. There are two ways, it seems, for us to get nested parameters:
|
Hi @davepagurek! Thanks for the insights on this. I am really enjoying this as it looks like I again got something to dive deeper and playaround with the approaches for a suitable one.
I agree that sometimes simplicity is favoured over the optimization for easier maintenance and enhanced readability. So, I guess yes the very first approach that came to my mind as I mentioned earlier and you also recognized will suffice for filter out the nested properties. Will work around and come back with the syntax changes as well checking it with FES.
Yeah! I have checked so far, |
Thanks for checking for As far as PRs go, feel free to work on one if you're interested in taking this on! If tackling the problem in two stages helps, your initial idea of just removing the object properties from the array in |
I am thinking to have a syntax like: "textToModel": {
"overloads": [
[
"String",
"Number",
"Number",
"Number",
"Number",
{
"type": "Object",
"optional": true,
"properties": {
"extrude": "Number?",
"sampleFactor": "Number?"
}
}
]
]
} I have given an additional key as optional with boolean values to indicate that this parameter would be optional.
I am thinking to, let's see |
@IIITM-Jay so if an array element is just a string, e.g. Maybe we allow a trailing
The main reason for this is that combinations of those things start making us think harder about the order we parse things in, e.g. |
Hi @davepagurek, hmm... got some interesting things here to flex my brains.
In my opinion, this isn't inherently tricky—it's more about the effort required to implement proper parsing. The ambiguity doesn't actually exist if we handle operator precedence correctly and explicitly. My concerns arise when I see examples like
Why in my sense it creates ambiguous to users/ readers? Yet another example:
Take a look again:
These are some really ambiguous examples that came to my mind first. @davepagurek aren't you find this interesting to dive into, but I am really to be honest. Tagging folks to get more thoughts. @ksen0 , @limzykenneth - would love to hear your thoughts as well. |
Hi @davepagurek the last example of above is literally critical... In my view, as I check for this, "p5": {
"describe": {
"overloads": [
[
"String",
"FALLBACK|LABEL?"
]
]
}, as compared to the earlier example of the above comment CC: @ksen0 , @limzykenneth |
and for the above, I have safely generated as "p5": {
"describe": {
"overloads": [
[
{
"type": "String",
"optional": false
},
{
"type": "union",
"elements": [
{
"type": "FALLBACK",
"optional": true
},
{
"type": "LABEL",
"optional": true
}
],
"optional": true
}
]
]
}, What do you say, @davepagurek , @ksen0 , @limzykenneth ? |
I think overall my preference is that any time we have the potential for ambiguity, we fall back to structured JSON to avoid the ambiguity, to avoid having extra complexity in FES. So if there's a situation where we'd have both optional + some other construct like arrays or unions, fall back to structured JSON. This way the FES codebase would be easier for contributors to understand, and contributors don't have to think about recursive parsing at all. The parsing problem is possibly avoidable, because we're creating the problem ourselves: in The one major benefit of the serialize-to-string-and-parse approach is that we can pack the data into a smaller package, but we can maybe get that out of JSON too by picking small property names? |
for your concerns above, for me I am able to generate for the below "red": {
"overloads": [
[
"p5.Color|Number[]|String"
]
]
}, as "red": {
"overloads": [
[
{
"type": "union",
"elements": [
{
"type": "p5.Color",
"optional": true
},
{
"type": "Array",
"element": "Number",
"optional": true
},
{
"type": "String",
"optional": true
}
],
"optional": false
}
]
]
}, This is what you expected @davepagurek ? |
That looks good to me @IIITM-Jay! Also if we want to make the JSON small to minimize file size, we can maybe remove |
@davepagurek Hi Dave, that's exactly what I have planned earlier keeping in mind about the size of the JSON that it will grow as a result of redundant keys, but then you made a point on my earlier PR when I kept optional key for only
[
{ "type": "String", "optional": false },
{ "type": "String", "optional": false },
{
"type": "Object",
"optional": true,
"properties": {
"successCallback": { "type": "Function", "optional": true, parameters: [{ type: "p5.Geometry" }] },
"failureCallback": { "type": "Function", "optional": true, parameters: [{ type: "Event" }] },
"normalize": { "type": "boolean", "optional": true },
"flipU": { "type": "boolean", "optional": true },
"flipV": { "type": "boolean", "optional": true }
}
}
] I thought to keep my point there at PR for minimization of JSON by removing redundant optional field here and keep only at required places, but then I thought as you suggested for consistent format. Anyways, will work too on optimization of JSON. |
Ah sorry if my point was a bit unclear, I was mostly referring to specifying optionality in JSON (via |
Hi @davepagurek , I have raised a PR #7843 as per our discussions as above, Would love to hear your feedback and thoughts on the same. Will incorporate appropriate changes and revise the PR as required. |
Hi @davepagurek , if by any chance, you got some time to look at the PR, may I request to provide suggestions and feedback on the same. |
Thanks @IIITM-Jay! Sorry for the delay, I've been busy helping with Processing interviews this week. I'll try to get you a review tonight or tomorrow 🙂 |
Most appropriate sub-area of p5.js?
p5.js version
2.0.0
Web browser and version
Firefox
Operating system
MacOS
Steps to reproduce this
Steps:
If you run
npm run docs
and then checkdocs/parameterData.json
, if you search fortextToModel
, it currently has these parameters:This is because we're documenting the properties of the object like this:
It looks like we're mistakenly parsing
options.extrude
andoptions.sampleFactor
as separate parameters, and not properties ofoptions
.This likely needs a change in
utils/convert.js
.The text was updated successfully, but these errors were encountered: