Skip to content

Commit 8551856

Browse files
committed
GRAILS-11506 optimize performance of leftShift calls in taglibs compiled with @CompileStatic
1 parent 3727919 commit 8551856

File tree

4 files changed

+23
-12
lines changed

4 files changed

+23
-12
lines changed

grails-plugin-gsp/src/main/groovy/org/codehaus/groovy/grails/plugins/web/taglib/FormTagLib.groovy

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ import java.text.DateFormat
2222
import java.text.DateFormatSymbols
2323

2424
import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler
25+
import org.codehaus.groovy.grails.support.encoding.CodecLookup
26+
import org.codehaus.groovy.grails.support.encoding.Encoder
2527
import org.codehaus.groovy.grails.web.mapping.LinkGenerator
2628
import org.codehaus.groovy.grails.web.pages.FastStringWriter
2729
import org.codehaus.groovy.grails.web.servlet.mvc.SynchronizerTokensHolder
30+
import org.codehaus.groovy.grails.web.util.GrailsPrintWriter
2831
import org.codehaus.groovy.runtime.InvokerHelper
2932
import org.springframework.beans.factory.InitializingBean
3033
import org.springframework.context.ApplicationContext
@@ -50,7 +53,9 @@ class FormTagLib implements ApplicationContextAware, InitializingBean {
5053
ApplicationContext applicationContext
5154
RequestDataValueProcessor requestDataValueProcessor
5255
ConversionService conversionService
53-
56+
57+
CodecLookup codecLookup
58+
5459
void afterPropertiesSet() {
5560
if (applicationContext.containsBean('requestDataValueProcessor')) {
5661
requestDataValueProcessor = applicationContext.getBean('requestDataValueProcessor', RequestDataValueProcessor)
@@ -133,7 +138,7 @@ class FormTagLib implements ApplicationContextAware, InitializingBean {
133138
}
134139

135140
@CompileStatic
136-
def fieldImpl(Writer out, Map attrs) {
141+
def fieldImpl(GrailsPrintWriter out, Map attrs) {
137142
resolveAttributes(attrs)
138143

139144
attrs.value = processFormFieldValueIfNecessary(attrs.name, attrs.value, attrs.type)
@@ -144,10 +149,11 @@ class FormTagLib implements ApplicationContextAware, InitializingBean {
144149
}
145150

146151
@CompileStatic
147-
private void outputNameAsIdIfIdDoesNotExist(Map attrs, Writer out) {
152+
private void outputNameAsIdIfIdDoesNotExist(Map attrs, GrailsPrintWriter out) {
148153
if (!attrs.containsKey('id') && attrs.containsKey('name')) {
154+
Encoder htmlEncoder = codecLookup?.lookupEncoder('HTML')
149155
out << 'id="'
150-
out << InvokerHelper.invokeMethod(String.valueOf(attrs.name), "encodeAsHTML", null)
156+
out << (htmlEncoder != null ? htmlEncoder.encode(attrs.name) : attrs.name)
151157
out << '" '
152158
}
153159
}
@@ -312,11 +318,15 @@ class FormTagLib implements ApplicationContextAware, InitializingBean {
312318
* Dump out attributes in HTML compliant fashion.
313319
*/
314320
@CompileStatic
315-
void outputAttributes(Map attrs, Writer writer, boolean useNameAsIdIfIdDoesNotExist = false) {
321+
void outputAttributes(Map attrs, GrailsPrintWriter writer, boolean useNameAsIdIfIdDoesNotExist = false) {
316322
attrs.remove('tagName') // Just in case one is left
323+
Encoder htmlEncoder = codecLookup?.lookupEncoder('HTML')
317324
attrs.each { k, v ->
318325
if (v != null) {
319-
writer << "$k=\"${InvokerHelper.invokeMethod(v.toString(), "encodeAsHTML", null)}\" "
326+
writer << k
327+
writer << '="'
328+
writer << (htmlEncoder != null ? htmlEncoder.encode(v) : v)
329+
writer << '" '
320330
}
321331
}
322332
if (useNameAsIdIfIdDoesNotExist) {

grails-test-suite-web/src/test/groovy/org/codehaus/groovy/grails/web/taglib/FormTagLibTests.groovy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package org.codehaus.groovy.grails.web.taglib
33
import grails.util.MockRequestDataValueProcessor
44

55
import org.codehaus.groovy.grails.plugins.web.taglib.FormTagLib
6-
import org.codehaus.groovy.grails.support.MockApplicationContext
6+
import org.codehaus.groovy.grails.web.pages.FastStringWriter
77

88
/**
99
* Tests for the FormTagLib.groovy file which contains tags to help with the l
@@ -323,7 +323,7 @@ class FormTagLibTests extends AbstractGrailsTagTests {
323323
void testFieldImplDoesNotApplyAttributesFromPreviousInvocation() {
324324
// GRAILS-8250
325325
def attrs = [:]
326-
def out = new StringWriter()
326+
def out = new FastStringWriter()
327327
attrs.name = 'A'
328328
attrs.type = 'text'
329329
attrs.tagName = 'textField'
@@ -332,7 +332,7 @@ class FormTagLibTests extends AbstractGrailsTagTests {
332332
tag.fieldImpl out, attrs
333333
assert '<input type="text" name="A" value="" id="A" />' == out.toString()
334334

335-
out = new StringWriter()
335+
out = new FastStringWriter()
336336
attrs.name = 'B'
337337
attrs.type = 'text'
338338
attrs.tagName = 'textField'

grails-web-gsp/src/main/groovy/org/codehaus/groovy/grails/plugins/web/api/TagLibraryApi.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes;
3939
import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest;
4040
import org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException;
41+
import org.codehaus.groovy.grails.web.util.GrailsPrintWriter;
4142
import org.codehaus.groovy.grails.web.util.TagLibraryMetaUtils;
4243
import org.codehaus.groovy.grails.web.util.WithCodecHelper;
4344
import org.codehaus.groovy.runtime.InvokerHelper;
@@ -99,7 +100,7 @@ public GroovyPageBinding getPageScope(Object instance) {
99100
* @param instance The tag library instance
100101
* @return The writer to use
101102
*/
102-
public Writer getOut(Object instance) {
103+
public GrailsPrintWriter getOut(Object instance) {
103104
return GroovyPageOutputStack.currentStack().getTaglibWriter();
104105
}
105106

grails-web-gsp/src/main/groovy/org/codehaus/groovy/grails/plugins/web/taglib/SitemeshTagLib.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import org.codehaus.groovy.grails.support.encoding.Encoder
2323
import org.codehaus.groovy.grails.web.pages.FastStringWriter
2424
import org.codehaus.groovy.grails.web.pages.SitemeshPreprocessor
2525
import org.codehaus.groovy.grails.web.sitemesh.GSPSitemeshPage
26+
import org.codehaus.groovy.grails.web.util.GrailsPrintWriter
2627
import org.codehaus.groovy.grails.web.util.StreamCharBuffer
27-
import org.codehaus.groovy.runtime.InvokerHelper
2828

2929
import com.opensymphony.module.sitemesh.RequestConstants
3030

@@ -42,7 +42,7 @@ class SitemeshTagLib implements RequestConstants {
4242
static namespace = 'sitemesh'
4343
CodecLookup codecLookup
4444

45-
def captureTagContent(Writer writer, String tagname, Map attrs, Object body, boolean noEndTagForEmpty=false) {
45+
def captureTagContent(GrailsPrintWriter writer, String tagname, Map attrs, Object body, boolean noEndTagForEmpty=false) {
4646
def content = null
4747
if (body != null) {
4848
if (body instanceof Closure) {

0 commit comments

Comments
 (0)