diff --git a/HISTORY.md b/HISTORY.md
index 37862039..9c4c6f36 100755
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -7,9 +7,10 @@
* **Notable Fixes:**
* fixed occasional invisible error messages
-### 2021-06-16
+### 2021-06-17
* extensions: added APL extension primitives
* updated apl library
+* threads, extensions: added variable extension primitives
### 2021-06-16
* threads: added exception handling primitives for try/catch
diff --git a/snap.html b/snap.html
index 345fe7e1..1bb575ea 100755
--- a/snap.html
+++ b/snap.html
@@ -9,7 +9,7 @@
-
+
diff --git a/src/extensions.js b/src/extensions.js
index 62848bf4..9e942ec1 100644
--- a/src/extensions.js
+++ b/src/extensions.js
@@ -28,7 +28,7 @@
// Global settings /////////////////////////////////////////////////////
/*global modules, List, StageMorph, Costume, SpeechSynthesisUtterance, Sound,
-IDE_Morph, CamSnapshotDialogMorph, SoundRecorderDialogMorph, isSnapObject*/
+IDE_Morph, CamSnapshotDialogMorph, SoundRecorderDialogMorph, isSnapObject, nop*/
modules.extensions = '2021-June-17';
@@ -83,6 +83,11 @@ SnapExtensions.set(
}
);
+SnapExtensions.set(
+ 'err_ignore',
+ nop
+);
+
// list utils (lst_):
SnapExtensions.set(
@@ -303,7 +308,7 @@ SnapExtensions.set(
}
);
-// Geo-location (geo_)
+// Geo-location (geo_):
SnapExtensions.set(
'geo_location(acc?)',
@@ -438,7 +443,7 @@ SnapExtensions.set(
}
);
-// Object properties (obj_)
+// Object properties (obj_):
SnapExtensions.set(
'obj_name(obj, name)',
@@ -460,3 +465,102 @@ SnapExtensions.set(
}
}
);
+
+// Variables (var_):
+
+SnapExtensions.set(
+ 'var_declare(scope, name)',
+ function (scope, name, proc) {
+ var frame;
+ proc.assertType(name, 'text');
+ if (name === '') {return; }
+ if (scope === 'script') {
+ frame = proc.context.isInCustomBlock() ?
+ proc.homeContext.variables
+ : proc.context.outerContext.variables;
+ } else if (scope === 'sprite') {
+ frame = this.variables;
+ } else {
+ frame = this.globalVariables();
+ }
+ if (frame.vars[name] === undefined) {
+ frame.addVar(name);
+ }
+ }
+);
+
+SnapExtensions.set(
+ 'var_delete(name)',
+ function (name, proc) {
+ var local;
+ proc.assertType(name, 'text');
+ if (name === '') {return; }
+ local = proc.context.isInCustomBlock() ?
+ proc.homeContext.variables
+ : proc.context.outerContext.variables;
+ if (local.vars[name] !== undefined) {
+ delete local.vars[name];
+ } else if (this.deletableVariableNames().indexOf(name) > -1) {
+ this.deleteVariable(name);
+ }
+ }
+);
+
+SnapExtensions.set(
+ 'var_get(name)',
+ function (name, proc) {
+ proc.assertType(name, 'text');
+ return proc.homeContext.variables.getVar(name);
+ }
+);
+
+SnapExtensions.set(
+ 'var_set(name, val)',
+ function (name, val, proc) {
+ var local;
+ proc.assertType(name, 'text');
+ if (name === '') {return; }
+ local = proc.context.isInCustomBlock() ?
+ proc.homeContext.variables
+ : proc.context.outerContext.variables;
+ local.setVar(name, val);
+ }
+);
+
+SnapExtensions.set(
+ 'var_show(name)',
+ function (name, proc) {
+ proc.doShowVar(
+ name,
+ proc.context.isInCustomBlock() ?
+ proc.homeContext
+ : proc.context.outerContext
+ );
+ }
+);
+
+SnapExtensions.set(
+ 'var_hide(name)',
+ function (name, proc) {
+ proc.doHideVar(
+ name,
+ proc.context.isInCustomBlock() ?
+ proc.homeContext
+ : proc.context.outerContext
+ );
+ }
+);
+
+// IDE (ide_):
+
+SnapExtensions.set(
+ 'ide_refreshpalette(name)',
+ function (name) {
+ var ide = this.parentThatIsA(IDE_Morph);
+ if (name !== 'variables') {
+ ide.flushBlocksCache(name);
+ }
+ ide.flushBlocksCache('variables'); // b/c of inheritance
+ ide.refreshPalette();
+ }
+);
diff --git a/src/threads.js b/src/threads.js
index 4184e93c..7c815a10 100644
--- a/src/threads.js
+++ b/src/threads.js
@@ -62,7 +62,7 @@ isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, BLACK,
TableFrameMorph, ColorSlotMorph, isSnapObject, newCanvas, Symbol, SVG_Costume,
SnapExtensions*/
-modules.threads = '2021-June-16';
+modules.threads = '2021-June-17';
var ThreadManager;
var Process;
@@ -1690,8 +1690,9 @@ Process.prototype.reportGetVar = function () {
);
};
-Process.prototype.doShowVar = function (varName) {
- var varFrame = (this.context || this.homeContext).variables,
+Process.prototype.doShowVar = function (varName, context) {
+ // context is an optional start-context to be used by extensions
+ var varFrame = (context || (this.context || this.homeContext)).variables,
stage,
watcher,
target,
@@ -1753,9 +1754,10 @@ Process.prototype.doShowVar = function (varName) {
}
};
-Process.prototype.doHideVar = function (varName) {
+Process.prototype.doHideVar = function (varName, context) {
// if no varName is specified delete all watchers on temporaries
- var varFrame = this.context.variables,
+ // context is an optional start-context to be used by extensions
+ var varFrame = (context || this.context).variables,
stage,
watcher,
target,
@@ -6870,6 +6872,16 @@ Context.prototype.stackSize = function () {
return 1 + this.parentContext.stackSize();
};
+Context.prototype.isInCustomBlock = function () {
+ if (this.isCustomBlock) {
+ return true;
+ }
+ if (this.parentContext) {
+ return this.parentContext.isInCustomBlock();
+ }
+ return false;
+};
+
// Variable /////////////////////////////////////////////////////////////////
function Variable(value, isTransient) {