pxt-core 8.1.4 → 8.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -689,11 +689,16 @@ var pxt;
689
689
  docs.prepTemplate = prepTemplate;
690
690
  function setupRenderer(renderer) {
691
691
  renderer.image = function (href, title, text) {
692
+ const endpointName = "makecode-lucas-testing-makecodetempmediaservice-usea";
692
693
  if (href.startsWith("youtube:")) {
693
694
  let out = '<div class="tutorial-video-embed"><iframe src="https://www.youtube.com/embed/' + href.split(":").pop()
694
695
  + '" title="' + title + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
695
696
  return out;
696
697
  }
698
+ else if (href.startsWith("azuremedia:")) {
699
+ let out = `<div class="tutorial-video-embed"><video class="ams-embed" controls src="https://${endpointName}.streaming.media.azure.net/` + href.split(":").pop() + '/manifest(format=mpd-time-cmaf)" /></div>';
700
+ return out;
701
+ }
697
702
  else {
698
703
  let out = '<img class="ui image" src="' + href + '" alt="' + text + '"';
699
704
  if (title) {
package/built/pxt.js CHANGED
@@ -103374,7 +103374,9 @@ var pxt;
103374
103374
  const height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
103375
103375
  const left = ((width / 2) - (popUpWidth / 2)) + winLeft;
103376
103376
  const top = ((height / 2) - (popUpHeight / 2)) + winTop;
103377
- const popupWindow = window.open(url, title, "width=" + popUpWidth + ", height=" + popUpHeight + ", top=" + top + ", left=" + left);
103377
+ const features = "width=" + popUpWidth + ", height=" + popUpHeight + ", top=" + top + ", left=" + left;
103378
+ // Current CEF version does not like when features parameter is passed and just immediately rejects.
103379
+ const popupWindow = window.open(url, title, !pxt.BrowserUtils.isIpcRenderer() ? features : undefined);
103378
103380
  if (popupWindow.focus) {
103379
103381
  popupWindow.focus();
103380
103382
  }
@@ -103382,7 +103384,7 @@ var pxt;
103382
103384
  }
103383
103385
  catch (e) {
103384
103386
  // Error opening popup
103385
- pxt.tickEvent('pxt.popupError', { url: url, msg: e.message });
103387
+ pxt.tickEvent('pxt.popupError', { msg: e.message });
103386
103388
  return null;
103387
103389
  }
103388
103390
  }
@@ -103460,6 +103462,19 @@ var pxt;
103460
103462
  return `${url}${url.indexOf('?') > 0 ? "&" : "?"}rnd=${Math.random()}`;
103461
103463
  }
103462
103464
  BrowserUtils.cacheBustingUrl = cacheBustingUrl;
103465
+ function legacyCopyText(element) {
103466
+ element.focus();
103467
+ element.setSelectionRange(0, 9999);
103468
+ try {
103469
+ const success = document.execCommand("copy");
103470
+ pxt.debug('copy: ' + success);
103471
+ return !!success;
103472
+ }
103473
+ catch (e) {
103474
+ return false;
103475
+ }
103476
+ }
103477
+ BrowserUtils.legacyCopyText = legacyCopyText;
103463
103478
  })(BrowserUtils = pxt.BrowserUtils || (pxt.BrowserUtils = {}));
103464
103479
  })(pxt || (pxt = {}));
103465
103480
  var pxt;
@@ -106384,11 +106399,16 @@ var pxt;
106384
106399
  docs.prepTemplate = prepTemplate;
106385
106400
  function setupRenderer(renderer) {
106386
106401
  renderer.image = function (href, title, text) {
106402
+ const endpointName = "makecode-lucas-testing-makecodetempmediaservice-usea";
106387
106403
  if (href.startsWith("youtube:")) {
106388
106404
  let out = '<div class="tutorial-video-embed"><iframe src="https://www.youtube.com/embed/' + href.split(":").pop()
106389
106405
  + '" title="' + title + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
106390
106406
  return out;
106391
106407
  }
106408
+ else if (href.startsWith("azuremedia:")) {
106409
+ let out = `<div class="tutorial-video-embed"><video class="ams-embed" controls src="https://${endpointName}.streaming.media.azure.net/` + href.split(":").pop() + '/manifest(format=mpd-time-cmaf)" /></div>';
106410
+ return out;
106411
+ }
106392
106412
  else {
106393
106413
  let out = '<img class="ui image" src="' + href + '" alt="' + text + '"';
106394
106414
  if (title) {
@@ -125394,6 +125414,56 @@ ${output}</xml>`;
125394
125414
  }
125395
125415
  return undefined;
125396
125416
  }
125417
+ function getCallKey(statement) {
125418
+ const call = statement.expression;
125419
+ const callInfo = pxtc.pxtInfo(call).callInfo;
125420
+ const attributes = attrs(callInfo);
125421
+ if (attributes.blockAllowMultiple)
125422
+ return undefined;
125423
+ if (attributes.blockHandlerKey)
125424
+ return attributes.blockHandlerKey;
125425
+ const args = callInfo.args.filter(arg => !ts.isArrowFunction(arg) && !isFunctionExpression(arg)).map(arg => getArgKeyRecursive(arg)).join("$$");
125426
+ return attributes.blockId + "-" + args;
125427
+ }
125428
+ // custom function to get the key for an argument. we do this instead of simply calling getText() because this
125429
+ // handles whitespace and certain passthrough nodes like parenthesized expressions
125430
+ function getArgKeyRecursive(n) {
125431
+ if (!n)
125432
+ return "";
125433
+ switch (n.kind) {
125434
+ case SK.ParenthesizedExpression:
125435
+ case SK.AsExpression:
125436
+ return getArgKeyRecursive(n.expression);
125437
+ case SK.Identifier:
125438
+ return n.text;
125439
+ case SK.StringLiteral:
125440
+ case SK.FirstTemplateToken:
125441
+ case SK.NoSubstitutionTemplateLiteral:
125442
+ return `"${n.text}"`;
125443
+ case SK.NumericLiteral:
125444
+ return n.text;
125445
+ case SK.TrueKeyword:
125446
+ return "true";
125447
+ case SK.FalseKeyword:
125448
+ return "false";
125449
+ case SK.BinaryExpression:
125450
+ return `{${getArgKeyRecursive(n.left)}${n.operatorToken.getText()}${getArgKeyRecursive(n.right)}}`;
125451
+ case SK.PrefixUnaryExpression:
125452
+ return n.operator + getArgKeyRecursive(n.operand);
125453
+ case SK.PropertyAccessExpression:
125454
+ return getArgKeyRecursive(n.expression) + "." + getArgKeyRecursive(n.name);
125455
+ case SK.ArrayLiteralExpression:
125456
+ return `[${n.elements.map(e => getArgKeyRecursive(e))}]`;
125457
+ case SK.ElementAccessExpression:
125458
+ return `${n.expression}[${n.argumentExpression}]`;
125459
+ case SK.TaggedTemplateExpression:
125460
+ return `${getArgKeyRecursive(n.tag)}\`${n.template.getText()}\``;
125461
+ case SK.CallExpression:
125462
+ return `${getArgKeyRecursive(n.expression)}(${n.arguments.map(getArgKeyRecursive).join(",")})`;
125463
+ default:
125464
+ return n.getText();
125465
+ }
125466
+ }
125397
125467
  function countBlock() {
125398
125468
  emittedBlocks++;
125399
125469
  if (emittedBlocks > MAX_BLOCKS) {
@@ -126935,7 +127005,20 @@ ${output}</xml>`;
126935
127005
  blockStatements.unshift(statement);
126936
127006
  }
126937
127007
  }
126938
- eventStatements.map(n => getStatementBlock(n, undefined, undefined, false, topLevel)).forEach(emitStatementNode);
127008
+ const compiledEvents = [];
127009
+ const keyMap = {};
127010
+ for (const statement of eventStatements) {
127011
+ const key = statement.kind === SK.FunctionDeclaration ? undefined : getCallKey(statement);
127012
+ if (key && keyMap[key]) {
127013
+ // Pass false for topLevel to force a grey block
127014
+ compiledEvents.push(getStatementBlock(statement, undefined, undefined, false, false));
127015
+ }
127016
+ else {
127017
+ keyMap[key] = true;
127018
+ compiledEvents.push(getStatementBlock(statement, undefined, undefined, false, topLevel));
127019
+ }
127020
+ }
127021
+ compiledEvents.forEach(emitStatementNode);
126939
127022
  if (blockStatements.length) {
126940
127023
  // wrap statement in "on start" if top level
126941
127024
  const blockNode = blockStatements.shift();
@@ -401,8 +401,8 @@ Blockly.ConnectionChecker.prototype.getErrorMessage=function(a,b,c){switch(a){ca
401
401
  Blockly.ConnectionChecker.prototype.doSafetyChecks=function(a,b){if(!a||!b)return Blockly.Connection.REASON_TARGET_NULL;if(a.isSuperior())var c=a.getSourceBlock(),d=b.getSourceBlock();else d=a.getSourceBlock(),c=b.getSourceBlock();return c==d?Blockly.Connection.REASON_SELF_CONNECTION:b.type!=Blockly.OPPOSITE_TYPE[a.type]?Blockly.Connection.REASON_WRONG_TYPE:c.workspace!==d.workspace?Blockly.Connection.REASON_DIFFERENT_WORKSPACES:Blockly.Connection.CAN_CONNECT};
402
402
  Blockly.ConnectionChecker.prototype.doTypeChecks=function(a,b){a=a.getCheck();b=b.getCheck();if(!a||!b)return!0;for(var c=0;c<a.length;c++)if(-1!=b.indexOf(a[c]))return!0;return!1};
403
403
  Blockly.ConnectionChecker.prototype.doDragChecks=function(a,b,c){if(a.distanceFrom(b)>c||b.getSourceBlock().isInsertionMarker())return!1;switch(b.type){case Blockly.connectionTypes.PREVIOUS_STATEMENT:return this.canConnectToPrevious_(a,b);case Blockly.connectionTypes.OUTPUT_VALUE:if(b.isConnected()&&!b.targetBlock().isInsertionMarker()||a.isConnected())return!1;break;case Blockly.connectionTypes.INPUT_VALUE:if(b.isConnected()&&!b.targetBlock().isMovable()&&!b.targetBlock().isShadow()||b&&b.targetBlock()&&
404
- (c=b.targetBlock(),c.isShadow()&&Blockly.pxtBlocklyUtils.isFunctionArgumentReporter(c))||Blockly.pxtBlocklyUtils.isFunctionArgumentReporter(a.getSourceBlock())&&(c=b.getSourceBlock().getRootBlock(),c.isEnabled()&&!Blockly.pxtBlocklyUtils.hasMatchingArgumentReporter(c,a.getSourceBlock())))return!1;break;case Blockly.connectionTypes.NEXT_STATEMENT:if(b.isConnected()&&!a.getSourceBlock().nextConnection&&!b.targetBlock().isShadow()&&b.targetBlock().nextConnection)return!1;break;default:return!1}return-1!=
405
- Blockly.draggingConnections.indexOf(b)?!1:!0};Blockly.ConnectionChecker.prototype.canConnectToPrevious_=function(a,b){if(a.targetConnection||-1!=Blockly.draggingConnections.indexOf(b))return!1;var c=a.getSourceBlock(),d=c.getFirstStatementConnection(),e=a==d;a=a==c.nextConnection;if(null!=d&&!e&&!a)return!1;c=null!=c.previousConnection;if(e&&c||!b.targetConnection)return!0;b=b.targetBlock();return b.isInsertionMarker()?!b.getPreviousBlock():!1};
404
+ (c=b.targetBlock(),c.isShadow()&&Blockly.pxtBlocklyUtils.isFunctionArgumentReporter(c)))return!1;if(Blockly.pxtBlocklyUtils.isFunctionArgumentReporter(a.getSourceBlock())){c=b.getSourceBlock().getParent();for(var d=!1;c;){if(!c.isEnabled()||Blockly.pxtBlocklyUtils.hasMatchingArgumentReporter(c,a.getSourceBlock())){d=!0;break}c=c.getParent()}if(!d)return!1}break;case Blockly.connectionTypes.NEXT_STATEMENT:if(b.isConnected()&&!a.getSourceBlock().nextConnection&&!b.targetBlock().isShadow()&&b.targetBlock().nextConnection)return!1;
405
+ break;default:return!1}return-1!=Blockly.draggingConnections.indexOf(b)?!1:!0};Blockly.ConnectionChecker.prototype.canConnectToPrevious_=function(a,b){if(a.targetConnection||-1!=Blockly.draggingConnections.indexOf(b))return!1;var c=a.getSourceBlock(),d=c.getFirstStatementConnection(),e=a==d;a=a==c.nextConnection;if(null!=d&&!e&&!a)return!1;c=null!=c.previousConnection;if(e&&c||!b.targetConnection)return!0;b=b.targetBlock();return b.isInsertionMarker()?!b.getPreviousBlock():!1};
406
406
  Blockly.registry.register(Blockly.registry.Type.CONNECTION_CHECKER,Blockly.registry.DEFAULT,Blockly.ConnectionChecker);Blockly.VariableMap=function(a){this.variableMap_=Object.create(null);this.workspace=a};Blockly.VariableMap.prototype.clear=function(){this.variableMap_=Object.create(null)};Blockly.VariableMap.prototype.renameVariable=function(a,b){var c=this.getVariable(b,a.type),d=this.workspace.getAllBlocks(!1);Blockly.Events.setGroup(!0);try{c&&c.getId()!=a.getId()?this.renameVariableWithConflict_(a,b,c,d):this.renameVariableAndUses_(a,b,d)}finally{Blockly.Events.setGroup(!1)}};
407
407
  Blockly.VariableMap.prototype.renameVariableById=function(a,b){var c=this.getVariableById(a);if(!c)throw Error("Tried to rename a variable that didn't exist. ID: "+a);this.renameVariable(c,b)};Blockly.VariableMap.prototype.renameVariableAndUses_=function(a,b,c){Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.VAR_RENAME))(a,b));a.name=b;for(b=0;b<c.length;b++)c[b].updateVarName(a)};
408
408
  Blockly.VariableMap.prototype.renameVariableWithConflict_=function(a,b,c,d){var e=a.type;b!=c.name&&this.renameVariableAndUses_(c,b,d);for(b=0;b<d.length;b++)d[b].renameVarById(a.getId(),c.getId());Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.VAR_DELETE))(a));a=this.getVariablesOfType(e).indexOf(a);this.variableMap_[e].splice(a,1)};
@@ -1084,7 +1084,7 @@ return Blockly.Functions.namesInUse(b,null,a)[c]?(Blockly.alert(Blockly.Msg.VARI
1084
1084
  Blockly.Functions.mutateCallersAndDefinition=function(a,b,c){var d=Blockly.Functions.getDefinition(a,b);d?(a=Blockly.Functions.getCallers(a,d.workspace),a.push(d),Blockly.Events.setGroup(!0),a.forEach(function(a){var b=a.mutationToDom(),e=b&&Blockly.Xml.domToText(b);a.domToMutation(c);var h=a.mutationToDom(),k=h&&Blockly.Xml.domToText(h);if(e!=k)if(Blockly.Events.fire(new Blockly.Events.BlockChange(a,"mutation",null,e,k)),a.id==d.id){var l=Blockly.Functions.getArgMap(b),m=Blockly.Functions.getArgMap(h,
1085
1085
  !0);d.getDescendants().forEach(function(a){if(Blockly.pxtBlocklyUtils.isFunctionArgumentReporter(a)){var b=a.getFieldValue("VALUE"),c=l[b];m[c]?m[c]!==b&&a.setFieldValue(m[c],"VALUE"):a.dispose()}})}else setTimeout(function(){a.bumpNeighbours()},Blockly.BUMP_DELAY)}),Blockly.Events.setGroup(!1)):console.warn("Attempted to change function "+a+", but no definition block was found on the workspace")};
1086
1086
  Blockly.Functions.createFlyout=function(a,b){var c=new Blockly.Options({scrollbars:!0,disabledPatternId:a.options.disabledPatternId,parentWorkspace:a,rtl:a.RTL,oneBasedIndex:a.options.oneBasedIndex,horizontalLayout:a.horizontalLayout,toolboxPosition:a.options.toolboxPosition,zoomOptions:a.options.zoomOptions,renderer:a.options.renderer,rendererOverrides:a.options.rendererOverrides,newFunctions:a.options.newFunctions,move:{scrollbars:!0}});c=c.horizontalLayout?new Blockly.HorizontalFlyout(c):new Blockly.VerticalFlyout(c);
1087
- var d=c.createDom("svg");goog.dom.insertSiblingAfter(d,b);c.init(a);return c};Blockly.VERSION="4.0.12";Blockly.mainWorkspace=null;Blockly.selected=null;Blockly.draggingConnections=[];Blockly.clipboardXml_=null;Blockly.clipboardSource_=null;Blockly.clipboardTypeCounts_=null;Blockly.cache3dSupported_=null;Blockly.parentContainer=null;Blockly.svgSize=function(a){Blockly.utils.deprecation.warn("Blockly.svgSize","March 2021","March 2022","workspace.getCachedParentSvgSize");return new Blockly.utils.Size(a.cachedWidth_,a.cachedHeight_)};Blockly.resizeSvgContents=function(a){a.resizeContents()};
1087
+ var d=c.createDom("svg");goog.dom.insertSiblingAfter(d,b);c.init(a);return c};Blockly.VERSION="4.0.15";Blockly.mainWorkspace=null;Blockly.selected=null;Blockly.draggingConnections=[];Blockly.clipboardXml_=null;Blockly.clipboardSource_=null;Blockly.clipboardTypeCounts_=null;Blockly.cache3dSupported_=null;Blockly.parentContainer=null;Blockly.svgSize=function(a){Blockly.utils.deprecation.warn("Blockly.svgSize","March 2021","March 2022","workspace.getCachedParentSvgSize");return new Blockly.utils.Size(a.cachedWidth_,a.cachedHeight_)};Blockly.resizeSvgContents=function(a){a.resizeContents()};
1088
1088
  Blockly.svgResize=function(a){for(;a.options.parentWorkspace;)a=a.options.parentWorkspace;var b=a.getParentSvg(),c=a.getCachedParentSvgSize(),d=b.parentNode;if(d){var e=d.offsetWidth;d=d.offsetHeight;c.width!=e&&(b.setAttribute("width",e+"px"),a.setCachedParentSvgSize(e,null));c.height!=d&&(b.setAttribute("height",d+"px"),a.setCachedParentSvgSize(null,d));a.resize()}};
1089
1089
  Blockly.onKeyDown=function(a){var b=Blockly.mainWorkspace;if(b&&!(Blockly.utils.isTargetInput(a)||b.rendered&&!b.isVisible()))Blockly.ShortcutRegistry.registry.onKeyDown(b,a)};Blockly.deleteBlock=function(a){a.workspace.isFlyout||(Blockly.Events.setGroup(!0),Blockly.hideChaff(),a.outputConnection?a.dispose(!1,!0):a.dispose(!0,!0),Blockly.Events.setGroup(!1))};Blockly.copy=function(a){if(a=a.toCopyData())Blockly.clipboardXml_=a.xml,Blockly.clipboardSource_=a.source,Blockly.clipboardTypeCounts_=a.typeCounts};
1090
1090
  Blockly.paste=function(){if(!Blockly.clipboardXml_)return!1;var a=Blockly.clipboardSource_;a.isFlyout&&(a=a.targetWorkspace);return Blockly.clipboardTypeCounts_&&a.isCapacityAvailable(Blockly.clipboardTypeCounts_)?(Blockly.Events.setGroup(!0),a.paste(Blockly.clipboardXml_),Blockly.Events.setGroup(!1),!0):!1};
@@ -1241,7 +1241,7 @@ weight:1,capabilities:[Blockly.ComponentManager.Capability.AUTOHIDEABLE,Blockly.
1241
1241
  Blockly.Toolbox.prototype.createDom_=function(a){a=a.getParentSvg();var b=this.createContainer_();this.contentsDiv_=this.createContentsContainer_();this.contentsDiv_.tabIndex=0;Blockly.utils.aria.setRole(this.contentsDiv_,Blockly.utils.aria.Role.TREE);b.appendChild(this.contentsDiv_);a.parentNode.insertBefore(b,a);this.attachEvents_(b,this.contentsDiv_);return b};
1242
1242
  Blockly.Toolbox.prototype.createContainer_=function(){var a=document.createElement("div");a.setAttribute("layout",this.isHorizontal()?"h":"v");Blockly.utils.dom.addClass(a,"blocklyToolboxDiv");Blockly.utils.dom.addClass(a,"blocklyNonSelectable");a.setAttribute("dir",this.RTL?"RTL":"LTR");return a};
1243
1243
  Blockly.Toolbox.prototype.createContentsContainer_=function(){var a=document.createElement("div");Blockly.utils.dom.addClass(a,"blocklyToolboxContents");this.isHorizontal()&&(a.style.flexDirection="row");return a};Blockly.Toolbox.prototype.attachEvents_=function(a,b){a=Blockly.browserEvents.conditionalBind(a,"click",this,this.onClick_,!1,!0);this.boundEvents_.push(a);b=Blockly.browserEvents.conditionalBind(b,"keydown",this,this.onKeyDown_,!1,!0);this.boundEvents_.push(b)};
1244
- Blockly.Toolbox.prototype.onClick_=function(a){if(Blockly.utils.isRightButton(a)||a.target==this.HtmlDiv)Blockly.hideChaff(!1);else{var b=a.target.getAttribute("id");b&&(b=this.getToolboxItemById(b),b.isSelectable()&&(this.setSelectedItem(b),b.onClick(a)));Blockly.hideChaff(!0)}Blockly.Touch.clearTouchIdentifier()};
1244
+ Blockly.Toolbox.prototype.onClick_=function(a){if(Blockly.utils.isRightButton(a)||a.target==this.HtmlDiv)Blockly.hideChaff(!1);else{var b=a.target.getAttribute("id");b&&(b=this.getToolboxItemById(b))&&b.isSelectable()&&(this.setSelectedItem(b),b.onClick(a));Blockly.hideChaff(!0)}Blockly.Touch.clearTouchIdentifier()};
1245
1245
  Blockly.Toolbox.prototype.onKeyDown_=function(a){var b=!1;switch(a.keyCode){case Blockly.utils.KeyCodes.DOWN:b=this.selectNext_();break;case Blockly.utils.KeyCodes.UP:b=this.selectPrevious_();break;case Blockly.utils.KeyCodes.LEFT:b=this.selectParent_();break;case Blockly.utils.KeyCodes.RIGHT:b=this.selectChild_();break;case Blockly.utils.KeyCodes.ENTER:case Blockly.utils.KeyCodes.SPACE:this.selectedItem_&&this.selectedItem_.isCollapsible()&&(this.selectedItem_.toggleExpanded(),b=!0);break;default:b=
1246
1246
  !1}!b&&this.selectedItem_&&this.selectedItem_.onKeyDown&&(b=this.selectedItem_.onKeyDown(a));b&&a.preventDefault()};
1247
1247
  Blockly.Toolbox.prototype.createFlyout_=function(){var a=this.workspace_,b=new Blockly.Options({parentWorkspace:a,rtl:a.RTL,oneBasedIndex:a.options.oneBasedIndex,horizontalLayout:a.horizontalLayout,renderer:a.options.renderer,rendererOverrides:a.options.rendererOverrides,move:{scrollbars:!0}});b.toolboxPosition=a.options.toolboxPosition;return new (a.horizontalLayout?Blockly.registry.getClassFromOptions(Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX,a.options,!0):Blockly.registry.getClassFromOptions(Blockly.registry.Type.FLYOUTS_VERTICAL_TOOLBOX,
@@ -4357,6 +4357,56 @@ ${output}</xml>`;
4357
4357
  }
4358
4358
  return undefined;
4359
4359
  }
4360
+ function getCallKey(statement) {
4361
+ const call = statement.expression;
4362
+ const callInfo = pxtc.pxtInfo(call).callInfo;
4363
+ const attributes = attrs(callInfo);
4364
+ if (attributes.blockAllowMultiple)
4365
+ return undefined;
4366
+ if (attributes.blockHandlerKey)
4367
+ return attributes.blockHandlerKey;
4368
+ const args = callInfo.args.filter(arg => !ts.isArrowFunction(arg) && !isFunctionExpression(arg)).map(arg => getArgKeyRecursive(arg)).join("$$");
4369
+ return attributes.blockId + "-" + args;
4370
+ }
4371
+ // custom function to get the key for an argument. we do this instead of simply calling getText() because this
4372
+ // handles whitespace and certain passthrough nodes like parenthesized expressions
4373
+ function getArgKeyRecursive(n) {
4374
+ if (!n)
4375
+ return "";
4376
+ switch (n.kind) {
4377
+ case SK.ParenthesizedExpression:
4378
+ case SK.AsExpression:
4379
+ return getArgKeyRecursive(n.expression);
4380
+ case SK.Identifier:
4381
+ return n.text;
4382
+ case SK.StringLiteral:
4383
+ case SK.FirstTemplateToken:
4384
+ case SK.NoSubstitutionTemplateLiteral:
4385
+ return `"${n.text}"`;
4386
+ case SK.NumericLiteral:
4387
+ return n.text;
4388
+ case SK.TrueKeyword:
4389
+ return "true";
4390
+ case SK.FalseKeyword:
4391
+ return "false";
4392
+ case SK.BinaryExpression:
4393
+ return `{${getArgKeyRecursive(n.left)}${n.operatorToken.getText()}${getArgKeyRecursive(n.right)}}`;
4394
+ case SK.PrefixUnaryExpression:
4395
+ return n.operator + getArgKeyRecursive(n.operand);
4396
+ case SK.PropertyAccessExpression:
4397
+ return getArgKeyRecursive(n.expression) + "." + getArgKeyRecursive(n.name);
4398
+ case SK.ArrayLiteralExpression:
4399
+ return `[${n.elements.map(e => getArgKeyRecursive(e))}]`;
4400
+ case SK.ElementAccessExpression:
4401
+ return `${n.expression}[${n.argumentExpression}]`;
4402
+ case SK.TaggedTemplateExpression:
4403
+ return `${getArgKeyRecursive(n.tag)}\`${n.template.getText()}\``;
4404
+ case SK.CallExpression:
4405
+ return `${getArgKeyRecursive(n.expression)}(${n.arguments.map(getArgKeyRecursive).join(",")})`;
4406
+ default:
4407
+ return n.getText();
4408
+ }
4409
+ }
4360
4410
  function countBlock() {
4361
4411
  emittedBlocks++;
4362
4412
  if (emittedBlocks > MAX_BLOCKS) {
@@ -5898,7 +5948,20 @@ ${output}</xml>`;
5898
5948
  blockStatements.unshift(statement);
5899
5949
  }
5900
5950
  }
5901
- eventStatements.map(n => getStatementBlock(n, undefined, undefined, false, topLevel)).forEach(emitStatementNode);
5951
+ const compiledEvents = [];
5952
+ const keyMap = {};
5953
+ for (const statement of eventStatements) {
5954
+ const key = statement.kind === SK.FunctionDeclaration ? undefined : getCallKey(statement);
5955
+ if (key && keyMap[key]) {
5956
+ // Pass false for topLevel to force a grey block
5957
+ compiledEvents.push(getStatementBlock(statement, undefined, undefined, false, false));
5958
+ }
5959
+ else {
5960
+ keyMap[key] = true;
5961
+ compiledEvents.push(getStatementBlock(statement, undefined, undefined, false, topLevel));
5962
+ }
5963
+ }
5964
+ compiledEvents.forEach(emitStatementNode);
5902
5965
  if (blockStatements.length) {
5903
5966
  // wrap statement in "on start" if top level
5904
5967
  const blockNode = blockStatements.shift();
package/built/pxtlib.d.ts CHANGED
@@ -860,6 +860,7 @@ declare namespace pxt.BrowserUtils {
860
860
  export function getCookieLang(): string;
861
861
  export function setCookieLang(langId: string, docs?: boolean): void;
862
862
  export function cacheBustingUrl(url: string): string;
863
+ export function legacyCopyText(element: HTMLInputElement | HTMLTextAreaElement): boolean;
863
864
  export {};
864
865
  }
865
866
  declare namespace pxt.cloud {
package/built/pxtlib.js CHANGED
@@ -5688,7 +5688,9 @@ var pxt;
5688
5688
  const height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
5689
5689
  const left = ((width / 2) - (popUpWidth / 2)) + winLeft;
5690
5690
  const top = ((height / 2) - (popUpHeight / 2)) + winTop;
5691
- const popupWindow = window.open(url, title, "width=" + popUpWidth + ", height=" + popUpHeight + ", top=" + top + ", left=" + left);
5691
+ const features = "width=" + popUpWidth + ", height=" + popUpHeight + ", top=" + top + ", left=" + left;
5692
+ // Current CEF version does not like when features parameter is passed and just immediately rejects.
5693
+ const popupWindow = window.open(url, title, !pxt.BrowserUtils.isIpcRenderer() ? features : undefined);
5692
5694
  if (popupWindow.focus) {
5693
5695
  popupWindow.focus();
5694
5696
  }
@@ -5696,7 +5698,7 @@ var pxt;
5696
5698
  }
5697
5699
  catch (e) {
5698
5700
  // Error opening popup
5699
- pxt.tickEvent('pxt.popupError', { url: url, msg: e.message });
5701
+ pxt.tickEvent('pxt.popupError', { msg: e.message });
5700
5702
  return null;
5701
5703
  }
5702
5704
  }
@@ -5774,6 +5776,19 @@ var pxt;
5774
5776
  return `${url}${url.indexOf('?') > 0 ? "&" : "?"}rnd=${Math.random()}`;
5775
5777
  }
5776
5778
  BrowserUtils.cacheBustingUrl = cacheBustingUrl;
5779
+ function legacyCopyText(element) {
5780
+ element.focus();
5781
+ element.setSelectionRange(0, 9999);
5782
+ try {
5783
+ const success = document.execCommand("copy");
5784
+ pxt.debug('copy: ' + success);
5785
+ return !!success;
5786
+ }
5787
+ catch (e) {
5788
+ return false;
5789
+ }
5790
+ }
5791
+ BrowserUtils.legacyCopyText = legacyCopyText;
5777
5792
  })(BrowserUtils = pxt.BrowserUtils || (pxt.BrowserUtils = {}));
5778
5793
  })(pxt || (pxt = {}));
5779
5794
  var pxt;
@@ -8698,11 +8713,16 @@ var pxt;
8698
8713
  docs.prepTemplate = prepTemplate;
8699
8714
  function setupRenderer(renderer) {
8700
8715
  renderer.image = function (href, title, text) {
8716
+ const endpointName = "makecode-lucas-testing-makecodetempmediaservice-usea";
8701
8717
  if (href.startsWith("youtube:")) {
8702
8718
  let out = '<div class="tutorial-video-embed"><iframe src="https://www.youtube.com/embed/' + href.split(":").pop()
8703
8719
  + '" title="' + title + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
8704
8720
  return out;
8705
8721
  }
8722
+ else if (href.startsWith("azuremedia:")) {
8723
+ let out = `<div class="tutorial-video-embed"><video class="ams-embed" controls src="https://${endpointName}.streaming.media.azure.net/` + href.split(":").pop() + '/manifest(format=mpd-time-cmaf)" /></div>';
8724
+ return out;
8725
+ }
8706
8726
  else {
8707
8727
  let out = '<img class="ui image" src="' + href + '" alt="' + text + '"';
8708
8728
  if (title) {