Always diplay sad face on errors; use nullCheck() function; see https://github.com/Microsoft/pxt/issues/302
This commit is contained in:
		@@ -154,7 +154,7 @@ namespace pxsim.instructions {
 | 
			
		||||
        //TODO: Refactor this function; it is too complicated. There is a lot of error-prone math being done
 | 
			
		||||
        // to scale and place all elements which could be simplified with more forethought.
 | 
			
		||||
        let svgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
 | 
			
		||||
        let dims = {l: 0, t: 0, w: 0, h: 0};
 | 
			
		||||
        let dims = { l: 0, t: 0, w: 0, h: 0 };
 | 
			
		||||
 | 
			
		||||
        let cmpSvgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
 | 
			
		||||
        svgEl.appendChild(cmpSvgEl);
 | 
			
		||||
@@ -181,7 +181,7 @@ namespace pxsim.instructions {
 | 
			
		||||
            scale(opts.cmpHeight / dims.h)
 | 
			
		||||
        }
 | 
			
		||||
        svg.hydrate(cmpSvgEl, cmpSvgAtts);
 | 
			
		||||
        let elDims = {l: dims.l, t: dims.t, w: dims.w, h: dims.h};
 | 
			
		||||
        let elDims = { l: dims.l, t: dims.t, w: dims.w, h: dims.h };
 | 
			
		||||
 | 
			
		||||
        let updateL = (newL: number) => {
 | 
			
		||||
            if (newL < dims.l) {
 | 
			
		||||
@@ -293,7 +293,7 @@ namespace pxsim.instructions {
 | 
			
		||||
            let cnstr = builtinComponentPartVisual[builtinVis];
 | 
			
		||||
            el = cnstr([0, 0]);
 | 
			
		||||
        } else {
 | 
			
		||||
            let partVis = <PartVisualDefinition> cmp;
 | 
			
		||||
            let partVis = <PartVisualDefinition>cmp;
 | 
			
		||||
            el = visuals.mkGenericPartSVG(partVis);
 | 
			
		||||
        }
 | 
			
		||||
        return wrapSvg(el, opts);
 | 
			
		||||
@@ -320,7 +320,7 @@ namespace pxsim.instructions {
 | 
			
		||||
            let step = w.assemblyStep + 1;
 | 
			
		||||
            (stepToWires[step] || (stepToWires[step] = [])).push(w)
 | 
			
		||||
        });
 | 
			
		||||
        let getMaxStep = (ns: {assemblyStep: number}[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0);
 | 
			
		||||
        let getMaxStep = (ns: { assemblyStep: number }[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0);
 | 
			
		||||
        let stepOffset = powerWires.length > 0 ? getMaxStep(powerWires) + 2 : 1;
 | 
			
		||||
        components.forEach(cAndWs => {
 | 
			
		||||
            let {component, wires} = cAndWs;
 | 
			
		||||
@@ -451,10 +451,10 @@ namespace pxsim.instructions {
 | 
			
		||||
 | 
			
		||||
        // board and breadboard
 | 
			
		||||
        let boardImg = mkBoardImgSvg(props.boardDef.visual);
 | 
			
		||||
        let board = wrapSvg(boardImg, {left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BOARD_SCALE});
 | 
			
		||||
        let board = wrapSvg(boardImg, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BOARD_SCALE });
 | 
			
		||||
        panel.appendChild(board);
 | 
			
		||||
        let bbRaw = mkBBSvg();
 | 
			
		||||
        let bb = wrapSvg(bbRaw, {left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BB_SCALE});
 | 
			
		||||
        let bb = wrapSvg(bbRaw, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BB_SCALE });
 | 
			
		||||
        panel.appendChild(bb);
 | 
			
		||||
 | 
			
		||||
        // components
 | 
			
		||||
@@ -592,7 +592,7 @@ namespace pxsim.instructions {
 | 
			
		||||
            //we use the docs renderer to decompile the code to blocks and render it
 | 
			
		||||
            //TODO: render the blocks code directly
 | 
			
		||||
            let md =
 | 
			
		||||
`\`\`\`blocks
 | 
			
		||||
                `\`\`\`blocks
 | 
			
		||||
${tsCode}
 | 
			
		||||
\`\`\`
 | 
			
		||||
\`\`\`package
 | 
			
		||||
@@ -600,9 +600,9 @@ ${tsPackage}
 | 
			
		||||
\`\`\`
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
            pxtdocs.requireMarked = function() { return (<any>window).marked; }
 | 
			
		||||
            pxtdocs.requireMarked = function () { return (<any>window).marked; }
 | 
			
		||||
            pxtrunner.renderMarkdownAsync(codeContainerDiv, md)
 | 
			
		||||
                .done(function() {
 | 
			
		||||
                .done(function () {
 | 
			
		||||
                    let codeSvg = $("#proj-code-container svg");
 | 
			
		||||
                    if (codeSvg.length > 0) {
 | 
			
		||||
                        //code rendered successfully as blocks
 | 
			
		||||
 
 | 
			
		||||
@@ -5,14 +5,33 @@
 | 
			
		||||
namespace pxsim {
 | 
			
		||||
    export type BBRowCol = [/*row*/string, /*column*/string];
 | 
			
		||||
    export type BoardPin = string;
 | 
			
		||||
    export interface BBLoc {type: "breadboard", rowCol: BBRowCol};
 | 
			
		||||
    export interface BoardLoc {type: "dalboard", pin: BoardPin};
 | 
			
		||||
    export interface BBLoc { type: "breadboard", rowCol: BBRowCol };
 | 
			
		||||
    export interface BoardLoc { type: "dalboard", pin: BoardPin };
 | 
			
		||||
    export type Loc = BBLoc | BoardLoc;
 | 
			
		||||
 | 
			
		||||
    export function initRuntimeWithDalBoard() {
 | 
			
		||||
        U.assert(!runtime.board);
 | 
			
		||||
        let b = new DalBoard();
 | 
			
		||||
        runtime.board = b;
 | 
			
		||||
        runtime.postError = (e) => {
 | 
			
		||||
            led.setBrightness(255);
 | 
			
		||||
            let img = board().ledMatrixState.image;
 | 
			
		||||
            img.clear();
 | 
			
		||||
            img.set(0, 4, 255);
 | 
			
		||||
            img.set(1, 3, 255);
 | 
			
		||||
            img.set(2, 3, 255);
 | 
			
		||||
            img.set(3, 3, 255);
 | 
			
		||||
            img.set(4, 4, 255);
 | 
			
		||||
            img.set(0, 0, 255);
 | 
			
		||||
            img.set(1, 0, 255);
 | 
			
		||||
            img.set(0, 1, 255);
 | 
			
		||||
            img.set(1, 1, 255);
 | 
			
		||||
            img.set(3, 0, 255);
 | 
			
		||||
            img.set(4, 0, 255);
 | 
			
		||||
            img.set(3, 1, 255);
 | 
			
		||||
            img.set(4, 1, 255);
 | 
			
		||||
            runtime.updateDisplay();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!pxsim.initCurrentRuntime) {
 | 
			
		||||
        pxsim.initCurrentRuntime = initRuntimeWithDalBoard;
 | 
			
		||||
@@ -58,7 +77,7 @@ namespace pxsim.visuals {
 | 
			
		||||
 | 
			
		||||
    export function translateEl(el: SVGElement, xy: [number, number]) {
 | 
			
		||||
        //TODO append translation instead of replacing the full transform
 | 
			
		||||
        svg.hydrate(el, {transform: `translate(${xy[0]} ${xy[1]})`});
 | 
			
		||||
        svg.hydrate(el, { transform: `translate(${xy[0]} ${xy[1]})` });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export interface ComposeOpts {
 | 
			
		||||
@@ -83,14 +102,14 @@ namespace pxsim.visuals {
 | 
			
		||||
    export function composeSVG(opts: ComposeOpts): ComposeResult {
 | 
			
		||||
        let [a, b] = [opts.el1, opts.el2];
 | 
			
		||||
        U.assert(a.x == 0 && a.y == 0 && b.x == 0 && b.y == 0, "el1 and el2 x,y offsets not supported");
 | 
			
		||||
        let setXY = (e: SVGSVGElement, x: number, y: number) => svg.hydrate(e, {x: x, y: y});
 | 
			
		||||
        let setXY = (e: SVGSVGElement, x: number, y: number) => svg.hydrate(e, { x: x, y: y });
 | 
			
		||||
        let setWH = (e: SVGSVGElement, w: string, h: string) => {
 | 
			
		||||
            if (w)
 | 
			
		||||
                svg.hydrate(e, {width: w});
 | 
			
		||||
                svg.hydrate(e, { width: w });
 | 
			
		||||
            if (h)
 | 
			
		||||
                svg.hydrate(e, {height: h});
 | 
			
		||||
                svg.hydrate(e, { height: h });
 | 
			
		||||
        }
 | 
			
		||||
        let setWHpx = (e: SVGSVGElement, w: number, h: number) => svg.hydrate(e, {width: `${w}px`, height: `${h}px`});
 | 
			
		||||
        let setWHpx = (e: SVGSVGElement, w: number, h: number) => svg.hydrate(e, { width: `${w}px`, height: `${h}px` });
 | 
			
		||||
        let scaleUnit = opts.scaleUnit2;
 | 
			
		||||
        let aScalar = opts.scaleUnit2 / opts.scaleUnit1;
 | 
			
		||||
        let bScalar = 1.0;
 | 
			
		||||
@@ -161,7 +180,7 @@ namespace pxsim.visuals {
 | 
			
		||||
            height: h,
 | 
			
		||||
            "href": `${opts.image}`
 | 
			
		||||
        });
 | 
			
		||||
        return {el: img, w: w, h: h, x: 0, y: 0};
 | 
			
		||||
        return { el: img, w: w, h: h, x: 0, y: 0 };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export type Coord = [number, number];
 | 
			
		||||
@@ -195,8 +214,10 @@ namespace pxsim.visuals {
 | 
			
		||||
        txtYOffFactor = txtYOffFactor || 0.3;
 | 
			
		||||
        const xOff = txtXOffFactor * size * txt.length;
 | 
			
		||||
        const yOff = txtYOffFactor * size;
 | 
			
		||||
        svg.hydrate(el, {style: `font-size:${size}px;`,
 | 
			
		||||
            transform: `translate(${cx} ${cy}) rotate(${rot}) translate(${xOff} ${yOff})` });
 | 
			
		||||
        svg.hydrate(el, {
 | 
			
		||||
            style: `font-size:${size}px;`,
 | 
			
		||||
            transform: `translate(${cx} ${cy}) rotate(${rot}) translate(${xOff} ${yOff})`
 | 
			
		||||
        });
 | 
			
		||||
        svg.addClass(el, "noselect");
 | 
			
		||||
        el.textContent = txt;
 | 
			
		||||
        return el;
 | 
			
		||||
 
 | 
			
		||||
@@ -195,26 +195,24 @@ namespace pxsim.images {
 | 
			
		||||
 | 
			
		||||
namespace pxsim.ImageMethods {
 | 
			
		||||
    export function showImage(leds: Image, offset: number) {
 | 
			
		||||
        if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
 | 
			
		||||
        pxtrt.nullCheck(leds)
 | 
			
		||||
        leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
 | 
			
		||||
        runtime.queueDisplayUpdate()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function plotImage(leds: Image, offset: number): void {
 | 
			
		||||
        if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
 | 
			
		||||
        pxtrt.nullCheck(leds)
 | 
			
		||||
        leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
 | 
			
		||||
        runtime.queueDisplayUpdate()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function height(leds: Image): number {
 | 
			
		||||
        if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
        pxtrt.nullCheck(leds)
 | 
			
		||||
        return Image.height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function width(leds: Image): number {
 | 
			
		||||
        if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
        pxtrt.nullCheck(leds)
 | 
			
		||||
        return leds.width;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -227,35 +225,32 @@ namespace pxsim.ImageMethods {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function pixel(leds: Image, x: number, y: number): number {
 | 
			
		||||
        if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
        pxtrt.nullCheck(leds)
 | 
			
		||||
        return leds.get(x, y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function setPixel(leds: Image, x: number, y: number, v: number) {
 | 
			
		||||
        if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
        pxtrt.nullCheck(leds)
 | 
			
		||||
        leds.set(x, y, v);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function clear(leds: Image) {
 | 
			
		||||
        if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
 | 
			
		||||
        pxtrt.nullCheck(leds)
 | 
			
		||||
        leds.clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function setPixelBrightness(i: Image, x: number, y: number, b: number) {
 | 
			
		||||
        if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
 | 
			
		||||
        pxtrt.nullCheck(i)
 | 
			
		||||
        i.set(x, y, b);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function pixelBrightness(i: Image, x: number, y: number): number {
 | 
			
		||||
        if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
 | 
			
		||||
        pxtrt.nullCheck(i)
 | 
			
		||||
        return i.get(x, y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export function scrollImage(leds: Image, stride: number, interval: number): void {
 | 
			
		||||
        if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
 | 
			
		||||
        pxtrt.nullCheck(leds)
 | 
			
		||||
        if (stride == 0) stride = 1;
 | 
			
		||||
 | 
			
		||||
        let cb = getResume();
 | 
			
		||||
 
 | 
			
		||||
@@ -19,24 +19,6 @@ namespace pxsim {
 | 
			
		||||
 | 
			
		||||
    export function panic(code: number) {
 | 
			
		||||
        console.log("PANIC:", code)
 | 
			
		||||
        led.setBrightness(255);
 | 
			
		||||
        let img = board().ledMatrixState.image;
 | 
			
		||||
        img.clear();
 | 
			
		||||
        img.set(0, 4, 255);
 | 
			
		||||
        img.set(1, 3, 255);
 | 
			
		||||
        img.set(2, 3, 255);
 | 
			
		||||
        img.set(3, 3, 255);
 | 
			
		||||
        img.set(4, 4, 255);
 | 
			
		||||
        img.set(0, 0, 255);
 | 
			
		||||
        img.set(1, 0, 255);
 | 
			
		||||
        img.set(0, 1, 255);
 | 
			
		||||
        img.set(1, 1, 255);
 | 
			
		||||
        img.set(3, 0, 255);
 | 
			
		||||
        img.set(4, 0, 255);
 | 
			
		||||
        img.set(3, 1, 255);
 | 
			
		||||
        img.set(4, 1, 255);
 | 
			
		||||
        runtime.updateDisplay();
 | 
			
		||||
 | 
			
		||||
        throw new Error("PANIC " + code)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user