Skip to content

Commit

Permalink
Merge pull request #22855 from code-dot-org/dynamic-events
Browse files Browse the repository at this point in the history
Add a 'defer' option to custom block args
  • Loading branch information
balderdash committed Jun 7, 2018
2 parents adae0f0 + a4703b4 commit eeb51da
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 23 deletions.
1 change: 1 addition & 0 deletions apps/package.json
Expand Up @@ -89,6 +89,7 @@
"css-loader": "^0.23.1",
"csv-parse": "^1.1.7",
"data-collection": "^1.1.6",
"dedent": "^0.7.0",
"ejs": "0.8.4",
"ejs-compiled-loader": "2.1.1",
"enzyme": "2.8.0",
Expand Down
19 changes: 12 additions & 7 deletions apps/src/block_utils.js
Expand Up @@ -416,6 +416,9 @@ exports.cleanBlocks = function (blocksDom) {
* non-inlined blocks.
* @property {boolean} assignment Indicates that this block should generate
* an assignment statement, with this input yielding the variable name.
* @property {boolean} defer Indicates that this input should be wrapped in a
* function before being passed into func, so that evaluation can be deferred
* until later.
*/

/**
Expand Down Expand Up @@ -508,6 +511,7 @@ const determineInputs = function (text, args, strictTypes=[]) {
type: arg.type,
options: arg.options,
assignment: arg.assignment,
defer: arg.defer,
};
Object.keys(labeledInput).forEach(key => {
if (labeledInput[key] === undefined) {
Expand Down Expand Up @@ -825,18 +829,19 @@ exports.createJsWrapperBlockCreator = function (
let prefix = '';
const values = args.map(arg => {
const inputConfig = inputConfigs.find(input => input.name === arg.name);
const inputCode = inputTypes[inputConfig.mode].generateCode(this, inputConfig);
let inputCode = inputTypes[inputConfig.mode].generateCode(this, inputConfig);
if (inputConfig.assignment) {
prefix += `${inputCode} = `;
}
return inputCode;
}).filter(value => value !== null).map(value => {
if (value === "") {
if (inputCode === "") {
// Missing inputs should be passed into func as undefined
return "undefined";
inputCode = "undefined";
}
return value;
});
if (inputConfig.defer) {
inputCode = `function () {\n return ${inputCode};\n}`;
}
return inputCode;
}).filter(value => value !== null);

if (simpleValue) {
return [
Expand Down
15 changes: 10 additions & 5 deletions apps/src/gamelab/GameLabJr.interpreted.js
Expand Up @@ -186,7 +186,7 @@ function whenPressedAndReleased(direction, pressedHandler, releasedHandler) {
}

function clickedOn(sprite, event) {
touchEvents.push({type: mousePressedOver, event: event, param: sprite});
touchEvents.push({type: mousePressedOver, event: event, sprite: sprite});
}

function spriteDestroyed(sprite, event) {
Expand Down Expand Up @@ -353,17 +353,22 @@ function draw() {
for (let i = 0; i < touchEvents.length; i++) {
const eventType = touchEvents[i].type;
const event = touchEvents[i].event;
const param = touchEvents[i].param;
if (eventType(param)) {
const param = touchEvents[i].sprite ?
touchEvents[i].sprite() :
touchEvents[i].param;
if (param && eventType(param)) {
event();
}
}

// Run collision events
for (let i = 0; i<collisionEvents.length; i++) {
const collisionEvent = collisionEvents[i];
const a = collisionEvent.a;
const b = collisionEvent.b;
const a = collisionEvent.a && collisionEvent.a();
const b = collisionEvent.b && collisionEvent.b();
if (!a || !b) {
continue;
}
if (a.overlap(b)) {
if (!collisionEvent.touching || collisionEvent.keepFiring) {
collisionEvent.event();
Expand Down
41 changes: 39 additions & 2 deletions apps/test/unit/blockUtilsTest.js
@@ -1,3 +1,4 @@
import dedent from 'dedent';
import {
appendBlocksByCategory,
cleanBlocks,
Expand Down Expand Up @@ -497,7 +498,7 @@ describe('block utils', () => {
);
generator = Blockly.Generator.get('JavaScript');
});
it ('generates code for a single assignment', () => {
it('generates code for a single assignment', () => {
createBlock({
func: 'foo',
blockText: 'set {NAME} to foo()',
Expand All @@ -513,7 +514,7 @@ describe('block utils', () => {
const code = generator['test_foo'].bind(fakeBlock)();
expect(code).to.equal('someVar = foo(someVar);\n');
});
it ('generates code for a double assignment', () => {
it('generates code for a double assignment', () => {
createBlock({
func: 'foo',
blockText: 'set {NAME1} and {NAME2} to foo()',
Expand All @@ -539,6 +540,42 @@ describe('block utils', () => {
const code = generator['test_foo'].bind(fakeBlock)();
expect(code).to.equal('a = b = foo(a, b);\n');
});
it('generates code for a deferred input', () => {
createBlock({
func: 'yellAt',
blockText: '{NAME1} yells at {NAME2}',
args: [
{
name: 'NAME1',
defer: true,
},
{
name: 'NAME2',
defer: true,
},
],
});

const valueToCodeStub = sinon.stub(Blockly.JavaScript, 'valueToCode')
.callsFake((block, name) => {
return {
NAME1: 'elrond',
NAME2: 'isildur',
}[name];
});
const code = generator['test_yellAt']();


expect(code.trim()).to.equal(dedent`
yellAt(function () {
return elrond;
}, function () {
return isildur;
});
`);

valueToCodeStub.restore();
});
});
});
});
2 changes: 1 addition & 1 deletion apps/test/unit/gamelab/GameLabJrTest.js
Expand Up @@ -164,7 +164,7 @@ describe('Game Lab Jr Helper Library', () => {
addBehavior(sprite, () => eventLog.push('behavior 2 ran'));
whenUpArrow(() => eventLog.push('key event ran'));
whenMouseClicked(() => eventLog.push('touch event ran'));
whenTouching(sprite, otherSprite, () => eventLog.push('collision event ran'));
whenTouching(() => sprite, () => otherSprite, () => eventLog.push('collision event ran'));

draw();

Expand Down
4 changes: 4 additions & 0 deletions apps/yarn.lock
Expand Up @@ -3793,6 +3793,10 @@ decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"

dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"

deep-diff@0.3.4:
version "0.3.4"
resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.4.tgz#aac5c39952236abe5f037a2349060ba01b00ae48"
Expand Down
2 changes: 1 addition & 1 deletion dashboard/app/views/blocks/edit.html.haml
Expand Up @@ -36,6 +36,6 @@
%h3 Block Preview
#blockly-container
%h3 Generated Code
%code#code-preview
%pre#code-preview

= link_to "Back", blocks_path
3 changes: 2 additions & 1 deletion dashboard/config/blocks/GamelabJr/gamelab_clickedOn.json
Expand Up @@ -11,7 +11,8 @@
"args": [
{
"name": "SPRITE",
"type": "Sprite"
"type": "Sprite",
"defer": true
}
],
"eventBlock": true
Expand Down
Expand Up @@ -13,11 +13,13 @@
"args": [
{
"name": "SPRITE1",
"type": "Sprite"
"type": "Sprite",
"defer": true
},
{
"name": "SPRITE2",
"type": "Sprite"
"type": "Sprite",
"defer": true
},
{
"name": "STATEMENT1",
Expand Down
6 changes: 4 additions & 2 deletions dashboard/config/blocks/GamelabJr/gamelab_whenTouching.json
Expand Up @@ -11,11 +11,13 @@
"args": [
{
"name": "SPRITE1",
"type": "Sprite"
"type": "Sprite",
"defer": true
},
{
"name": "SPRITE2",
"type": "Sprite"
"type": "Sprite",
"defer": true
}
],
"eventBlock": true
Expand Down
6 changes: 4 additions & 2 deletions dashboard/config/blocks/GamelabJr/gamelab_whileTouching.json
Expand Up @@ -11,11 +11,13 @@
"args": [
{
"name": "SPRITE1",
"type": "Sprite"
"type": "Sprite",
"defer": true
},
{
"name": "SPRITE2",
"type": "Sprite"
"type": "Sprite",
"defer": true
}
],
"eventLoopBlock": true
Expand Down

0 comments on commit eeb51da

Please sign in to comment.