fixed JS stack overflow issue for MAP primitive

pull/89/head
jmoenig 2019-04-23 16:43:23 +02:00
rodzic 2ce7caf4f4
commit fd7f8f803d
3 zmienionych plików z 54 dodań i 50 usunięć

Wyświetl plik

@ -67,6 +67,9 @@
* German * German
* French * French
### 2019-04-23
* Threads: fixed JS stack overflow issue for MAP primitive
### 2019-04-22 ### 2019-04-22
* Threads: fixed variable binding for "arguments", turned dictionary key into a Symbol * Threads: fixed variable binding for "arguments", turned dictionary key into a Symbol

Wyświetl plik

@ -7,7 +7,7 @@
<script type="text/javascript" src="src/morphic.js?version=2019-02-07"></script> <script type="text/javascript" src="src/morphic.js?version=2019-02-07"></script>
<script type="text/javascript" src="src/widgets.js?version=2019-04-05"></script> <script type="text/javascript" src="src/widgets.js?version=2019-04-05"></script>
<script type="text/javascript" src="src/blocks.js?version=2019-04-11"></script> <script type="text/javascript" src="src/blocks.js?version=2019-04-11"></script>
<script type="text/javascript" src="src/threads.js?version=2019-04-22"></script> <script type="text/javascript" src="src/threads.js?version=2019-04-23"></script>
<script type="text/javascript" src="src/objects.js?version=2019-04-12"></script> <script type="text/javascript" src="src/objects.js?version=2019-04-12"></script>
<script type="text/javascript" src="src/gui.js?version=2019-04-10"></script> <script type="text/javascript" src="src/gui.js?version=2019-04-10"></script>
<script type="text/javascript" src="src/paint.js?version=2019-02-22"></script> <script type="text/javascript" src="src/paint.js?version=2019-02-22"></script>

Wyświetl plik

@ -62,7 +62,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy,
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, Color, isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, Color,
TableFrameMorph, ColorSlotMorph, isSnapObject, Map, newCanvas, Symbol*/ TableFrameMorph, ColorSlotMorph, isSnapObject, Map, newCanvas, Symbol*/
modules.threads = '2019-April-22'; modules.threads = '2019-April-23';
var ThreadManager; var ThreadManager;
var Process; var Process;
@ -1075,11 +1075,9 @@ Process.prototype.evaluate = function (
) { ) {
if (!context) {return null; } if (!context) {return null; }
if (context instanceof Function) { if (context instanceof Function) {
/* // if (!this.enableJS) {
if (!this.enableJS) { // throw new Error('JavaScript is not enabled');
throw new Error('JavaScript is not enabled'); // }
}
*/
return context.apply( return context.apply(
this.blockReceiver(), this.blockReceiver(),
args.asArray().concat([this]) args.asArray().concat([this])
@ -2071,58 +2069,59 @@ Process.prototype.reportMap = function (reporter, list) {
// answer a new list containing the results of the reporter applied // answer a new list containing the results of the reporter applied
// to each value of the given list. Distinguish between linked and // to each value of the given list. Distinguish between linked and
// arrayed lists. // arrayed lists.
// Note: This method utilizes the current context's inputs array to
// manage temporary variables, whose allocation to which slot are // this.context.inputs:
// documented in each of the variants' code (linked or arrayed) below // [0] - reporter
// [1] - list (original source)
// -----------------------------
// [2] - last reporter evaluation result
var next; var next;
if (list.isLinked) { if (list.isLinked) {
// this.context.inputs: if (this.context.aggregation === null) {
// [0] - reporter this.context.aggregation = {
// [1] - list (original source) source : list,
// ----------------------------- target : new List(),
// [2] - result list (target) end : null,
// [3] - currently last element of result list remaining : list.length()
// [4] - current source list (what's left to map) };
// [5] - current value of last function call this.context.aggregation.target.isLinked = true;
this.context.aggregation.end = this.context.aggregation.target;
if (this.context.inputs.length < 3) { } else if (this.context.inputs.length > 2) {
this.context.addInput(new List()); this.context.aggregation.end.rest = list.cons(
this.context.inputs[2].isLinked = true; this.context.inputs.pop()
this.context.addInput(this.context.inputs[2]); );
this.context.addInput(list); this.context.aggregation.end = this.context.aggregation.end.rest;
this.context.aggregation.remaining -= 1;
} }
if (this.context.inputs[4].length() === 0) { if (this.context.aggregation.remaining === 0) {
this.context.inputs[3].rest = list.cons(this.context.inputs[5]); this.context.aggregation.end.rest = list.cons(
this.returnValueToParentContext(this.context.inputs[2].cdr()); this.context.inputs[2]
return; ).cdr();
}
if (this.context.inputs.length > 5) {
this.context.inputs[3].rest = list.cons(this.context.inputs[5]);
this.context.inputs[3] = this.context.inputs[3].rest;
this.context.inputs.splice(5);
}
next = this.context.inputs[4].at(1);
this.context.inputs[4] = this.context.inputs[4].cdr();
this.pushContext();
this.evaluate(reporter, new List([next]));
} else { // arrayed
// this.context.inputs:
// [0] - reporter
// [1] - list (original source)
// -----------------------------
// [2..n] - result values (target)
if (this.context.inputs.length - 2 === list.length()) {
this.returnValueToParentContext( this.returnValueToParentContext(
new List(this.context.inputs.slice(2)) this.context.aggregation.target.cdr()
); );
return; return;
} }
next = list.at(this.context.inputs.length - 1);
this.pushContext(); next = this.context.aggregation.source.at(1);
this.evaluate(reporter, new List([next])); this.context.aggregation.source = this.context.aggregation.source.cdr();
} else { // arrayed
if (this.context.aggregation === null) {
this.context.aggregation = [];
} else if (this.context.inputs.length > 2) {
this.context.aggregation.push(this.context.inputs.pop());
}
if (this.context.aggregation.length === list.length()) {
this.returnValueToParentContext(
new List(this.context.aggregation)
);
return;
}
next = list.at(this.context.aggregation.length + 1);
} }
this.pushContext();
this.evaluate(reporter, new List([next]));
}; };
Process.prototype.doForEach = function (upvar, list, script) { Process.prototype.doForEach = function (upvar, list, script) {
@ -4819,6 +4818,7 @@ Process.prototype.reportAtomicGroup = function (list, reporter) {
tag string or number to optionally identify the Context, tag string or number to optionally identify the Context,
as a "return" target (for the "stop block" primitive) as a "return" target (for the "stop block" primitive)
isFlashing flag for single-stepping isFlashing flag for single-stepping
aggregation slot for collecting data from reentrant visits
*/ */
function Context( function Context(
@ -4849,6 +4849,7 @@ function Context(
this.emptySlots = 0; // used for block reification this.emptySlots = 0; // used for block reification
this.tag = null; // lexical catch-tag for custom blocks this.tag = null; // lexical catch-tag for custom blocks
this.isFlashing = false; // for single-stepping this.isFlashing = false; // for single-stepping
this.aggregation = null;
} }
Context.prototype.toString = function () { Context.prototype.toString = function () {