This patch modifies the way Javascript <script> tags are handled.
It defines a new element type "scripts", and this new element has a new #pre_render callback drupal_pre_render_scripts, just like the element "styles" and drupal_pre_render_styles for CSS files.
By doing this, we align the "scripts" element with the "styles" element.
| Comment | File | Size | Author |
|---|---|---|---|
| #55 | 3051370.patch | 8.33 KB | pol |
Comments
Comment #2
polPatch is being worked on, it will be uploaded here as soon as it's ready.
Comment #4
polComment #5
polComment #6
fabianx commentedRTBC, but this will need a change record before commit.
Comment #7
polChange record: https://www.drupal.org/node/3051383
Comment #8
polComment #9
fabianx commentedComment #11
markhalliwellWe really shouldn't introduce #markup, even temporarily. I'm confused with why exactly this needs to be split out. #2990123: Ensure CSS and JS are rendered using the same workflow seems like a more solid solution which doesn't include #markup.
I'm in favor of just closing this as a dup of that issue and focus our efforts there. It's not like this is a lot of code.
Comment #12
markhalliwellNevermind...
Comment #13
pol@Mark, it's going to be removed, but we are changing one small stuff, one step at a time.
I'm going to submit the second part now. See this: https://www.drupal.org/project/drupal/issues/1664602#comment-13086536
Comment #14
fabianx commented#11 I am in agreement (and will take it in mind for further re-work), but workflow-wise it was simpler to work on it one step at a time.
Comment #15
markhalliwellYes, I just saw that comment, from one hour ago...
I appreciate that we're finally doing at least something with that issue... but seems like this new direction (which is the first we're all hearing about this) is being snuck in without any real sort of community feedback/review.
Feels a bit shady.
Comment #16
markhalliwellI will note that I'm not disagreeing with this approach.
It certainly will help address the fact that both CSS and JS differ greatly in how they're handled. I've reviewed the patch and it works, aside from the #markup bit. As that will be taken care of by another issue, I'm fine with it I guess since it's already committed.
I just don't appreciate a years-long issue suddenly being taken in a different direction with commits, all within a span of an hour, before the 77+ people actually following the issue have at least had a little time to digest this news.
A week or, at the very least, a day would have been a more appropriate length of time before commits were made.
Comment #17
fabianx commentedYou are right, I will revert. We will work the theme('html_tag') into this issue.
Comment #19
polHere's a new version of the updated patch that contains the first version of this patch (that has been reverted), plus the removal of
theme()calls.Comment #20
markhalliwellI get that this was changed to respect the 80 character limit, but this kind of just irks me. We should just put the second sentence on the second line; no need to have that much whitespace.
While this is technically "okay" (keeps order), we lose the real associative keys used by aggregation. Given that this is becoming a #pre_render callback, we shouldn't obfuscate this in case contrib/custom code needs/wants to alter this in additional #pre_render callbacks.
I honestly preferred the approach and variable renames in #2990123: Ensure CSS and JS are rendered using the same workflow here.
Comment #21
pol@Mark, thanks for the feedback, I will update the patch accordingly.
However, the approach in #2990123: Ensure CSS and JS are rendered using the same workflow is wrong.
The
#pre_rendercallback is supposed to return the element it receives in its argument and the patch in there doesn't do that.Comment #22
fabianx commented#20 1,2: Agree 100%.
Yes, we can bring part of that back.
- $output -> $settings -- yes
- $processed -> $items -- yes
As for the #pre_render issue:
What about we return two keys:
Comment #23
polEven better :-)
I will update now.
Comment #24
polPatch updated.
Comment #25
polComment #26
markhalliwellAh, didn't catch that.
I like the idea of adding two new child keys to the element. The only drawback is making sure
scripts(which should also be the variable name IMO, not $items) is rendered beforesettings. We should probably add'#weight' => 1to$settingsto ensure this.Comment #27
polOoh nice catch indeed. Update ongoing.
Comment #28
polComment #29
polComment #30
markhalliwellAlso, now that I think about this, I don't think we want to risk introducing another Drupal WTF moment here.
What if, someone, supplies these keys (for whatever reason) prior to this being invoked. These won't get added because the keys already exist.
I think this should use any existing children as a default starting point (will likely need to use this as the starting $index) and then definitively set the children on the element at the end.
This looks... odd. A simple
$settings['#weight'] = 1;at the top would suffice.Comment #31
polAll your feedback has been addressed in the following patch.
Interdiff provided against #19.
Comment #32
markhalliwell@Pol, see #30.
Comment #33
polOn it.
Would this be better ?
It's mostly the end of the pre_process that has been updated:
Comment #34
fabianx commented#30 I am not sure I agree as we introduce this element newly here.
I think the sub-keys are fine to use, however I suggest we use #weight => 0 for settings and, #weight => 10 for 'scripts'.
If contrib / custom wants to add before 'settings', they can use a negative weight.
If they want to add it in between, they can use a weight between 0 and 10, etc.
What do you think?
Comment #35
markhalliwellI was thinking something a little simpler:
And then just explicitly set them at the end:
edit: accounting for new weights and counting element children on $scripts
Comment #36
markhalliwellTrue, but it's also possible for hook_element_info_alter() to allow callbacks to be prepended prior to this being invoked. If some contrib/custom code already populates this, then this needs to account for that.
Comment #37
polI do agree with @Fabian in #34.
And I don't have anything to say on @Mark's code, one or the other, for me it's the same.
I let you guys decide on which direction you want to take, then I'll update the patch.
Comment #38
polI guess the idea here is to make sure that the weight of the settings is bigger than the one from scripts.
However, if a previous
pre_rendermodifies the weight of scripts and set a value higher than 10, then it will break.I would suggest to do:
WDYT ?
Comment #39
markhalliwellIf this were staying internal (like it was) then I wouldn't have an issue with the current approach.
However, given that this is becoming a #pre_render callback this means it's being opened up to the entire system that is the "Render API".
It needs to follow the paradigm of allowing the possibility of #pre_render callbacks being invoked prior to this one (because contrib/custom code can inject their own, before cores
array_unshift()) and populate similar keys/properties.True, yes, it should be
$settings['#weight'] = $scripts['#weight'] + 10;Comment #40
polAll good guys, going to update the patch taking all of this into account.
Comment #41
fabianx commented#39 I agree, but I think it's feasible that we reserve the right to exclusively set 'scripts' and 'settings' keys in our #pre_render callback return.
Would it not be also a kinda WTF if the default settings would not be there anymore once you set 'settings' in your pre-pre-render callback?
Also we wanted the possibility to change the original $keys, so I think preserving that has a priority?
Comment #42
pol@Mark,
I think it would maybe be better to delegate the alteration of the
$elementsvariable at the end of both loops, according to me. It's easier to understand than dealing with index like you propose in your alternative in #35.Would it be ok for you to follow what I propose in patch #33 ?
@Fabian, any point of view on this ?
As soon as we agree on something, I'll reroll a proper patch.
Thanks guys!
Comment #43
markhalliwellNo, that went out the window the moment this became a #pre_render callback in the render system.
What happens to core callbacks that don't work with contrib/custom code? They get replaced with duplicate code that fixes the code so it can work with prior callbacks.
I'm not saying that I have a solid use-case here, other than it is now technically possible and to ignore that would be extremely shortsighted.
This is exactly what I'm saying the WTF is and why #35 is a must for a #pre_render callback.
If we check for these children and use them as a starting point (instead of an empty array), we're actually appending new data to existing data (from a pre-pre-render callback) and then explicitly [re]setting the child elements at the end.
Comment #44
polI do agree @Mark, a
#pre_rendercallback should not "reserve" some keys because now that "scripts" is an element, it can be altered through custom hooks... and who knows what happen in there... but it cannot be overriden.Comment #45
markhalliwellTo clarify, #33 and #35 are two different approaches.
#33 creates empty array variables and ignores any pre-pre-render children set
#35 creates array variables from existing children of a pre-pre-render, if set, or an empty array if not set
Comment #46
pol@Mark,
I don't think #33 ignores any pre-
#pre_renderchildren set.It is using non-destructive assignement (+=) everywhere when it comes to fill in the
$elementsvariable.Comment #47
markhalliwellTo further clarify:
#33 re-loops over the items unnecessarily and re-introduces the issue I brought up in #20.2 by re-indexing array items and losing any aggregated associative keys.
While #33 does technically "add" using the array default method and then subsequently iterates over everything to add it to the element, this does not constitute the "same result" as #35 and why I consider them vastly different approaches.
Comment #48
markhalliwellA little cleaner using the default array method for the weights:
Comment #49
polOk guys,
I have uploaded here two versions of the patch, I let you guys decide.
Comment #50
polAfter some private discussions on Slack, I will follow the @Mark's patch here.
@Mark, could you review the last one I posted there and give me some (last) feedback ?
Comment #51
markhalliwellOne tiny doc nit after re-reading the entire thing again. This should start with a normal word/capital letter and a single line according to docs docs.
Comment #52
polComment #53
fabianx commentedI think this will break - I just noticed it.
Would that be an empty render array child or empty markup?
Ohhh - I see now that as '' == [] => empty('') == TRUE, so this will work fine.
Even if it looks a little bit strange.
---
Marking for commit. The plan would be to commit this within the next week or so.
Great work!
Thanks for the explanation, Mark. I finally got how you wanted to structure this.
I agree that the solution that we now have is nicely documented and allows easy extending things.
++
Comment #54
fabianx commentedHmmmm - thinking about this a little bit I think we should explain the returned structure and also show what can be passed in, in here.
Comment #55
polComment has been updated.
Comment #56
fabianx commentedI think this is good to go now again, but leaving up for feedback from Mark and potentially others.
Planned commit of this is within 1 week.
Comment #57
markhalliwellLGTM
Comment #59
markhalliwellComment #60
polGreat ! Thank you guys for your valuable feedback!
Comment #61
pol