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.
- package/built/cli.js +57 -5
- package/built/pxt.js +194 -11
- package/built/pxtblockly.js +83 -32
- package/built/pxtblocks.d.ts +1 -0
- package/built/pxtblocks.js +83 -32
- package/built/pxtcompiler.js +42 -4
- package/built/pxtlib.d.ts +2 -0
- package/built/pxtlib.js +22 -0
- package/built/pxtpy.js +73 -2
- package/built/server.js +4 -0
- package/built/target.js +1 -1
- package/built/web/main.js +1 -1
- package/built/web/pxtapp.js +1 -1
- package/built/web/pxtasseteditor.js +1 -1
- package/built/web/pxtblockly.js +2 -2
- package/built/web/pxtblocks.js +1 -1
- package/built/web/pxtcompiler.js +1 -1
- package/built/web/pxtembed.js +2 -2
- package/built/web/pxtlib.js +1 -1
- package/built/web/pxtpy.js +1 -1
- package/built/web/pxtworker.js +1 -1
- package/built/web/react-common-authcode.css +6008 -0
- package/built/web/react-common-skillmap.css +1 -1
- package/built/web/rtlreact-common-skillmap.css +1 -1
- package/built/web/rtlsemantic.css +1 -1
- package/built/web/semantic.css +1 -1
- package/common-docs/faq.md +1 -1
- package/common-docs/translate.md +2 -2
- package/package.json +2 -2
- package/react-common/components/controls/EditorToggle.tsx +109 -0
- package/react-common/styles/controls/Button.less +4 -0
- package/react-common/styles/controls/EditorToggle.less +233 -0
- package/react-common/styles/profile/profile.less +2 -2
- package/react-common/styles/react-common-authcode-core.less +10 -0
- package/react-common/styles/react-common-authcode.less +12 -0
- package/react-common/styles/react-common-variables.less +24 -0
- package/react-common/styles/react-common.less +1 -0
- package/theme/common.less +5 -0
- package/theme/image-editor/imageEditor.less +7 -116
- package/webapp/public/authcode.html +1 -0
package/built/pxtblockly.js
CHANGED
|
@@ -3741,7 +3741,7 @@ var pxt;
|
|
|
3741
3741
|
}
|
|
3742
3742
|
else if (b.type == "argument_reporter_array") {
|
|
3743
3743
|
if (!tp) {
|
|
3744
|
-
tp =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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 [
|
|
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 [
|
|
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 =>
|
|
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
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
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")
|
package/built/pxtblocks.d.ts
CHANGED
|
@@ -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 {
|
package/built/pxtblocks.js
CHANGED
|
@@ -179,7 +179,7 @@ var pxt;
|
|
|
179
179
|
}
|
|
180
180
|
else if (b.type == "argument_reporter_array") {
|
|
181
181
|
if (!tp) {
|
|
182
|
-
tp =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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 [
|
|
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 [
|
|
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 =>
|
|
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
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
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")
|
package/built/pxtcompiler.js
CHANGED
|
@@ -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
|
|
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:
|
|
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
|
-
|
|
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;
|