Skip to content
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

Shorter general code generator? #3

Open
837951602 opened this issue Feb 6, 2017 · 29 comments
Open

Shorter general code generator? #3

837951602 opened this issue Feb 6, 2017 · 29 comments

Comments

@837951602
Copy link
Contributor

[All Supported Env.]
'!!!!!' 26486
unescape(unescape("false2521false2521false2521false2521false2521".split(false).join("%"))) 22547
unescape("false21false21false21false21false21".split(false).join("%")) 17058, but with 'b' or 'c' escaped that'd be too long

(though I don't know what code generated by the present way

@837951602
Copy link
Contributor Author

OK after I remove the () I get the '!!!!!' is turned into String.fromCharCode(33,33,33,33,33)

@837951602
Copy link
Contributor Author

For larger code it may be a better solution to make a bootstrap(a function that modify self's attrib and return itself so can be called with a list of (xxx), with 10 xxx shorter than 6 EMPTY, [], +[], ![], [[]], !![], +!![], [![]], [+[]], []+[], have 100>127-32 and encode the rest chars. I wonder if String.fromCharCode have its space

@837951602
Copy link
Contributor Author

837951602 commented Feb 12, 2017

Testrecord:
[].filter.constructor(unescape("alertfalse28false27false48ellofalse2cfalse20false57false6frldfalse21false27false29".split(false).join("%")))() 19617
alert('Hello, World!') 28779
even if use "eval(...)" it would be shorter

@837951602
Copy link
Contributor Author

837951602 commented Mar 10, 2017

';;;' 25961
unescape('%3B%3B%3B') 25867
unescape(unescape('false3false42false3false42false3false42'.split(false).join('%'))) 22115
unescape('false3Bfalse3Bfalse3B'.split(false).join('%')) 21048
unescape(3201714281..toString(15).split(1).join('%')) 20144, but require short source
'falsefalsefalse'.split(false).join(';') 18124, but requires almost same char and the left ones can be expressed easily
[].constructor(4).join(';') 15794, but require fully same char
String.prototype.repeat is not defined on IE and Maxthon, so not listed here

@fasttime
Copy link
Owner

I believe something like Array(4).join(";") should be almost always the best choice with repeated substrings (where Array is [].constructor).

@fasttime
Copy link
Owner

Well there is also ";".repeat(3), although it doesn't work in older engines.

@837951602
Copy link
Contributor Author

[IE9]
unescape('false21false21false21'.split(false).join('%')) 9503
'!!!' 9366
[].filter.constructor('return({}+false).constructor.fromCharCode('+'33false33false33'.split(false)+')')() 9120

@fasttime
Copy link
Owner

This is still longer than [].constructor(4).join("!"). But I appreciate the idea.

@837951602
Copy link
Contributor Author

It's not required to be the same char.

[IE9]
'!' 6168c
([]+[]).constructor.fromCharCode(33) 5098c

I chose IE9 because Uppercase Letters are cheaper than in other environment without atob

@fasttime
Copy link
Owner

Seems legit. This can be probably integrated in createCharCodesEncoding somehow.

@837951602
Copy link
Contributor Author

837951602 commented Mar 15, 2017

For the fromCharCode(list), [].filter.constructor('return(isNaN+false).constructor.fromCharCode('+'33false64false35'.split(false)+')')() seems to be the best way, but not sure if best for every environment

@fasttime
Copy link
Owner

fasttime commented Mar 15, 2017

Apparently, return String... is cheaper for ["CAPITAL_HTML", "ENTRIES_OBJ"]: https://jsfiddle.net/wrspc5g5/
Granted, that's a feature combination not found anywhere, but still.

@837951602
Copy link
Contributor Author

ok I didn't realize 'S' can be expressed by ''['su'+'[Obje...'[2]]()[1] ^_^
So is there any more possible winner?

@837951602
Copy link
Contributor Author

837951602 commented Mar 15, 2017

The unescape optimize seems not so simple, but still not so complex:
for basic chars, it should be directly placed
for % it should be false instead of false25 if won't be treated as an encoder and falsefalse20 if in code and may be treated as an encoder
false should have one char encoded
In my boot in jfuery, I used !1(it should have been !true) to mean false, cuz it's cheaper; but not false in string
...
Same as byeval

@fasttime
Copy link
Owner

That's because in IE, "".sub() + "" produces <SUB></SUB> rather than <sub></sub>, but I can't think of how to make (isNaN+false).constructor shorter, so there are no more winners by now.
Sure, the unescape optimization wouldn't be too difficult. The problem is that I'm still fighting to fix some bugs and get old stuff straight, and I don't know when I'll have the time to implement all those improvements.
If there is something you want to help with I can try to guide you step-by-step, otherwise I promise I'll work on all of those, but I just can't say when.

@837951602
Copy link
Contributor Author

I meant it's harder for me. I don't know too much about the code. Every time I want to see how you did, I unassemble the generated code - -

@fasttime
Copy link
Owner

That's no surprise since I wrote nearly all of the code myself, and sometimes I must use a debugger to understand what I did. But if you have any questions just feel free to ask.

@837951602
Copy link
Contributor Author

[IE9, isNaN fix]
[].filter.constructor('return(isNaN+false).constructor.fromCharCode(33,33,33,33,33)')() 8967c
'!!!!!' 8954c
[].filter.constructor('return(isNaN+false).constructor.fromCharCode(3'+[].slice.call('33')+[].slice.call('33')+[].slice.call('33')+[].slice.call('33')+'3)')() 8883c

@837951602
Copy link
Contributor Author

[IE9]
'!@#$%' on jscrew.it(old version) 9507
'!@#$%' on local(new) 9019
[].filter.constructor("return status.constructor.fromCharCode(" + "33false64false35false36false37".split(false) + ")")() 8840

@837951602
Copy link
Contributor Author

encode('"\\\\"','UNEVAL').length
3525
encode('"!"','UNEVAL').length
10706
encode('"错"','UNEVAL').length
7713
encode('[].filter.constructor("return\\"\\\\u9519\\"")()','UNEVAL').length
7713
encode('[].filter.constructor("return\\"\\\\u0021\\"")()','UNEVAL').length
7616

@fasttime
Copy link
Owner

fasttime commented Apr 5, 2017

Sometimes it's better to use legacy octal escape sequences, e.g. \\41 instead of \\u0021. These should be fine also in strict mode code since they are parsed by the Function constructor, but I'll have to check with ES6 modules.

@837951602
Copy link
Contributor Author

837951602 commented Apr 5, 2017

So '\040' should be eval("'\\040'") , not Function("return '\\040'")()?
#4
Update:
Function('"use strict";return eval')()('"\\040"') returns ' ', even if in node v6.10.0 strict mode

@fasttime
Copy link
Owner

fasttime commented Apr 5, 2017

I think that Function("return\"\\41\"")() is just fine. It should evaluate to "!" in any environment. As I understand it, #4 is about input parsing, and for that we can't assume that "\040" is inside a Function argument or something.

@837951602
Copy link
Contributor Author

I meant that even if you write "\040", it still doesn't run as normally run in strict mode

@fasttime
Copy link
Owner

fasttime commented Apr 5, 2017

True, I'll have to see what can be done.

@837951602
Copy link
Contributor Author

837951602 commented Jan 10, 2019

'fromCharCode' 16855
'from0har0ode'.split(0).join('C') 15273
well...

0 15273 debugger eval code:1:18
1 15290 debugger eval code:1:18
2 15276 debugger eval code:1:18
3 15251 debugger eval code:1:18
4 15293 debugger eval code:1:18
5 15270 debugger eval code:1:18
6 15308 debugger eval code:1:18
7 15293 debugger eval code:1:18
8 15315 debugger eval code:1:18
9 15291
b 18566 debugger eval code:1:31
c 17358 debugger eval code:1:31
g 18535 debugger eval code:1:31
i 17113 debugger eval code:1:31
j 19243 debugger eval code:1:31
k 20428 debugger eval code:1:31
l 17118 debugger eval code:1:31
n 17104 debugger eval code:1:31
p 20444 debugger eval code:1:31
q 20453 debugger eval code:1:31
s 17075 debugger eval code:1:31
t 17090 debugger eval code:1:31
u 17117 debugger eval code:1:31
v 17445 debugger eval code:1:31
w 20480 debugger eval code:1:31
x 20434 debugger eval code:1:31
y 17190 debugger eval code:1:31
z 20537

@fasttime
Copy link
Owner

I like the fromCharCode optimization because it works in all environments, it would be nice to have this in the next version. The shortest I could do is "from3har3o".split(3).join("C") + "d" + "e".

@837951602
Copy link
Contributor Author

I'm not sure if it's useful because the situation that using fromCharCode is better than escape/unescape seems to only happen when C is cheap (FONTCOLOR)

@fasttime
Copy link
Owner

fromCharCode is most useful with strings of multiple characters (e.g. "XYZ").

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants