Skip to content

Commit

Permalink
Properly handle <!-- <script </script in JavaScript
Browse files Browse the repository at this point in the history
Fixes #1379
  • Loading branch information
marschall authored Jul 16, 2024
1 parent cb4b8ef commit 597e6d0
Show file tree
Hide file tree
Showing 30 changed files with 132 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ tests-creation
testHtml
self
assert: (self jQuery html: [ :html | html div: 'foo' ])
equals: self function , '("<div>foo<\/div>")'.
equals: self function , '("<div>foo</div>")'.
self
assert: (self jQuery html: [ :html | html div title: 'foo'; with: 'bar' ])
equals: self function , '("<div title=\"foo\">bar<\/div>")'
equals: self function , '("<div title=\"foo\">bar</div>")'
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ tests-with
testWithBlock
self
assert: (self jQuery: [ :html | html heading: 'jQuery' ])
equals: self function , '("<h1>jQuery<\/h1>")'
equals: self function , '("<h1>jQuery</h1>")'
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ tests-modifying
testAfter
self
assert: ((self jQuery: 'p') after: [ :html | html strong: 'Hello' ])
equals: self function , '("p").after("<strong>Hello<\/strong>")'.
equals: self function , '("p").after("<strong>Hello</strong>")'.
self
assert: ((self jQuery: 'span') insertAfter: '#foo')
equals: self function , '("span").insertAfter("#foo")'
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ tests-modifying
testAppend
self
assert: ((self jQuery: 'p') append: [ :html | html strong: 'Hello' ])
equals: self function , '("p").append("<strong>Hello<\/strong>")'.
equals: self function , '("p").append("<strong>Hello</strong>")'.
self
assert: ((self jQuery: 'span') appendTo: '#foo')
equals: self function , '("span").appendTo("#foo")'
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ tests-modifying
testBefore
self
assert: ((self jQuery: 'p') before: [ :html | html strong: 'Hello' ])
equals: self function , '("p").before("<strong>Hello<\/strong>")'.
equals: self function , '("p").before("<strong>Hello</strong>")'.
self
assert: ((self jQuery: 'span') insertBefore: '#foo')
equals: self function , '("span").insertBefore("#foo")'
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ testHtml
equals: self function , '("div").html()'.
self
assert: ((self jQuery: 'div') html: [ :html | html div ])
equals: self function , '("div").html("<div><\/div>")'
equals: self function , '("div").html("<div></div>")'
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ tests-modifying
testPrepend
self
assert: ((self jQuery: 'p') prepend: [ :html | html strong: 'Hello' ])
equals: self function , '("p").prepend("<strong>Hello<\/strong>")'.
equals: self function , '("p").prepend("<strong>Hello</strong>")'.
self
assert: ((self jQuery: 'span') prependTo: '#foo')
equals: self function , '("span").prependTo("#foo")'
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ tests-modifying
testReplace
self
assert: ((self jQuery: 'p') replaceWith: [ :html | html emphasis: 'Hello' ])
equals: self function , '("p").replaceWith("<em>Hello<\/em>")'.
equals: self function , '("p").replaceWith("<em>Hello</em>")'.
self
assert: ((self jQuery html: [ :html | html div: 'Hello' ]) replaceAll: '.foo')
equals: self function , '("<div>Hello<\/div>").replaceAll(".foo")'
equals: self function , '("<div>Hello</div>").replaceAll(".foo")'
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ tests-modifying
testWrap
self
assert: ((self jQuery: 'p') wrap: [ :html | html strong ])
equals: self function , '("p").wrap("<strong><\/strong>")'.
equals: self function , '("p").wrap("<strong></strong>")'.
self
assert: ((self jQuery: 'p') wrapAll: [ :html | html div ])
equals: self function , '("p").wrapAll("<div><\/div>")'.
equals: self function , '("p").wrapAll("<div></div>")'.
self
assert: ((self jQuery: 'p') wrapInner: [ :html | html span ])
equals: self function , '("p").wrapInner("<span><\/span>")'
equals: self function , '("p").wrapInner("<span></span>")'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
encoding - private
encodeLessThanIn: aString at: anInteger on: aStream
"Encode <, answer the number of characters coded"

#('<!--' '<script' '</script') do: [ :each |
(self hasString: aString subString: each at: anInteger) ifTrue: [
aStream nextPutAll: '\x3C'.
aStream greaseNext: each size - 1 putAll: each startingAt: 2.
^ each size ]. ].
aStream nextPut: $<.
^ 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
encoding - private
encodeNonAsciiCharacter: aCharacter withCodePoint: anInteger on: aStream
"U+2028 and U+2029 have to be treated as new lines"

anInteger = 16r2028 "Line separator"
ifTrue: [ aStream nextPutAll: '\u2028' ]
ifFalse: [
anInteger = 16r2029 "Paragraph separator"
ifTrue: [ aStream nextPutAll: '\u2029' ]
ifFalse: [ aStream nextPut: aCharacter ] ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
encoding - private
encodeString: aString fastOn: aStream
"Encode a String without <, much simpler implementation that can use #to:do"

1 to: aString size do: [ :index |
| char value encoded |
char := aString at: index.
value := char greaseInteger.
value < JavascriptCharacters size
ifFalse: [
self encodeNonAsciiCharacter: char withCodePoint: value on: aStream ]
ifTrue: [
encoded := JavascriptCharacters at: value + 1.
"we use nil markers becausee #isNil is faster than #isString because it's not
actually sent"
encoded isNil
ifTrue: [ aStream nextPut: char ]
ifFalse: [ aStream nextPutAll: encoded ] ] ]
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,8 @@ encoding
encodeString: aString on: aStream
"Strings have a complicated encoding in Javascript, try to optimize their serialization."

| last |
aStream nextPut: $".
1 to: aString size do: [ :index |
| char value encoded |
char := aString at: index.
value := char greaseInteger.
value < JavascriptCharacters size
ifFalse: [
"U+2028 and U+2029 have to be treated as new lines"
value = 16r2028 "Line separator"
ifTrue: [ aStream nextPutAll: '\u2028' ]
ifFalse: [
value = 16r2029 "Paragraph separator"
ifTrue: [ aStream nextPutAll: '\u2029' ]
ifFalse: [ aStream nextPut: char ] ] ]
ifTrue: [
encoded := JavascriptCharacters at: value + 1.
"we use nil markers becausee #isNil is faster than #isString because it's not
actually sent"
encoded isNil
ifTrue: [
"avoid that browsers mistakenly take the output as a closing tag"
(last = $< and: [ char = $/ ])
ifTrue: [ aStream nextPutAll: '\/' ]
ifFalse: [ aStream nextPut: char ] ]
ifFalse: [ aStream nextPutAll: encoded ] ].
last := char ].
(aString indexOf: $<) = 0
ifTrue: [ self encodeString: aString fastOn: aStream ]
ifFalse: [ self encodeString: aString slowOn: aStream ].
aStream nextPut: $"
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
encoding - private
encodeString: aString slowOn: aStream
"Strings with < a complicated encoding in Javascript"

| index size |
index := 1.
size := aString size.
[ index <= size ] whileTrue: [
| char value encoded |
char := aString at: index.
value := char greaseInteger.
value < JavascriptCharacters size
ifFalse: [
self encodeNonAsciiCharacter: char withCodePoint: value on: aStream.
index := index + 1. ]
ifTrue: [
encoded := JavascriptCharacters at: value + 1.
"we use nil markers becausee #isNil is faster than #isString because it's not
actually sent"
encoded isNil
ifTrue: [
"avoid that browsers mistakenly take the output as a closing tag"
char = $<
ifTrue: [
index := index + (self encodeLessThanIn: aString at: index on: aStream) ]
ifFalse: [
aStream nextPut: char.
index := index + 1. ] ]
ifFalse: [
aStream nextPutAll: encoded.
index := index + 1 ] ] ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
encoding - private
hasString: aString subString: aSubstring at: anIntegerIndex
"Strings with < a complicated encoding in Javascript"

(anIntegerIndex + aSubstring size) > (aString size + 1) ifTrue: [
^ false ].
1 to: aSubstring size do: [ :index |
(aString at: anIntegerIndex + index - 1) = (aSubstring at: index)
ifFalse: [ ^ false ] ].
^ true
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
SystemOrganization addCategory: #'Javascript-Core'!
SystemOrganization addCategory: 'Javascript-Core-Decorations'!
self packageOrganizer ensurePackage: #'Javascript-Core' withTags: #('Decorations')!
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
tests-encoding
testHasStringSubStringAt
self assert: (JSStream hasString: 'Seaside' subString: 'Seaside' at: 1).
self assert: (JSStream hasString: 'Seaside' subString: 'easide' at: 2).
self deny: (JSStream hasString: 'Seaside' subString: 'Seaside' at: 2).
self deny: (JSStream hasString: 'Seaside' subString: 'waytoolongtofix' at: 1).
Original file line number Diff line number Diff line change
@@ -1 +1 @@
SystemOrganization addCategory: #'Javascript-Tests-Core'!
self packageOrganizer ensurePackage: #'Javascript-Tests-Core' withTags: #()!

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ testModifyingInsert
equals: '$(this).insert("1")'.
self
assert: (self element insertAfter: [ :r | r div ])
equals: '$(this).insert({"after":"<div><\/div>"})'.
equals: '$(this).insert({"after":"<div></div>"})'.
self
assert: (self element insertBefore: 'abc')
equals: '$(this).insert({"before":"abc"})'.
self
assert: (self element insertTop: [ :r | r span: 5 ])
equals: '$(this).insert({"top":"<span>5<\/span>"})'.
equals: '$(this).insert({"top":"<span>5</span>"})'.
self
assert: (self element insertBottom: '5')
equals: '$(this).insert({"bottom":"5"})'
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ testModifyingReplace
equals: '$(this).replace("foo")'.
self
assert: (self element replace: [ :r | r div id: 'foo' ])
equals: '$(this).replace("<div id=\"foo\"><\/div>")'
equals: '$(this).replace("<div id=\"foo\"></div>")'
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ testModifyingUpdate
equals: '$("foo").update("bar")'.
self
assert: (self element update: [ :r | r div: 'bar' ])
equals: '$(this).update("<div>bar<\/div>")'
equals: '$(this).update("<div>bar</div>")'
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ tests-rendering
testRenderedHtml
self
assert: [ :html | html div script: (html scriptaculous element update: [ :r | r span ]) ]
renders: '<div id="id1"></div><script type="text/javascript">$("id1").update("<span><\/span>");</script>'
renders: '<div id="id1"></div><script type="text/javascript">$("id1").update("<span></span>");</script>'
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ testRenderedHtmlWithScripts
assert: [ :html |
html div script: (html scriptaculous element remove).
html div script: (html scriptaculous element update: [ :r | r span ]) ]
renders: '<div id="id1"></div><div id="id2"></div><script type="text/javascript">$("id1").remove();$("id2").update("<span><\/span>");</script>'
renders: '<div id="id1"></div><div id="id2"></div><script type="text/javascript">$("id1").remove();$("id2").update("<span></span>");</script>'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(name 'Prototype-Tests-Core-pmm.21' message '- fix test' id 'bfad35bc-5735-0d00-b128-7dde02b3bc31' date '24 October 2018' time '11:20:33.301536 am' author 'pmm' ancestors ((name 'Prototype-Tests-Core-pmm.20' message 'Add Prototype script generator- fixes #1026' id '558e804a-5735-0d00-b10a-603302b3bc31' date '24 October 2018' time '10:48:45.604612 am' author 'pmm' ancestors ((name 'Prototype-Tests-Core-pmm.19' message 'Add mapping to Prototype''s PeriodicalExecuter- fixes #925' id '558de728-e331-0d00-8e86-62c808033da6' date '10 September 2018' time '12:00:10.83962 pm' author 'pmm' ancestors ((name 'Prototype-Tests-Core-pmm.18' message 'Issue 822: Drop clever CDATA trick' id '64717be3-c73b-4e85-b16c-c322d1137294' date '23 August 2014' time '10:03:16 am' author 'pmm' ancestors () stepChildren ())) stepChildren ())) stepChildren ())) stepChildren ())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
public
with: aString
with: aStringOrJSObject

self attributes
at: 'type'
ifAbsentPut: [ 'text/javascript' ].
super with: [
aString ifNotNil: [
self document nextPutAll: aString greaseString ] ]
aStringOrJSObject ifNotNil: [
aStringOrJSObject isJavascript
ifTrue: [
self document stream javascript: aStringOrJSObject ]
ifFalse: [
"we want to render a String directly and avoid escaping "" and '"
self document nextPutAll: aStringOrJSObject greaseString ] ] ]
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ testNestedScripts
on: 'click'
selector: '.class'
do: (JSStream on: 'alert(''nested script''')) ]) ]
gives: '<html><head><title></title></head><body onload="onLoad()"><a id="id2"></a><script type="text/javascript">function onLoad(){$("#id2").closest("div").append("<div id=\"id1\"><\/div><script type=\"text/javascript\">$(\"#id1\").on(\"click\",\".class\",function(){alert(''nested script''});<\/script>");};</script></body></html>'
gives: '<html><head><title></title></head><body onload="onLoad()"><a id="id2"></a><script type="text/javascript">function onLoad(){$("#id2").closest("div").append("<div id=\"id1\"></div>\x3Cscript type=\"text/javascript\">$(\"#id1\").on(\"click\",\".class\",function(){alert(''nested script''});\x3C/script>");};</script></body></html>'
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
testing
testScripts
"https://html.spec.whatwg.org/#restrictions-for-contents-of-script-elements
"
self
assert: [ :html |
html
script: (html logger log: '<!-- <script></script>');
paragraph: 'Test Paragraph' ]
gives: '<html><head><title></title></head><body onload="onLoad()"><script type="text/javascript">console.log("\x3C!-- \x3Cscript>\x3C/script>")</script><p>Test Paragraph</p><script type="text/javascript">function onLoad(){};</script></body></html>'
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ assert: aBlock gives: aString
fullDocument: false;
rootBlock: aBlock;
render: aBlock.
self assert: aString = html
self assert: aString equals: html
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ assert: aBlock gives: aString
| xml |
xml := WAXmlCanvas builder
render: aBlock.
self assert: aString = xml
self assert: aString equals: xml

0 comments on commit 597e6d0

Please sign in to comment.