kopia lustrzana https://github.com/backface/turtlestitch
				
				
				
			added @xBZZZZ's JSCompiler fixes (was #3009)
							rodzic
							
								
									af04d1a4fb
								
							
						
					
					
						commit
						d42d01f9e0
					
				|  | @ -23,6 +23,9 @@ | |||
| * **Translation Updates:** | ||||
|     * German | ||||
| 
 | ||||
| ### 2022-03-25 | ||||
| * threads: added @xBZZZZ's JSCompiler fixes (was #3009) | ||||
| 
 | ||||
| ### 2022-03-24 | ||||
| * German translation update for "costume name" | ||||
| * threads, extension: decodeURI XHR requests | ||||
|  |  | |||
							
								
								
									
										135
									
								
								src/threads.js
								
								
								
								
							
							
						
						
									
										135
									
								
								src/threads.js
								
								
								
								
							|  | @ -7507,9 +7507,10 @@ VariableFrame.prototype.allNames = function (upTo, includeHidden) { | |||
| function JSCompiler(aProcess) { | ||||
| 	this.process = aProcess; | ||||
| 	this.source = null; // a context
 | ||||
|  	this.gensyms = null; // temp dictionary for parameter substitutions
 | ||||
|  	this.gensyms = new Map(); // temp dictionary for parameter substitutions
 | ||||
|   	this.implicitParams = null; | ||||
|    	this.paramCount = null; | ||||
|     this.scriptVarCounter = null; | ||||
| } | ||||
| 
 | ||||
| JSCompiler.prototype.toString = function () { | ||||
|  | @ -7519,12 +7520,19 @@ JSCompiler.prototype.toString = function () { | |||
| JSCompiler.prototype.compileFunction = function (aContext, implicitParamCount) { | ||||
|     var block = aContext.expression, | ||||
|   		parameters = aContext.inputs, | ||||
|         parms = [], | ||||
|         hasEmptySlots = false, | ||||
|         i; | ||||
|         plength = 0; | ||||
| 
 | ||||
| 	this.source = aContext; | ||||
|     this.implicitParams = implicitParamCount || 1; | ||||
|     if (implicitParamCount == null || implicitParamCount === '') { | ||||
|         this.implicitParams = 1; | ||||
|     } else { | ||||
|         this.implicitParams = implicitParamCount >> 0; | ||||
|         if (this.implicitParams < 0) { | ||||
|             // use 1 if implicitParamCount doesn't make sense
 | ||||
|             this.implicitParams = 1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	// scan for empty input slots
 | ||||
|  	hasEmptySlots = !isNil(detect( | ||||
|  | @ -7533,7 +7541,7 @@ JSCompiler.prototype.compileFunction = function (aContext, implicitParamCount) { | |||
|     )); | ||||
| 
 | ||||
|     // translate formal parameters into gensyms
 | ||||
|     this.gensyms = new Map(); | ||||
|     this.gensyms.clear(); | ||||
|     this.paramCount = 0; | ||||
|     if (parameters.length) { | ||||
|         // test for conflicts
 | ||||
|  | @ -7546,33 +7554,34 @@ JSCompiler.prototype.compileFunction = function (aContext, implicitParamCount) { | |||
|         } | ||||
|         // map explicit formal parameters
 | ||||
|         parameters.forEach((pName, idx) => { | ||||
|         	var pn = 'p' + idx; | ||||
|             parms.push(pn); | ||||
|         	this.gensyms.set(pName, pn); | ||||
|         	this.gensyms.set(pName, 'p[' + idx + ']'); | ||||
|         }); | ||||
|         plength = parameters.length; | ||||
|     } else if (hasEmptySlots) { | ||||
|     	if (this.implicitParams > 1) { | ||||
|         	for (i = 0; i < this.implicitParams; i += 1) { | ||||
|          		parms.push('p' + i); | ||||
|          	} | ||||
|      	} else { | ||||
|         	// allow for a single implicit formal parameter
 | ||||
|         	parms = ['p0']; | ||||
|         } | ||||
|     	plength = this.implicitParams; | ||||
|     } | ||||
| 
 | ||||
|     // compile using gensyms
 | ||||
| 
 | ||||
|     if (block instanceof CommandBlockMorph) { | ||||
|         return Function.apply( | ||||
|             null, | ||||
|             parms.concat([this.compileSequence(block)]) | ||||
|         ); | ||||
|     this.scriptVarCounter = 0; | ||||
|     var code = 'proc=p.pop();\n'; | ||||
|     if (plength) { | ||||
|         // fill missing parameters with empty string
 | ||||
|         code += 'while(' + plength + '>p.length)p.push("");\n'; | ||||
|     } | ||||
|     return Function.apply( | ||||
|         null, | ||||
|         parms.concat(['return ' + this.compileExpression(block)]) | ||||
|     ); | ||||
|     if (block instanceof CommandBlockMorph) { | ||||
|         code += this.compileSequence(block) + 'return ""'; | ||||
|     } else { | ||||
|         code += 'return ' + this.compileExpression(block); | ||||
|     } | ||||
|     block = 'var '; | ||||
|     this.gensyms.forEach(function (value) { | ||||
|         if (value.charAt(0) === 's') { | ||||
|             // declare script variable
 | ||||
|             block += value + '=0,'; | ||||
|         } | ||||
|     }); | ||||
|     return Function('...p', block + code); | ||||
| }; | ||||
| 
 | ||||
| JSCompiler.prototype.compileExpression = function (block) { | ||||
|  | @ -7607,21 +7616,49 @@ JSCompiler.prototype.compileExpression = function (block) { | |||
|     case 'evaluate': | ||||
|         return 'invoke(' + | ||||
|             this.compileInput(inputs[0]) + | ||||
|             ',' + | ||||
|             ', ' + | ||||
|             this.compileInput(inputs[1]) + | ||||
|             ')'; | ||||
| 
 | ||||
|     // special command forms
 | ||||
|     case 'doSetVar': // redirect var to process
 | ||||
|         return 'arguments[arguments.length - 1].setVarNamed(' + | ||||
|     case 'doDeclareVariables': | ||||
|         block = ''; | ||||
|         inputs[0].inputs().forEach(({children: {0: {blockSpec: name}}}) => { | ||||
|             if (gensym = this.gensyms.get(name)) { | ||||
|                 // we already have that script variable, just set it to 0
 | ||||
|                 block += gensym + '='; | ||||
|                 return; | ||||
|             } | ||||
|             var gensym = 's' + this.scriptVarCounter++; | ||||
|             block += gensym + '='; | ||||
|             this.gensyms.set(name, gensym); | ||||
|         }); | ||||
|         return block + '0'; | ||||
|     case 'reportGetVar': | ||||
|         return this.gensyms.get(block.blockSpec) || ('proc.getVarNamed("' + | ||||
|             this.escape(block.blockSpec) + | ||||
|             '")'); | ||||
|     case 'doSetVar': | ||||
|         if (inputs[0] instanceof ArgMorph && (target = this.gensyms.get(inputs[0].evaluate()))) { | ||||
|             // setting gensym (script or argument) variable
 | ||||
|             return target + ' = ' + this.compileInput(inputs[1]); | ||||
|         } | ||||
|         // redirect var to process
 | ||||
|         return 'proc.setVarNamed(' + | ||||
|             this.compileInput(inputs[0]) + | ||||
|             ',' + | ||||
|             ', ' + | ||||
|             this.compileInput(inputs[1]) + | ||||
|             ')'; | ||||
|     case 'doChangeVar': // redirect var to process
 | ||||
|         return 'arguments[arguments.length - 1].incrementVarNamed(' + | ||||
|     case 'doChangeVar': | ||||
|         if (inputs[0] instanceof ArgMorph && (target = this.gensyms.get(inputs[0].evaluate()))) { | ||||
|             return '{const d=' + this.compileInput(inputs[1]) + | ||||
|                 ',v=parseFloat(' + target + ');' + | ||||
|                 target + '=isNaN(v)?d:v+parseFloat(d)}'; | ||||
|         } | ||||
|         // redirect var to process
 | ||||
|         return 'proc.incrementVarNamed(' + | ||||
|             this.compileInput(inputs[0]) + | ||||
|             ',' + | ||||
|             ', ' + | ||||
|             this.compileInput(inputs[1]) + | ||||
|             ')'; | ||||
|     case 'doReport': | ||||
|  | @ -7640,7 +7677,9 @@ JSCompiler.prototype.compileExpression = function (block) { | |||
|             '} else {\n' + | ||||
|             this.compileSequence(inputs[2].evaluate()) + | ||||
|             '}'; | ||||
| 
 | ||||
|     case 'reportBoolean': | ||||
|     case 'reportNewList': | ||||
|         return this.compileInput(inputs[0]); | ||||
|     default: | ||||
|         target = this.process[selector] ? this.process | ||||
|             : (this.source.receiver || this.process.receiver); | ||||
|  | @ -7649,13 +7688,11 @@ JSCompiler.prototype.compileExpression = function (block) { | |||
|         if (isSnapObject(target)) { | ||||
|             if (rcvr === 'SpriteMorph.prototype') { | ||||
|                 // fix for blocks like (x position)
 | ||||
|                 rcvr = 'arguments[arguments.length - 1].blockReceiver()'; | ||||
|             }  | ||||
|             return rcvr + '.' + selector + '(' + args +')'; | ||||
|                 rcvr = 'proc.blockReceiver()'; | ||||
|             } | ||||
|             return rcvr + '.' + selector + '(' + args + ')'; | ||||
|         } else { | ||||
|             return 'arguments[arguments.length - 1].' + | ||||
|                 selector + | ||||
|                 '(' + args + ')'; | ||||
|             return 'proc.' + selector + '(' + args + ')'; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | @ -7670,13 +7707,13 @@ JSCompiler.prototype.compileSequence = function (commandBlock) { | |||
| 
 | ||||
| JSCompiler.prototype.compileInfix = function (operator, inputs) { | ||||
|     return '(' + this.compileInput(inputs[0]) + ' ' + operator + ' ' + | ||||
|         this.compileInput(inputs[1]) +')'; | ||||
|         this.compileInput(inputs[1]) + ')'; | ||||
| }; | ||||
| 
 | ||||
| JSCompiler.prototype.compileInputs = function (array) { | ||||
|     var args = ''; | ||||
|     array.forEach(inp => { | ||||
|         if (args.length) { | ||||
|         if (args) { | ||||
|             args += ', '; | ||||
|         } | ||||
|         args += this.compileInput(inp); | ||||
|  | @ -7692,7 +7729,7 @@ JSCompiler.prototype.compileInput = function (inp) { | |||
|         if (this.implicitParams > 1) { | ||||
|          	if (this.paramCount < this.implicitParams) { | ||||
|             	this.paramCount += 1; | ||||
|              	return 'p' + (this.paramCount - 1); | ||||
|              	return 'p[' + (this.paramCount - 1) + ']'; | ||||
|         	} | ||||
|             throw new Error( | ||||
|                 localize('expecting') + ' ' + this.implicitParams + ' ' | ||||
|  | @ -7700,7 +7737,7 @@ JSCompiler.prototype.compileInput = function (inp) { | |||
|                     + this.paramCount | ||||
|             ); | ||||
|         } | ||||
| 		return 'p0'; | ||||
| 		return 'p[0]'; | ||||
|     } else if (inp instanceof MultiArgMorph) { | ||||
|         return 'new List([' + this.compileInputs(inp.inputs()) + '])'; | ||||
|     } else if (inp instanceof ArgLabelMorph) { | ||||
|  | @ -7729,16 +7766,6 @@ JSCompiler.prototype.compileInput = function (inp) { | |||
|             ); | ||||
|         } | ||||
|     } else if (inp instanceof BlockMorph) { | ||||
|         if (inp.selector === 'reportGetVar') { | ||||
|         	if (this.gensyms.has(inp.blockSpec)) { | ||||
|             	// un-quoted gensym:
 | ||||
|             	return this.gensyms.get(inp.blockSpec); | ||||
|         	} | ||||
|          	// redirect var query to process
 | ||||
|             return 'arguments[arguments.length - 1].getVarNamed("' + | ||||
|             	this.escape(inp.blockSpec) + | ||||
|             	'")'; | ||||
|         } | ||||
|         return this.compileExpression(inp); | ||||
|     } else { | ||||
|         throw new Error( | ||||
|  | @ -7752,7 +7779,7 @@ JSCompiler.prototype.compileInput = function (inp) { | |||
| JSCompiler.prototype.escape = function(string) { | ||||
|     // make sure string is a string
 | ||||
|     string += ''; | ||||
|     var len = string.length, i = 0, char, escaped = '', safe_chars =  | ||||
|     var len = string.length, i = 0, char, escaped = '', safe_chars = | ||||
|         ' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$' + | ||||
|         "%&'()*+,-./:;<=>?@[]^_`{|}~"; | ||||
|     while (len > i) { | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Jens Mönig
						Jens Mönig