pxt-core 7.4.26 → 7.5.3

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.
Files changed (40) hide show
  1. package/built/cli.js +57 -5
  2. package/built/pxt.js +194 -11
  3. package/built/pxtblockly.js +83 -32
  4. package/built/pxtblocks.d.ts +1 -0
  5. package/built/pxtblocks.js +83 -32
  6. package/built/pxtcompiler.js +42 -4
  7. package/built/pxtlib.d.ts +2 -0
  8. package/built/pxtlib.js +22 -0
  9. package/built/pxtpy.js +73 -2
  10. package/built/server.js +4 -0
  11. package/built/target.js +1 -1
  12. package/built/web/main.js +1 -1
  13. package/built/web/pxtapp.js +1 -1
  14. package/built/web/pxtasseteditor.js +1 -1
  15. package/built/web/pxtblockly.js +2 -2
  16. package/built/web/pxtblocks.js +1 -1
  17. package/built/web/pxtcompiler.js +1 -1
  18. package/built/web/pxtembed.js +2 -2
  19. package/built/web/pxtlib.js +1 -1
  20. package/built/web/pxtpy.js +1 -1
  21. package/built/web/pxtworker.js +1 -1
  22. package/built/web/react-common-authcode.css +6008 -0
  23. package/built/web/react-common-skillmap.css +1 -1
  24. package/built/web/rtlreact-common-skillmap.css +1 -1
  25. package/built/web/rtlsemantic.css +1 -1
  26. package/built/web/semantic.css +1 -1
  27. package/common-docs/faq.md +1 -1
  28. package/common-docs/translate.md +2 -2
  29. package/package.json +2 -2
  30. package/react-common/components/controls/EditorToggle.tsx +109 -0
  31. package/react-common/styles/controls/Button.less +4 -0
  32. package/react-common/styles/controls/EditorToggle.less +233 -0
  33. package/react-common/styles/profile/profile.less +2 -2
  34. package/react-common/styles/react-common-authcode-core.less +10 -0
  35. package/react-common/styles/react-common-authcode.less +12 -0
  36. package/react-common/styles/react-common-variables.less +24 -0
  37. package/react-common/styles/react-common.less +1 -0
  38. package/theme/common.less +5 -0
  39. package/theme/image-editor/imageEditor.less +7 -116
  40. package/webapp/public/authcode.html +1 -0
@@ -3741,7 +3741,7 @@ var pxt;
3741
3741
  }
3742
3742
  else if (b.type == "argument_reporter_array") {
3743
3743
  if (!tp) {
3744
- tp = ground("any[]");
3744
+ tp = lookup(e, b, b.getFieldValue("VALUE")).type;
3745
3745
  }
3746
3746
  }
3747
3747
  if (tp)
@@ -4054,8 +4054,14 @@ var pxt;
4054
4054
  // Last pass: if some variable has no type (because it was never used or
4055
4055
  // assigned to), just unify it with int...
4056
4056
  e.allVariables.forEach((v) => {
4057
- if (getConcreteType(v.type).type == null)
4058
- union(v.type, ground(v.type.isArrayType ? "number[]" : pNumber.type));
4057
+ if (getConcreteType(v.type).type == null) {
4058
+ if (!v.isFunctionParameter) {
4059
+ union(v.type, ground(v.type.isArrayType ? "number[]" : pNumber.type));
4060
+ }
4061
+ else if (v.type.isArrayType) {
4062
+ v.type.type = "any[]";
4063
+ }
4064
+ }
4059
4065
  });
