From e20d304bc5ca4e27882c021b3b7f56e00f2b1e74 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 24 Jun 2021 16:00:44 +0200 Subject: [PATCH 1/4] extensions: tweaked loading unlisted script-extensions --- HISTORY.md | 3 +++ snap.html | 2 +- src/extensions.js | 29 +++++++++++++++++------------ 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 0de5f00a..7b1390e3 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -10,6 +10,9 @@ * **Notable Fixes:** * fixed occasional invisible error messages +### 2021-06-24 +* extensions: tweaked loading unlisted script-extensions + ### 2021-06-23 * updated bignums library * pushed dev version to 6.10 diff --git a/snap.html b/snap.html index b5b69ef4..245fc6d5 100755 --- a/snap.html +++ b/snap.html @@ -19,7 +19,7 @@ - + diff --git a/src/extensions.js b/src/extensions.js index 816c44e5..a3e487a0 100644 --- a/src/extensions.js +++ b/src/extensions.js @@ -29,9 +29,9 @@ /*global modules, List, StageMorph, Costume, SpeechSynthesisUtterance, Sound, IDE_Morph, CamSnapshotDialogMorph, SoundRecorderDialogMorph, isSnapObject, nop, -Color, contains*/ +Color, Process, contains*/ -modules.extensions = '2021-June-23'; +modules.extensions = '2021-June-24'; // Global stuff @@ -691,23 +691,28 @@ SnapExtensions.primitives.set( if (contains(SnapExtensions.scripts, url)) { return; } - if (!(SnapExtensions.urls.some(any => url.indexOf(any) === 0))) { - throw new Error('unlisted extension url:\n"' + url + '"'); + if (Process.prototype.enableJS || SnapExtensions.urls.some( + any => url.indexOf(any) === 0) + ) { + scriptElement = document.createElement('script'); + scriptElement.onload = () => { + SnapExtensions.scripts.push(url); + proc.context.accumulator.done = true; + }; + document.head.appendChild(scriptElement); + scriptElement.src = url; + } else { + throw new Error( + 'unlisted extension url:\n"' + url + '"\n' + + 'JavaScript extensions for Snap!\nare turned off' + ); } - scriptElement = document.createElement('script'); - scriptElement.onload = () => { - SnapExtensions.scripts.push(url); - proc.context.accumulator.done = true; - }; - document.head.appendChild(scriptElement); - scriptElement.src = url; } else if (proc.context.accumulator.done) { return; } proc.pushContext('doYield'); proc.pushContext(); } - ); // Menus From eb75e8d96ad442d5e32b963d4418816c8f63e90d Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 24 Jun 2021 16:07:21 +0200 Subject: [PATCH 2/4] removed unused code --- HISTORY.md | 1 + snap.html | 6 +++--- src/byob.js | 7 +------ src/store.js | 13 +------------ src/threads.js | 7 +------ 5 files changed, 7 insertions(+), 27 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7b1390e3..cb0949ba 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -12,6 +12,7 @@ ### 2021-06-24 * extensions: tweaked loading unlisted script-extensions +* byob, threads, store: removed unused code ### 2021-06-23 * updated bignums library diff --git a/snap.html b/snap.html index 245fc6d5..42a950dd 100755 --- a/snap.html +++ b/snap.html @@ -9,19 +9,19 @@ - + - + - + diff --git a/src/byob.js b/src/byob.js index ecfc4e73..62d6d25b 100644 --- a/src/byob.js +++ b/src/byob.js @@ -106,7 +106,7 @@ WatcherMorph, XML_Serializer, SnapTranslator, SnapExtensions*/ // Global stuff //////////////////////////////////////////////////////// -modules.byob = '2021-June-19'; +modules.byob = '2021-June-24'; // Declarations @@ -347,11 +347,6 @@ CustomBlockDefinition.prototype.parseChoices = function (string) { if (string.match(/^function\s*\(.*\)\s*{.*\n/)) { // It's a JS function definition. // Let's extract its params and body, and return a Function out of them. - /* - if (!Process.prototype.enableJS) { - throw new Error('JavaScript is not enabled'); - } - */ params = string.match(/^function\s*\((.*)\)/)[1].split(','); body = string.split('\n').slice(1,-1).join('\n'); return Function.apply(null, params.concat([body])); diff --git a/src/store.js b/src/store.js index c2aabea7..fb7bc2f4 100644 --- a/src/store.js +++ b/src/store.js @@ -61,7 +61,7 @@ normalizeCanvas, contains*/ // Global stuff //////////////////////////////////////////////////////// -modules.store = '2021-June-10'; +modules.store = '2021-June-24'; // XML_Serializer /////////////////////////////////////////////////////// @@ -1164,17 +1164,6 @@ SnapSerializer.prototype.loadBlock = function (model, isReporter, object) { model.attributes['var'] ); } else { - // disable loading JavaScript functions - /* - if (model.attributes.s === 'reportJSFunction' && - !Process.prototype.enableJS) { - if (window.confirm('enable JavaScript?')) { - Process.prototype.enableJS = true; - } else { - throw new Error('JavaScript is not enabled'); - } - } - */ block = SpriteMorph.prototype.blockForSelector(model.attributes.s); migration = SpriteMorph.prototype.blockMigrations[ model.attributes.s diff --git a/src/threads.js b/src/threads.js index 216eedd1..7b3b5bc8 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-18'; +modules.threads = '2021-June-24'; var ThreadManager; var Process; @@ -1254,11 +1254,6 @@ Process.prototype.evaluate = function ( return this.returnValueToParentContext(null); } if (context instanceof Function) { - /* - if (!this.enableJS) { - throw new Error('JavaScript extensions for Snap!\nare turned off'); - } - */ return context.apply( this.blockReceiver(), args.itemsArray().concat([this]) From d38f9d713496dfc568ad7124876768a57fe7301b Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 24 Jun 2021 18:43:49 +0200 Subject: [PATCH 3/4] added documentation for adding external JS modules --- HISTORY.md | 1 + src/extensions.js | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index cb0949ba..bfa326a7 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -13,6 +13,7 @@ ### 2021-06-24 * extensions: tweaked loading unlisted script-extensions * byob, threads, store: removed unused code +* extensions: added documentation for adding external JS modules ### 2021-06-23 * updated bignums library diff --git a/src/extensions.js b/src/extensions.js index a3e487a0..0ffbee87 100644 --- a/src/extensions.js +++ b/src/extensions.js @@ -49,6 +49,11 @@ var SnapExtensions = { used as extension primitives for blocks or dynamic dropdown menus. Block extensions are stored in the "primitives" dictionary of SnapExtensions, dynamic dropdown menus in the "menus" section. + + You can also extend Snap! with your own externally hosted JavaScript file(s) + and have them add your own extension primitives and menus to the global + SnapExtensions dictionaries. This lets you provide libraries to support + special APIs and custom hardware. 1. Primitives (additional blocks) @@ -109,6 +114,37 @@ var SnapExtensions = { "block.inputs()". This will give you an array of all input slots. You can access the contents of an input slot by calling "slot.evaluate()" + + 3. External JavaScript files + ============================ + You can provide extensions for your custom hardware or for arbitrary APIs + or extend Snap! with JavaScript libraries from other parties. You can + load additional JavaScript files using the "src_load(url)" extension + primitive inside Snap, which you can find using Snap's search bar in the + IDE. The loading primitive will wait until the source file has fully loaded + and its defined functions are ready to be called. + + adding primitives to SnapExtensions + ----------------------------------- + It is the suggested best practice to expose your own extension primitives + by adding them to the global SnapExtensions libraries (for primitives and + menus) using the very same conventions described herein, and then to offer + a library of custom blocks that make calls to your additional operations. + + publishing an extension + ----------------------- + Running the "src_load(url)" primitive will throw an error unless you first + check the "Enable JavaScript extensions" setting in Snap's preferences menu, + or if your JavaScript extension comes from a list of trusted hosts. + While you develop your JavaScript extension it's recommended to turn the + "Enable JavaScript extensions" setting on to load the extension once, and + then to turn it off again, so you can make sure your custom blocks are not + using any "JS Function" blocks (because those will be caught if the + preference is turned off). + When you're ready to publish your extension you can contact us to allow-list + the url hosting your JS file, or you can send me a Github pull-request to + include it in the main Snap branch. + Whatever you do, please use these extension capabilities sensibly. */ @@ -680,10 +716,10 @@ SnapExtensions.primitives.set( } ); -// loading external scripts (scr_) +// loading external scripts (src_) SnapExtensions.primitives.set( - 'scr_load(url)', + 'src_load(url)', function (url, proc) { var scriptElement; if (!proc.context.accumulator) { From 6c769c2017b37375fcbd01762898b05aa031d2aa Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 24 Jun 2021 18:46:46 +0200 Subject: [PATCH 4/4] updated bignumbers library --- HISTORY.md | 1 + libraries/bignumbers.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index bfa326a7..942a240b 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -14,6 +14,7 @@ * extensions: tweaked loading unlisted script-extensions * byob, threads, store: removed unused code * extensions: added documentation for adding external JS modules +* updated bignumbers library ### 2021-06-23 * updated bignums library diff --git a/libraries/bignumbers.xml b/libraries/bignumbers.xml index 9ab6ac84..e07c62c0 100644 --- a/libraries/bignumbers.xml +++ b/libraries/bignumbers.xml @@ -1 +1 @@ -call with True to turn on the entire Scheme numeric tower, including infinite-precision integers, exact rationals, and complex numbers; call with False to restore native JavaScript arithmetic.
pt:altera utilização de aritmética do Scheme para _
The factorial function, to make very large numbers, to demo bignums.
The identity function: reports its input. It's useful to get things like 3/4 or 5-2i into numeric input slots.
Provides Scheme arithmetic functions not in JavaScript
pt:_ de _ number? complex? real? rational? integer? exact? inexact? exact inexact finite? infinite? nan? numerator denominator real-part imag-part magnitude angle
\ No newline at end of file +call with True to turn on the entire Scheme numeric tower, including infinite-precision integers, exact rationals, and complex numbers; call with False to restore native JavaScript arithmetic.
pt:altera utilização de aritmética do Scheme para _
The factorial function, to make very large numbers, to demo bignums.
The identity function: reports its input. It's useful to get things like 3/4 or 5-2i into numeric input slots.
Provides Scheme arithmetic functions not in JavaScript
pt:_ de _ number? complex? real? rational? integer? exact? inexact? exact inexact finite? infinite? nan? numerator denominator real-part imag-part magnitude angle
\ No newline at end of file