4060
4066
  function connectionCheck(i) {
4061
4067
  return i.name ? i.connection && i.connection.check_ && i.connection.check_.length ? i.connection.check_[0] : "T" : undefined;
@@ -4144,9 +4150,31 @@ var pxt;
4144
4150
  function compileNumber(e, b, comments) {
4145
4151
  return blocks_1.H.mkNumberLiteral(extractNumber(b));
4146
4152
  }
4153
+ function isNumericLiteral(e, b) {
4154
+ if (!b)
4155
+ return false;
4156
+ if (b.type === "math_number" || b.type === "math_integer" || b.type === "math_number_minmax" || b.type === "math_whole_number") {
4157
+ return true;
4158
+ }
4159
+ const blockInfo = e.stdCallTable[b.type];
4160
+ if (!blockInfo)
4161
+ return false;
4162
+ const { comp } = blockInfo;
4163
+ if (blockInfo.attrs.shim === "TD_ID" && comp.parameters.length === 1) {
4164
+ const fieldValue = b.getFieldValue(comp.parameters[0].definitionName);
4165
+ if (fieldValue) {
4166
+ return !isNaN(parseInt(fieldValue));
4167
+ }
4168
+ else {
4169
+ return isNumericLiteral(e, getInputTargetBlock(b, comp.parameters[0].definitionName));
4170
+ }
4171
+ }
4172
+ return false;
4173
+ }
4174
+ function isLiteral(e, b) {
4175
+ return isNumericLiteral(e, b) || b.type === "logic_boolean" || b.type === "text";
4176
+ }
4147
4177
  let opToTok = {
4148
- // POWER gets a special treatment because there's no operator for it in
4149
- // TouchDevelop
4150
4178
  "ADD": "+",
4151
4179
  "MINUS": "-",
4152
4180
  "MULTIPLY": "*",
@@ -4161,11 +4189,21 @@ var pxt;
4161
4189
  "NEQ": "!=",
4162
4190
  "POWER": "**"
4163
4191
  };
4192
+ function isComparisonOp(op) {
4193
+ return ["LT", "LTE", "GT", "GTE", "EQ", "NEQ"].indexOf(op) !== -1;
4194
+ }
4164
4195
  function compileArithmetic(e, b, comments) {
4165
4196
  let bOp = b.getFieldValue("OP");
4166
4197
  let left = getInputTargetBlock(b, "A");
4167
4198
  let right = getInputTargetBlock(b, "B");
4168
4199
  let args = [compileExpression(e, left, comments), compileExpression(e, right, comments)];
4200
+ // Special handling for the case of comparing two literals (e.g. 0 === 5). TypeScript
4201
+ // throws an error if we don't first cast to any
4202
+ if (isComparisonOp(bOp) && isLiteral(e, left) && isLiteral(e, right)) {
4203
+ if (blocks_1.flattenNode([args[0]]).output !== blocks_1.flattenNode([args[1]]).output) {
4204
+ args = args.map(arg => blocks_1.H.mkParenthesizedExpression(blocks_1.mkGroup([arg, blocks_1.mkText(" as any")])));
4205
+ }
4206
+ }
4169
4207
  let t = returnType(e, left).type;
4170
4208
  if (t == pString.type) {
4171
4209
  if (bOp == "EQ")
@@ -4273,7 +4311,10 @@ var pxt;
4273
4311
  const stmts = getInputTargetBlock(b, "STACK");
4274
4312
  const argsDeclaration = b.getArguments().map(a => {
4275
4313
  if (a.type == "Array") {
4276
- return `${escapeVarName(a.name, e)}: any[]`;
4314
+ const binding = lookup(e, b, a.name);
4315
+ const declaredType = getConcreteType(binding.type);
4316
+ const paramType = ((declaredType === null || declaredType === void 0 ? void 0 : declaredType.type) && declaredType.type !== "Array") ? declaredType.type : "any[]";
4317
+ return `${escapeVarName(a.name, e)}: ${paramType}`;
4277
4318
  }
4278
4319
  return `${escapeVarName(a.name, e)}: ${a.type}`;
4279
4320
  });
@@ -5421,7 +5462,7 @@ var pxt;
5421
5462
  return res;
5422
5463
  }
5423
5464
  function getEscapedCBParameters(b, stdfun, e) {
5424
- return getCBParameters(b, stdfun).map(binding => lookup(e, b, binding[0]).escapedName);
5465
+ return getCBParameters(b, stdfun).map(binding => lookup(e, b, binding.name).escapedName);
5425
5466
  }
5426
5467
  function getCBParameters(b, stdfun) {
5427
5468
  let handlerArgs = [];
@@ -5437,7 +5478,10 @@ var pxt;
5437
5478
  varName = varBlock && varBlock.getField("VAR").getText();
5438
5479
  }
5439
5480
  if (varName !== null) {
5440
- handlerArgs.push([varName, mkPoint(arg.type)]);
5481
+ handlerArgs.push({
5482
+ name: varName,
5483
+ type: mkPoint(arg.type)
5484
+ });
5441
5485
  }
5442
5486
  else {
5443
5487
  break;
@@ -5450,7 +5494,10 @@ var pxt;
5450
5494
  const varField = b.getField("HANDLER_" + arg.name);
5451
5495
  const varName = varField && varField.getText();
5452
5496
  if (varName !== null) {
5453
- handlerArgs.push([varName, mkPoint(arg.type)]);
5497
+ handlerArgs.push({
5498
+ name: varName,
5499
+ type: mkPoint(arg.type)
5500
+ });
5454
5501
  }
5455
5502
  else {
5456
5503
  break;
@@ -5653,11 +5700,7 @@ var pxt;
5653
5700
  }
5654
5701
  if (hasStatementInput(block)) {
5655
5702
  const vars = getDeclaredVariables(block, e).map(binding => {
5656
- return {
5657
- name: binding[0],
5658
- type: binding[1],
5659
- id: id++
5660
- };
5703
+ return Object.assign(Object.assign({}, binding), { id: id++ });
5661
5704
  });
5662
5705
  let parentScope = currentScope;
5663
5706
  if (vars.length) {
@@ -5741,17 +5784,37 @@ var pxt;
5741
5784
  switch (block.type) {
5742
5785
  case 'pxt_controls_for':
5743
5786
  case 'controls_simple_for':
5744
- return [[getLoopVariableField(block).getField("VAR").getText(), pNumber]];
5787
+ return [{
5788
+ name: getLoopVariableField(block).getField("VAR").getText(),
5789
+ type: pNumber
5790
+ }];
5745
5791
  case 'pxt_controls_for_of':
5746
5792
  case 'controls_for_of':
5747
- return [[getLoopVariableField(block).getField("VAR").getText(), mkPoint(null)]];
5793
+ return [{
5794
+ name: getLoopVariableField(block).getField("VAR").getText(),
5795
+ type: mkPoint(null)
5796
+ }];
5797
+ case 'function_definition':
5798
+ return block.getArguments().filter(arg => arg.type === "Array")
5799
+ .map(arg => {
5800
+ const point = mkPoint(null);
5801
+ point.isArrayType = true;
5802
+ return {
5803
+ name: arg.name,
5804
+ type: point,
5805
+ isFunctionParameter: true
5806
+ };
5807
+ });
5748
5808
  default:
5749
5809
  break;
5750
5810
  }
5751
5811
  if (isMutatingBlock(block)) {
5752
5812
  const declarations = block.mutation.getDeclaredVariables();
5753
5813
  if (declarations) {
5754
- return Object.keys(declarations).map(varName => [varName, mkPoint(declarations[varName])]);
5814
+ return Object.keys(declarations).map(varName => ({
5815
+ name: varName,
5816
+ type: mkPoint(declarations[varName])
5817
+ }));
5755
5818
  }
5756
5819
  }
5757
5820
  let stdFunc = e.stdCallTable[block.type];
@@ -7640,21 +7703,9 @@ var pxt;
7640
7703
  || (nsinfo && nsinfo.attributes.color)
7641
7704
  || pxt.toolbox.getNamespaceColor(ns)
7642
7705
  || 255;
7643
- if (fn.attributes.help) {
7644
- const helpUrl = fn.attributes.help.replace(/^\//, '');
7645
- if (/^github:/.test(helpUrl)) {
7646
- block.setHelpUrl(helpUrl);
7647
- }
7648
- else if (helpUrl !== "none") {
7649
- block.setHelpUrl("/reference/" + helpUrl);
7650
- }
7651
- }
7652
- else if (fn.pkg && !pxt.appTarget.bundledpkgs[fn.pkg]) { // added package
7653
- let anchor = fn.qName.toLowerCase().split('.');
7654
- if (anchor[0] == fn.pkg)
7655
- anchor.shift();
7656
- block.setHelpUrl(`/pkg/${fn.pkg}#${encodeURIComponent(anchor.join('-'))}`);
7657
- }
7706
+ const helpUrl = pxt.blocks.getHelpUrl(fn);
7707
+ if (helpUrl)
7708
+ block.setHelpUrl(helpUrl);
7658
7709
  block.setColour(color);
7659
7710
  let blockShape = Blockly.OUTPUT_SHAPE_ROUND;
7660
7711
  if (fn.retType == "boolean")
@@ -39,6 +39,7 @@ declare namespace pxt.blocks {
39
39
  alreadyDeclared?: BlockDeclarationType;
40
40
  firstReference?: Blockly.Block;
41
41
  isAssigned?: boolean;
42
+ isFunctionParameter?: boolean;
42
43
  }
43
44
  function compileExpression(e: Environment, b: Blockly.Block, comments: string[]): JsNode;
44
45
  interface Environment {
@@ -179,7 +179,7 @@ var pxt;
179
179
  }
180
180
  else if (b.type == "argument_reporter_array") {
181
181
  if (!tp) {
182
- tp = ground("any[]");
182
+ tp = lookup(e, b, b.getFieldValue("VALUE")).type;
183
183
  }
184
184
  }
185
185
  if (tp)
@@ -492,8 +492,14 @@ var pxt;
492
492
  // Last pass: if some variable has no type (because it was never used or
493
493
  // assigned to), just unify it with int...
494
494
  e.allVariables.forEach((v) => {
495
- if (getConcreteType(v.type).type == null)
496
- union(v.type, ground(v.type.isArrayType ? "number[]" : pNumber.type));
495
+ if (getConcreteType(v.type).type == null) {
496
+ if (!v.isFunctionParameter) {
497
+ union(v.type, ground(v.type.isArrayType ? "number[]" : pNumber.type));
498
+ }
499
+ else if (v.type.isArrayType) {
500
+ v.type.type = "any[]";
501
+ }
502
+ }
497
503
  });
498
504
  function connectionCheck(i) {
499
505
  return i.name ? i.connection && i.connection.check_ && i.connection.check_.length ? i.connection.check_[0] : "T" : undefined;
@@ -582,9 +588,31 @@ var pxt;
582
588
  function compileNumber(e, b, comments) {
583
589
  return blocks_1.H.mkNumberLiteral(extractNumber(b));
584
590
  }
591
+ function isNumericLiteral(e, b) {
592
+ if (!b)
593
+ return false;
594
+ if (b.type === "math_number" || b.type === "math_integer" || b.type === "math_number_minmax" || b.type === "math_whole_number") {
595
+ return true;
596
+ }
597
+ const blockInfo = e.stdCallTable[b.type];
598
+ if (!blockInfo)
599
+ return false;
600
+ const { comp } = blockInfo;
601
+ if (blockInfo.attrs.shim === "TD_ID" && comp.parameters.length === 1) {
602
+ const fieldValue = b.getFieldValue(comp.parameters[0].definitionName);
603
+ if (fieldValue) {
604
+ return !isNaN(parseInt(fieldValue));
605
+ }
606
+ else {
607
+ return isNumericLiteral(e, getInputTargetBlock(b, comp.parameters[0].definitionName));
608
+ }
609
+ }
610
+ return false;
611
+ }
612
+ function isLiteral(e, b) {
613
+ return isNumericLiteral(e, b) || b.type === "logic_boolean" || b.type === "text";
614
+ }
585
615
  let opToTok = {
586
- // POWER gets a special treatment because there's no operator for it in
587
- // TouchDevelop
588
616
  "ADD": "+",
589
617
  "MINUS": "-",
590
618
  "MULTIPLY": "*",
@@ -599,11 +627,21 @@ var pxt;
599
627
  "NEQ": "!=",
600
628
  "POWER": "**"
601
629
  };
630
+ function isComparisonOp(op) {
631
+ return ["LT", "LTE", "GT", "GTE", "EQ", "NEQ"].indexOf(op) !== -1;
632
+ }
602
633
  function compileArithmetic(e, b, comments) {
603
634
  let bOp = b.getFieldValue("OP");
604
635
  let left = getInputTargetBlock(b, "A");
605
636
  let right = getInputTargetBlock(b, "B");
606
637
  let args = [compileExpression(e, left, comments), compileExpression(e, right, comments)];
638
+ // Special handling for the case of comparing two literals (e.g. 0 === 5). TypeScript
639
+ // throws an error if we don't first cast to any
640
+ if (isComparisonOp(bOp) && isLiteral(e, left) && isLiteral(e, right)) {
641
+ if (blocks_1.flattenNode([args[0]]).output !== blocks_1.flattenNode([args[1]]).output) {
642
+ args = args.map(arg => blocks_1.H.mkParenthesizedExpression(blocks_1.mkGroup([arg, blocks_1.mkText(" as any")])));
643
+ }
644
+ }
607
645
  let t = returnType(e, left).type;
608
646
  if (t == pString.type) {
609
647
  if (bOp == "EQ")
@@ -711,7 +749,10 @@ var pxt;
711
749
  const stmts = getInputTargetBlock(b, "STACK");
712
750
  const argsDeclaration = b.getArguments().map(a => {
713
751
  if (a.type == "Array") {
714
- return `${escapeVarName(a.name, e)}: any[]`;
752
+ const binding = lookup(e, b, a.name);
753
+ const declaredType = getConcreteType(binding.type);
754
+ const paramType = ((declaredType === null || declaredType === void 0 ? void 0 : declaredType.type) && declaredType.type !== "Array") ? declaredType.type : "any[]";
755
+ return `${escapeVarName(a.name, e)}: ${paramType}`;
715
756
  }
716
757
  return `${escapeVarName(a.name, e)}: ${a.type}`;
717
758
  });
@@ -1859,7 +1900,7 @@ var pxt;
1859
1900
  return res;
1860
1901
  }
1861
1902
  function getEscapedCBParameters(b, stdfun, e) {
1862
- return getCBParameters(b, stdfun).map(binding => lookup(e, b, binding[0]).escapedName);
1903
+ return getCBParameters(b, stdfun).map(binding => lookup(e, b, binding.name).escapedName);
1863
1904
  }
1864
1905
  function getCBParameters(b, stdfun) {
1865
1906
  let handlerArgs = [];
@@ -1875,7 +1916,10 @@ var pxt;
1875
1916
  varName = varBlock && varBlock.getField("VAR").getText();
1876
1917
  }
1877
1918
  if (varName !== null) {
1878
- handlerArgs.push([varName, mkPoint(arg.type)]);
1919
+ handlerArgs.push({
1920
+ name: varName,
1921
+ type: mkPoint(arg.type)
1922
+ });
1879
1923
  }
1880
1924
  else {
1881
1925
  break;
@@ -1888,7 +1932,10 @@ var pxt;
1888
1932
  const varField = b.getField("HANDLER_" + arg.name);
1889
1933
  const varName = varField && varField.getText();
1890
1934
  if (varName !== null) {
1891
- handlerArgs.push([varName, mkPoint(arg.type)]);
1935
+ handlerArgs.push({
1936
+ name: varName,
1937
+ type: mkPoint(arg.type)
1938
+ });
1892
1939
  }
1893
1940
  else {
1894
1941
  break;
@@ -2091,11 +2138,7 @@ var pxt;
2091
2138
  }
2092
2139
  if (hasStatementInput(block)) {
2093
2140
  const vars = getDeclaredVariables(block, e).map(binding => {
2094
- return {
2095
- name: binding[0],
2096
- type: binding[1],
2097
- id: id++
2098
- };
2141
+ return Object.assign(Object.assign({}, binding), { id: id++ });
2099
2142
  });
2100
2143
  let parentScope = currentScope;
2101
2144
  if (vars.length) {
@@ -2179,17 +2222,37 @@ var pxt;
2179
2222
  switch (block.type) {
2180
2223
  case 'pxt_controls_for':
2181
2224
  case 'controls_simple_for':
2182
- return [[getLoopVariableField(block).getField("VAR").getText(), pNumber]];
2225
+ return [{
2226
+ name: getLoopVariableField(block).getField("VAR").getText(),
2227
+ type: pNumber
2228
+ }];
2183
2229
  case 'pxt_controls_for_of':
2184
2230
  case 'controls_for_of':
2185
- return [[getLoopVariableField(block).getField("VAR").getText(), mkPoint(null)]];
2231
+ return [{
2232
+ name: getLoopVariableField(block).getField("VAR").getText(),
2233
+ type: mkPoint(null)
2234
+ }];
2235
+ case 'function_definition':
2236
+ return block.getArguments().filter(arg => arg.type === "Array")
2237
+ .map(arg => {
2238
+ const point = mkPoint(null);
2239
+ point.isArrayType = true;
2240
+ return {
2241
+ name: arg.name,
2242
+ type: point,
2243
+ isFunctionParameter: true
2244
+ };
2245
+ });
2186
2246
  default:
2187
2247
  break;
2188
2248
  }
2189
2249
  if (isMutatingBlock(block)) {
2190
2250
  const declarations = block.mutation.getDeclaredVariables();
2191
2251
  if (declarations) {
2192
- return Object.keys(declarations).map(varName => [varName, mkPoint(declarations[varName])]);
2252
+ return Object.keys(declarations).map(varName => ({
2253
+ name: varName,
2254
+ type: mkPoint(declarations[varName])
2255
+ }));
2193
2256
  }
2194
2257
  }
2195
2258
  let stdFunc = e.stdCallTable[block.type];
@@ -4078,21 +4141,9 @@ var pxt;
4078
4141
  || (nsinfo && nsinfo.attributes.color)
4079
4142
  || pxt.toolbox.getNamespaceColor(ns)
4080
4143
  || 255;
4081
- if (fn.attributes.help) {
4082
- const helpUrl = fn.attributes.help.replace(/^\//, '');
4083
- if (/^github:/.test(helpUrl)) {
4084
- block.setHelpUrl(helpUrl);
4085
- }
4086
- else if (helpUrl !== "none") {
4087
- block.setHelpUrl("/reference/" + helpUrl);
4088
- }
4089
- }
4090
- else if (fn.pkg && !pxt.appTarget.bundledpkgs[fn.pkg]) { // added package
4091
- let anchor = fn.qName.toLowerCase().split('.');
4092
- if (anchor[0] == fn.pkg)
4093
- anchor.shift();
4094
- block.setHelpUrl(`/pkg/${fn.pkg}#${encodeURIComponent(anchor.join('-'))}`);
4095
- }
4144
+ const helpUrl = pxt.blocks.getHelpUrl(fn);
4145
+ if (helpUrl)
4146
+ block.setHelpUrl(helpUrl);
4096
4147
  block.setColour(color);
4097
4148
  let blockShape = Blockly.OUTPUT_SHAPE_ROUND;
4098
4149
  if (fn.retType == "boolean")
@@ -4620,6 +4620,8 @@ ${output}</xml>`;
4620
4620
  return getTaggedTemplateExpression(n);
4621
4621
  case SK.CallExpression:
4622
4622
  return getStatementBlock(n, undefined, undefined, true);
4623
+ case SK.AsExpression:
4624
+ return getOutputBlock(n.expression);
4623
4625
  default:
4624
4626
  error(n, pxtc.Util.lf("Unsupported syntax kind for output expression block: {0}", SK[n.kind]));
4625
4627
  break;
@@ -5500,11 +5502,14 @@ ${output}</xml>`;
5500
5502
  r.mutationChildren = [];
5501
5503
  n.parameters.forEach(p => {
5502
5504
  const paramName = p.name.getText();
5505
+ let type = normalizeType(p.type.getText());
5506
+ if (pxt.U.endsWith(type, "[]"))
5507
+ type = "Array";
5503
5508
  r.mutationChildren.push({
5504
5509
  nodeName: "arg",
5505
5510
  attributes: {
5506
5511
  name: paramName,
5507
- type: p.type.getText(),
5512
+ type,
5508
5513
  id: env.functionParamIds[name][paramName]
5509
5514
  }
5510
5515
  });
@@ -5580,11 +5585,14 @@ ${output}</xml>`;
5580
5585
  env.declaredFunctions[name].parameters.forEach((p, i) => {
5581
5586
  const paramName = p.name.getText();
5582
5587
  const argId = env.functionParamIds[name][paramName];
5588
+ let type = normalizeType(p.type.getText());
5589
+ if (pxt.U.endsWith(type, "[]"))
5590
+ type = "Array";
5583
5591
  r.mutationChildren.push({
5584
5592
  nodeName: "arg",
5585
5593
  attributes: {
5586
5594
  name: paramName,
5587
- type: p.type.getText(),
5595
+ type: type,
5588
5596
  id: argId
5589
5597
  }
5590
5598
  });
@@ -6452,7 +6460,8 @@ ${output}</xml>`;
6452
6460
  if (!type) {
6453
6461
  return pxtc.Util.lf("Function parameters must declare a type");
6454
6462
  }
6455
- if (env.opts.allowedArgumentTypes.indexOf(normalizeType(type)) === -1) {
6463
+ const normalized = normalizeType(type);
6464
+ if (env.opts.allowedArgumentTypes.indexOf(normalized) === -1 && !pxtc.U.endsWith(normalized, "[]")) {
6456
6465
  return pxtc.Util.lf("Only types that can be added in blocks can be used for function arguments");
6457
6466
  }
6458
6467
  }
@@ -6727,6 +6736,8 @@ ${output}</xml>`;
6727
6736
  return checkStatement(n, env, true, undefined);
6728
6737
  case SK.TaggedTemplateExpression:
6729
6738
  return checkTaggedTemplateExpression(n, env);
6739
+ case SK.AsExpression:
6740
+ return checkAsExpression(n);
6730
6741
  }
6731
6742
  return pxtc.Util.lf("Unsupported syntax kind for output expression block: {0}", SK[n.kind]);
6732
6743
  function checkStringLiteral(n) {
@@ -6823,6 +6834,31 @@ ${output}</xml>`;
6823
6834
  // The compiler will have already caught any invalid tags or templates
6824
6835
  return undefined;
6825
6836
  }
6837
+ function checkAsExpression(n) {
6838
+ // The only time we allow casts to decompile is in the very special case where someone has
6839
+ // written a program comparing two string, boolean, or numeric literals in blocks and
6840
+ // converted to text. e.g. 3 == 5 or true != false
6841
+ if (n.type.getText().trim() === "any" && (ts.isStringOrNumericLiteral(n.expression) ||
6842
+ n.expression.kind === SK.TrueKeyword || n.expression.kind === SK.FalseKeyword)) {
6843
+ const [parent] = getParent(n);
6844
+ if (parent.kind === SK.BinaryExpression) {
6845
+ switch (parent.operatorToken.kind) {
6846
+ case SK.EqualsEqualsToken:
6847
+ case SK.EqualsEqualsEqualsToken:
6848
+ case SK.ExclamationEqualsToken:
6849
+ case SK.ExclamationEqualsEqualsToken:
6850
+ case SK.LessThanToken:
6851
+ case SK.LessThanEqualsToken:
6852
+ case SK.GreaterThanToken:
6853
+ case SK.GreaterThanEqualsToken:
6854
+ return undefined;
6855
+ default:
6856
+ break;
6857
+ }
6858
+ }
6859
+ }
6860
+ return pxtc.Util.lf("Casting not supported in blocks");
6861
+ }
6826
6862
  function getParent(node) {
6827
6863
  if (!node.parent) {
6828
6864
  return [undefined, node];
@@ -12615,8 +12651,10 @@ ${lbl}: .short 0xffff
12615
12651
  return needsNumberConversions() ? pxtc.ir.rtcall("pxt::toInt", [e]) : e;
12616
12652
  };
12617
12653
  // c = a[i]
12618
- if (iterVar)
12654
+ if (iterVar) {
12619
12655
  proc.emitExpr(iterVar.storeByRef(pxtc.ir.rtcall(indexer, [collectionVar.loadCore(), toInt(intVarIter.loadCore())])));
12656
+ emitBrk(node.initializer);
12657
+ }
12620
12658
  flushHoistedFunctionDefinitions();
12621
12659
  emit(node.statement);
12622
12660
  proc.emitLblDirect(l.cont);
package/built/pxtlib.d.ts CHANGED
@@ -552,6 +552,7 @@ declare namespace pxt {
552
552
  multiUrl?: string;
553
553
  asseteditorUrl?: string;
554
554
  skillmapUrl?: string;
555
+ authcodeUrl?: string;
555
556
  isStatic?: boolean;
556
557
  verprefix?: string;
557
558
  }
@@ -656,6 +657,7 @@ declare namespace pxt.blocks {
656
657
  function normalizeBlock(b: string, err?: (msg: string) => void): string;
657
658
  function compileInfo(fn: pxtc.SymbolInfo): BlockCompileInfo;
658
659
  function hasHandler(fn: pxtc.SymbolInfo): boolean;
660
+ function getHelpUrl(fn: pxtc.SymbolInfo): string;
659
661
  /**
660
662
  * Returns which Blockly block type to use for an argument reporter based
661
663
  * on the specified TypeScript type.
package/built/pxtlib.js CHANGED
@@ -3909,6 +3909,25 @@ var pxt;
3909
3909
  });
3910
3910
  }
3911
3911
  blocks.hasHandler = hasHandler;
3912
+ function getHelpUrl(fn) {
3913
+ if (fn.attributes.help) {
3914
+ const helpUrl = fn.attributes.help.replace(/^\//, '');
3915
+ if (/^github:/.test(helpUrl)) {
3916
+ return helpUrl;
3917
+ }
3918
+ else if (helpUrl !== "none") {
3919
+ return "/reference/" + helpUrl;
3920
+ }
3921
+ }
3922
+ else if (fn.pkg && !pxt.appTarget.bundledpkgs[fn.pkg]) { // added package
3923
+ let anchor = fn.qName.toLowerCase().split('.');
3924
+ if (anchor[0] == fn.pkg)
3925
+ anchor.shift();
3926
+ return `/pkg/${fn.pkg}#${encodeURIComponent(anchor.join('-'))}`;
3927
+ }
3928
+ return undefined;
3929
+ }
3930
+ blocks.getHelpUrl = getHelpUrl;
3912
3931
  /**
3913
3932
  * Returns which Blockly block type to use for an argument reporter based
3914
3933
  * on the specified TypeScript type.
@@ -3920,6 +3939,9 @@ var pxt;
3920
3939
  if (varType === "boolean" || varType === "number" || varType === "string") {
3921
3940
  reporterType = `argument_reporter_${varType}`;
3922
3941
  }
3942
+ if (/^(?:Array<(?:.+)>)|(?:(?:.+)\[\])$/.test(varType)) {
3943
+ reporterType = "argument_reporter_array";
3944
+ }
3923
3945
  return reporterType;
3924
3946
  }
3925
3947
  blocks.reporterTypeForArgType = reporterTypeForArgType;