@scratch/scratch-vm 11.1.0-spork.9 → 11.2.0-cla.1

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.
@@ -45,10 +45,7 @@ class Blocks {
45
45
  * @type {{inputs: {}, procedureParamNames: {}, procedureDefinitions: {}}}
46
46
  * @private
47
47
  */
48
- Object.defineProperty(this, '_cache', {
49
- writable: true,
50
- enumerable: false
51
- });
48
+ Object.defineProperty(this, '_cache', {writable: true, enumerable: false});
52
49
  this._cache = {
53
50
  /**
54
51
  * Cache block inputs by block id
@@ -126,13 +123,13 @@ class Blocks {
126
123
  }
127
124
 
128
125
  /**
129
- * Get the next block for a particular block
130
- * @param {?string} id ID of block to get the next block for
131
- * @return {?string} ID of next block in the sequence
132
- */
126
+ * Get the next block for a particular block
127
+ * @param {?string} id ID of block to get the next block for
128
+ * @return {?string} ID of next block in the sequence
129
+ */
133
130
  getNextBlock (id) {
134
131
  const block = this._blocks[id];
135
- return typeof block === 'undefined' ? null : block.next;
132
+ return (typeof block === 'undefined') ? null : block.next;
136
133
  }
137
134
 
138
135
  /**
@@ -153,7 +150,7 @@ class Blocks {
153
150
 
154
151
  // Empty C-block?
155
152
  const input = block.inputs[inputName];
156
- return typeof input === 'undefined' ? null : input.block;
153
+ return (typeof input === 'undefined') ? null : input.block;
157
154
  }
158
155
 
159
156
  /**
@@ -162,7 +159,7 @@ class Blocks {
162
159
  * @return {?string} the opcode corresponding to that block
163
160
  */
164
161
  getOpcode (block) {
165
- return typeof block === 'undefined' ? null : block.opcode;
162
+ return (typeof block === 'undefined') ? null : block.opcode;
166
163
  }
167
164
 
168
165
  /**
@@ -171,7 +168,7 @@ class Blocks {
171
168
  * @return {?object} All fields and their values.
172
169
  */
173
170
  getFields (block) {
174
- return typeof block === 'undefined' ? null : block.fields;
171
+ return (typeof block === 'undefined') ? null : block.fields;
175
172
  }
176
173
 
177
174
  /**
@@ -189,10 +186,8 @@ class Blocks {
189
186
  inputs = {};
190
187
  for (const input in block.inputs) {
191
188
  // Ignore blocks prefixed with branch prefix.
192
- if (
193
- input.substring(0, Blocks.BRANCH_INPUT_PREFIX.length) !==
194
- Blocks.BRANCH_INPUT_PREFIX
195
- ) {
189
+ if (input.substring(0, Blocks.BRANCH_INPUT_PREFIX.length) !==
190
+ Blocks.BRANCH_INPUT_PREFIX) {
196
191
  inputs[input] = block.inputs[input];
197
192
  }
198
193
  }
@@ -207,7 +202,7 @@ class Blocks {
207
202
  * @return {?object} Mutation for the block.
208
203
  */
209
204
  getMutation (block) {
210
- return typeof block === 'undefined' ? null : block.mutation;
205
+ return (typeof block === 'undefined') ? null : block.mutation;
211
206
  }
212
207
 
213
208
  /**
@@ -236,9 +231,7 @@ class Blocks {
236
231
  }
237
232
 
238
233
  for (const id in this._blocks) {
239
- if (!Object.prototype.hasOwnProperty.call(this._blocks, id)) {
240
- continue;
241
- }
234
+ if (!Object.prototype.hasOwnProperty.call(this._blocks, id)) continue;
242
235
  const block = this._blocks[id];
243
236
  if (block.opcode === 'procedures_definition') {
244
237
  const internal = this._getCustomBlockInternal(block);
@@ -274,14 +267,10 @@ class Blocks {
274
267
  }
275
268
 
276
269
  for (const id in this._blocks) {
277
- if (!Object.prototype.hasOwnProperty.call(this._blocks, id)) {
278
- continue;
279
- }
270
+ if (!Object.prototype.hasOwnProperty.call(this._blocks, id)) continue;
280
271
  const block = this._blocks[id];
281
- if (
282
- block.opcode === 'procedures_prototype' &&
283
- block.mutation.proccode === name
284
- ) {
272
+ if (block.opcode === 'procedures_prototype' &&
273
+ block.mutation.proccode === name) {
285
274
  const names = JSON.parse(block.mutation.argumentnames);
286
275
  const ids = JSON.parse(block.mutation.argumentids);
287
276
  const defaults = JSON.parse(block.mutation.argumentdefaults);
@@ -312,16 +301,19 @@ class Blocks {
312
301
  blocklyListen (e) {
313
302
  // Validate event
314
303
  if (typeof e !== 'object') return;
315
- if (
316
- typeof e.blockId !== 'string' &&
317
- typeof e.varId !== 'string' &&
318
- typeof e.commentId !== 'string'
319
- ) {
304
+ if (typeof e.blockId !== 'string' && typeof e.varId !== 'string' &&
305
+ typeof e.commentId !== 'string') {
320
306
  return;
321
307
  }
322
308
  const stage = this.runtime.getTargetForStage();
323
309
  const editingTarget = this.runtime.getEditingTarget();
324
310
 
311
+ // UI event: clicked scripts toggle in the runtime.
312
+ if (e.element === 'stackclick') {
313
+ this.runtime.toggleScript(e.blockId, {stackClick: true});
314
+ return;
315
+ }
316
+
325
317
  // Block create/update/destroy
326
318
  switch (e.type) {
327
319
  case 'create': {
@@ -365,13 +357,8 @@ class Blocks {
365
357
  case 'delete':
366
358
  // Don't accept delete events for missing blocks,
367
359
  // or shadow blocks being obscured.
368
- if (
369
- !Object.prototype.hasOwnProperty.call(
370
- this._blocks,
371
- e.blockId
372
- ) ||
373
- this._blocks[e.blockId].shadow
374
- ) {
360
+ if (!Object.prototype.hasOwnProperty.call(this._blocks, e.blockId) ||
361
+ this._blocks[e.blockId].shadow) {
375
362
  return;
376
363
  }
377
364
  // Inform any runtime to forget about glows on this script.
@@ -388,18 +375,9 @@ class Blocks {
388
375
  // into a state where a local var was requested for the stage,
389
376
  // create a stage (global) var after checking for name conflicts
390
377
  // on all the sprites.
391
- if (
392
- e.isLocal &&
393
- editingTarget &&
394
- !editingTarget.isStage &&
395
- !e.isCloud
396
- ) {
378
+ if (e.isLocal && editingTarget && !editingTarget.isStage && !e.isCloud) {
397
379
  if (!editingTarget.lookupVariableById(e.varId)) {
398
- editingTarget.createVariable(
399
- e.varId,
400
- e.varName,
401
- e.varType
402
- );
380
+ editingTarget.createVariable(e.varId, e.varName, e.varType);
403
381
  this.emitProjectChanged();
404
382
  }
405
383
  } else {
@@ -408,45 +386,23 @@ class Blocks {
408
386
  return;
409
387
  }
410
388
  // Check for name conflicts in all of the targets
411
- const allTargets = this.runtime.targets.filter(
412
- t => t.isOriginal
413
- );
389
+ const allTargets = this.runtime.targets.filter(t => t.isOriginal);
414
390
  for (const target of allTargets) {
415
- if (
416
- target.lookupVariableByNameAndType(
417
- e.varName,
418
- e.varType,
419
- true
420
- )
421
- ) {
391
+ if (target.lookupVariableByNameAndType(e.varName, e.varType, true)) {
422
392
  return;
423
393
  }
424
394
  }
425
- stage.createVariable(
426
- e.varId,
427
- e.varName,
428
- e.varType,
429
- e.isCloud
430
- );
395
+ stage.createVariable(e.varId, e.varName, e.varType, e.isCloud);
431
396
  this.emitProjectChanged();
432
397
  }
433
398
  break;
434
399
  case 'var_rename':
435
- if (
436
- editingTarget &&
437
- Object.prototype.hasOwnProperty.call(
438
- editingTarget.variables,
439
- e.varId
440
- )
441
- ) {
400
+ if (editingTarget && Object.prototype.hasOwnProperty.call(editingTarget.variables, e.varId)) {
442
401
  // This is a local variable, rename on the current target
443
402
  editingTarget.renameVariable(e.varId, e.newName);
444
403
  // Update all the blocks on the current target that use
445
404
  // this variable
446
- editingTarget.blocks.updateBlocksAfterVarRename(
447
- e.varId,
448
- e.newName
449
- );
405
+ editingTarget.blocks.updateBlocksAfterVarRename(e.varId, e.newName);
450
406
  } else {
451
407
  // This is a global variable
452
408
  stage.renameVariable(e.varId, e.newName);
@@ -454,92 +410,66 @@ class Blocks {
454
410
  const targets = this.runtime.targets;
455
411
  for (let i = 0; i < targets.length; i++) {
456
412
  const currTarget = targets[i];
457
- currTarget.blocks.updateBlocksAfterVarRename(
458
- e.varId,
459
- e.newName
460
- );
413
+ currTarget.blocks.updateBlocksAfterVarRename(e.varId, e.newName);
461
414
  }
462
415
  }
463
416
  this.emitProjectChanged();
464
417
  break;
465
418
  case 'var_delete': {
466
- const target =
467
- editingTarget &&
468
- Object.prototype.hasOwnProperty.call(
469
- editingTarget.variables,
470
- e.varId
471
- ) ?
472
- editingTarget :
473
- stage;
419
+ const target = (editingTarget && Object.prototype.hasOwnProperty.call(editingTarget.variables, e.varId)) ?
420
+ editingTarget : stage;
474
421
  target.deleteVariable(e.varId);
475
422
  this.emitProjectChanged();
476
423
  break;
477
424
  }
478
- case 'block_comment_create':
479
425
  case 'comment_create':
480
426
  if (this.runtime.getEditingTarget()) {
481
427
  const currTarget = this.runtime.getEditingTarget();
482
- currTarget.createComment(
483
- e.commentId,
484
- e.blockId,
485
- '',
486
- e.json.x,
487
- e.json.y,
488
- e.json.width,
489
- e.json.height,
490
- false
491
- );
492
-
493
- if (
494
- currTarget.comments[e.commentId].x === null &&
495
- currTarget.comments[e.commentId].y === null
496
- ) {
428
+ currTarget.createComment(e.commentId, e.blockId, e.text,
429
+ e.xy.x, e.xy.y, e.width, e.height, e.minimized);
430
+
431
+ if (currTarget.comments[e.commentId].x === null &&
432
+ currTarget.comments[e.commentId].y === null) {
497
433
  // Block comments imported from 2.0 projects are imported with their
498
434
  // x and y coordinates set to null so that scratch-blocks can
499
435
  // auto-position them. If we are receiving a create event for these
500
436
  // comments, then the auto positioning should have taken place.
501
437
  // Update the x and y position of these comments to match the
502
438
  // one from the event.
503
- currTarget.comments[e.commentId].x = e.json.x;
504
- currTarget.comments[e.commentId].y = e.json.y;
439
+ currTarget.comments[e.commentId].x = e.xy.x;
440
+ currTarget.comments[e.commentId].y = e.xy.y;
505
441
  }
506
442
  }
507
443
  this.emitProjectChanged();
508
444
  break;
509
- case 'block_comment_change':
510
445
  case 'comment_change':
511
446
  if (this.runtime.getEditingTarget()) {
512
447
  const currTarget = this.runtime.getEditingTarget();
513
- if (
514
- !Object.prototype.hasOwnProperty.call(
515
- currTarget.comments,
516
- e.commentId
517
- )
518
- ) {
519
- log.warn(
520
- `Cannot change comment with id ${e.commentId} because it does not exist.`
521
- );
448
+ if (!Object.prototype.hasOwnProperty.call(currTarget.comments, e.commentId)) {
449
+ log.warn(`Cannot change comment with id ${e.commentId} because it does not exist.`);
522
450
  return;
523
451
  }
524
452
  const comment = currTarget.comments[e.commentId];
525
- comment.text = e.newContents_;
453
+ const change = e.newContents_;
454
+ if (Object.prototype.hasOwnProperty.call(change, 'minimized')) {
455
+ comment.minimized = change.minimized;
456
+ }
457
+ if (Object.prototype.hasOwnProperty.call(change, 'width') &&
458
+ Object.prototype.hasOwnProperty.call(change, 'height')) {
459
+ comment.width = change.width;
460
+ comment.height = change.height;
461
+ }
462
+ if (Object.prototype.hasOwnProperty.call(change, 'text')) {
463
+ comment.text = change.text;
464
+ }
526
465
  this.emitProjectChanged();
527
466
  }
528
467
  break;
529
- case 'block_comment_move':
530
468
  case 'comment_move':
531
469
  if (this.runtime.getEditingTarget()) {
532
470
  const currTarget = this.runtime.getEditingTarget();
533
- if (
534
- currTarget &&
535
- !Object.prototype.hasOwnProperty.call(
536
- currTarget.comments,
537
- e.commentId
538
- )
539
- ) {
540
- log.warn(
541
- `Cannot move comment with id ${e.commentId} because it does not exist.`
542
- );
471
+ if (currTarget && !Object.prototype.hasOwnProperty.call(currTarget.comments, e.commentId)) {
472
+ log.warn(`Cannot change comment with id ${e.commentId} because it does not exist.`);
543
473
  return;
544
474
  }
545
475
  const comment = currTarget.comments[e.commentId];
@@ -550,59 +480,10 @@ class Blocks {
550
480
  this.emitProjectChanged();
551
481
  }
552
482
  break;
553
- case 'block_comment_collapse':
554
- case 'comment_collapse':
555
- if (this.runtime.getEditingTarget()) {
556
- const currTarget = this.runtime.getEditingTarget();
557
- if (
558
- currTarget &&
559
- !Object.prototype.hasOwnProperty.call(
560
- currTarget.comments,
561
- e.commentId
562
- )
563
- ) {
564
- log.warn(
565
- `Cannot collapse comment with id ${e.commentId} because it does not exist.`
566
- );
567
- return;
568
- }
569
- const comment = currTarget.comments[e.commentId];
570
- comment.minimized = e.newCollapsed;
571
- this.emitProjectChanged();
572
- }
573
- break;
574
- case 'block_comment_resize':
575
- case 'comment_resize':
576
- if (this.runtime.getEditingTarget()) {
577
- const currTarget = this.runtime.getEditingTarget();
578
- if (
579
- currTarget &&
580
- !Object.prototype.hasOwnProperty.call(
581
- currTarget.comments,
582
- e.commentId
583
- )
584
- ) {
585
- log.warn(
586
- `Cannot resize comment with id ${e.commentId} because it does not exist.`
587
- );
588
- return;
589
- }
590
- const comment = currTarget.comments[e.commentId];
591
- comment.width = e.newSize.width;
592
- comment.height = e.newSize.height;
593
- this.emitProjectChanged();
594
- }
595
- break;
596
- case 'block_comment_delete':
597
483
  case 'comment_delete':
598
484
  if (this.runtime.getEditingTarget()) {
599
485
  const currTarget = this.runtime.getEditingTarget();
600
- if (
601
- !Object.prototype.hasOwnProperty.call(
602
- currTarget.comments,
603
- e.commentId
604
- )
605
- ) {
486
+ if (!Object.prototype.hasOwnProperty.call(currTarget.comments, e.commentId)) {
606
487
  // If we're in this state, we have probably received
607
488
  // a delete event from a workspace that we switched from
608
489
  // (e.g. a delete event for a comment on sprite a's workspace
@@ -613,9 +494,7 @@ class Blocks {
613
494
  if (e.blockId) {
614
495
  const block = currTarget.blocks.getBlock(e.blockId);
615
496
  if (!block) {
616
- log.warn(
617
- `Could not find block referenced by comment with id: ${e.commentId}`
618
- );
497
+ log.warn(`Could not find block referenced by comment with id: ${e.commentId}`);
619
498
  return;
620
499
  }
621
500
  delete block.comment;
@@ -624,15 +503,6 @@ class Blocks {
624
503
  this.emitProjectChanged();
625
504
  }
626
505
  break;
627
- case 'click':
628
- // UI event: clicked scripts toggle in the runtime.
629
- if (e.targetType === 'block') {
630
- this.runtime.toggleScript(
631
- this.getTopLevelScript(e.blockId),
632
- {stackClick: true}
633
- );
634
- }
635
- break;
636
506
  }
637
507
  }
638
508
 
@@ -692,9 +562,7 @@ class Blocks {
692
562
  */
693
563
  changeBlock (args) {
694
564
  // Validate
695
- if (['field', 'mutation', 'checkbox'].indexOf(args.element) === -1) {
696
- return;
697
- }
565
+ if (['field', 'mutation', 'checkbox'].indexOf(args.element) === -1) return;
698
566
  let block = this._blocks[args.id];
699
567
  if (typeof block === 'undefined') return;
700
568
  switch (args.element) {
@@ -708,17 +576,13 @@ class Blocks {
708
576
  // 3. the checkbox should become unchecked if we're not already
709
577
  // monitoring current minute
710
578
 
579
+
711
580
  // Update block value
712
581
  if (!block.fields[args.name]) return;
713
- if (
714
- args.name === 'VARIABLE' ||
715
- args.name === 'LIST' ||
716
- args.name === 'BROADCAST_OPTION'
717
- ) {
582
+ if (args.name === 'VARIABLE' || args.name === 'LIST' ||
583
+ args.name === 'BROADCAST_OPTION') {
718
584
  // Get variable name using the id in args.value.
719
- const variable = this.runtime
720
- .getEditingTarget()
721
- .lookupVariableById(args.value);
585
+ const variable = this.runtime.getEditingTarget().lookupVariableById(args.value);
722
586
  if (variable) {
723
587
  block.fields[args.name].value = variable.name;
724
588
  block.fields[args.name].id = args.value;
@@ -732,26 +596,19 @@ class Blocks {
732
596
  // TODO: (#1787)
733
597
  if (block.opcode === 'sensing_of_object_menu') {
734
598
  if (block.fields.OBJECT.value === '_stage_') {
735
- this._blocks[block.parent].fields.PROPERTY.value =
736
- 'backdrop #';
599
+ this._blocks[block.parent].fields.PROPERTY.value = 'backdrop #';
737
600
  } else {
738
- this._blocks[block.parent].fields.PROPERTY.value =
739
- 'x position';
601
+ this._blocks[block.parent].fields.PROPERTY.value = 'x position';
740
602
  }
741
603
  this.runtime.requestBlocksUpdate();
742
604
  }
743
605
 
744
- const flyoutBlock =
745
- block.shadow && block.parent ?
746
- this._blocks[block.parent] :
747
- block;
606
+ const flyoutBlock = block.shadow && block.parent ? this._blocks[block.parent] : block;
748
607
  if (flyoutBlock.isMonitored) {
749
- this.runtime.requestUpdateMonitor(
750
- Map({
751
- id: flyoutBlock.id,
752
- params: this._getBlockParams(flyoutBlock)
753
- })
754
- );
608
+ this.runtime.requestUpdateMonitor(Map({
609
+ id: flyoutBlock.id,
610
+ params: this._getBlockParams(flyoutBlock)
611
+ }));
755
612
  }
756
613
  }
757
614
  break;
@@ -762,20 +619,14 @@ class Blocks {
762
619
  // A checkbox usually has a one to one correspondence with the monitor
763
620
  // block but in the case of monitored reporters that have arguments,
764
621
  // map the old id to a new id, creating a new monitor block if necessary
765
- if (
766
- block.fields &&
767
- Object.keys(block.fields).length > 0 &&
768
- block.opcode !== 'data_variable' &&
769
- block.opcode !== 'data_listcontents'
770
- ) {
622
+ if (block.fields && Object.keys(block.fields).length > 0 &&
623
+ block.opcode !== 'data_variable' && block.opcode !== 'data_listcontents') {
624
+
771
625
  // This block has an argument which needs to get separated out into
772
626
  // multiple monitor blocks with ids based on the selected argument
627
+ const newId = getMonitorIdForBlockWithArgs(block.id, block.fields);
773
628
  // Note: we're not just constantly creating a longer and longer id everytime we check
774
629
  // the checkbox because we're using the id of the block in the flyout as the base
775
- const newId = getMonitorIdForBlockWithArgs(
776
- block.id,
777
- block.fields
778
- );
779
630
 
780
631
  // check if a block with the new id already exists, otherwise create
781
632
  let newBlock = this.runtime.monitorBlocks.getBlock(newId);
@@ -794,31 +645,19 @@ class Blocks {
794
645
  // Variable blocks may be sprite specific depending on the owner of the variable
795
646
  let isSpriteLocalVariable = false;
796
647
  if (block.opcode === 'data_variable') {
797
- isSpriteLocalVariable =
798
- !this.runtime.getTargetForStage().variables[
799
- block.fields.VARIABLE.id
800
- ];
648
+ isSpriteLocalVariable = !(this.runtime.getTargetForStage().variables[block.fields.VARIABLE.id]);
801
649
  } else if (block.opcode === 'data_listcontents') {
802
- isSpriteLocalVariable =
803
- !this.runtime.getTargetForStage().variables[
804
- block.fields.LIST.id
805
- ];
650
+ isSpriteLocalVariable = !(this.runtime.getTargetForStage().variables[block.fields.LIST.id]);
806
651
  }
807
652
 
808
- const isSpriteSpecific =
809
- isSpriteLocalVariable ||
810
- (Object.prototype.hasOwnProperty.call(
811
- this.runtime.monitorBlockInfo,
812
- block.opcode
813
- ) &&
814
- this.runtime.monitorBlockInfo[block.opcode]
815
- .isSpriteSpecific);
653
+ const isSpriteSpecific = isSpriteLocalVariable ||
654
+ (Object.prototype.hasOwnProperty.call(this.runtime.monitorBlockInfo, block.opcode) &&
655
+ this.runtime.monitorBlockInfo[block.opcode].isSpriteSpecific);
816
656
  if (isSpriteSpecific) {
817
657
  // If creating a new sprite specific monitor, the only possible target is
818
658
  // the current editing one b/c you cannot dynamically create monitors.
819
659
  // Also, do not change the targetId if it has already been assigned
820
- block.targetId =
821
- block.targetId || this.runtime.getEditingTarget().id;
660
+ block.targetId = block.targetId || this.runtime.getEditingTarget().id;
822
661
  } else {
823
662
  block.targetId = null;
824
663
  }
@@ -828,25 +667,16 @@ class Blocks {
828
667
  } else if (!wasMonitored && block.isMonitored) {
829
668
  // Tries to show the monitor for specified block. If it doesn't exist, add the monitor.
830
669
  if (!this.runtime.requestShowMonitor(block.id)) {
831
- this.runtime.requestAddMonitor(
832
- MonitorRecord({
833
- id: block.id,
834
- targetId: block.targetId,
835
- spriteName: block.targetId ?
836
- this.runtime
837
- .getTargetById(block.targetId)
838
- .getName() :
839
- null,
840
- opcode: block.opcode,
841
- params: this._getBlockParams(block),
842
- // @todo(vm#565) for numerical values with decimals, some countries use comma
843
- value: '',
844
- mode:
845
- block.opcode === 'data_listcontents' ?
846
- 'list' :
847
- 'default'
848
- })
849
- );
670
+ this.runtime.requestAddMonitor(MonitorRecord({
671
+ id: block.id,
672
+ targetId: block.targetId,
673
+ spriteName: block.targetId ? this.runtime.getTargetById(block.targetId).getName() : null,
674
+ opcode: block.opcode,
675
+ params: this._getBlockParams(block),
676
+ // @todo(vm#565) for numerical values with decimals, some countries use comma
677
+ value: '',
678
+ mode: block.opcode === 'data_listcontents' ? 'list' : 'default'
679
+ }));
850
680
  }
851
681
  }
852
682
  break;
@@ -875,8 +705,8 @@ class Blocks {
875
705
 
876
706
  // Move coordinate changes.
877
707
  if (e.newCoordinate) {
878
- didChange =
879
- block.x !== e.newCoordinate.x || block.y !== e.newCoordinate.y;
708
+
709
+ didChange = (block.x !== e.newCoordinate.x) || (block.y !== e.newCoordinate.y);
880
710
 
881
711
  block.x = e.newCoordinate.x;
882
712
  block.y = e.newCoordinate.y;
@@ -885,36 +715,21 @@ class Blocks {
885
715
  // Remove from any old parent.
886
716
  if (typeof e.oldParent !== 'undefined') {
887
717
  const oldParent = this._blocks[e.oldParent];
888
- if (
889
- typeof e.oldInput !== 'undefined' &&
890
- oldParent.inputs[e.oldInput].block === e.id
891
- ) {
892
- // This block was connected to an input. We either want to
893
- // restore the shadow block that previously occupied
894
- // this input, or null out the input's block.
895
- const shadow = oldParent.inputs[e.oldInput].shadow;
896
- if (shadow && e.id !== shadow) {
897
- oldParent.inputs[e.oldInput].block = shadow;
898
- this._blocks[shadow].parent = oldParent.id;
899
- } else {
900
- oldParent.inputs[e.oldInput].block = null;
901
- if (e.id !== shadow) {
902
- this._blocks[e.id].parent = null;
903
- }
904
- }
718
+ if (typeof e.oldInput !== 'undefined' &&
719
+ oldParent.inputs[e.oldInput].block === e.id) {
720
+ // This block was connected to the old parent's input.
721
+ oldParent.inputs[e.oldInput].block = null;
905
722
  } else if (oldParent.next === e.id) {
906
723
  // This block was connected to the old parent's next connection.
907
724
  oldParent.next = null;
908
- this._blocks[e.id].parent = null;
909
725
  }
726
+ this._blocks[e.id].parent = null;
910
727
  didChange = true;
911
728
  }
912
729
 
913
730
  // Is this block a top-level block?
914
731
  if (typeof e.newParent === 'undefined') {
915
- if (!this._blocks[e.id].shadow) {
916
- this._addScript(e.id);
917
- }
732
+ this._addScript(e.id);
918
733
  } else {
919
734
  // Remove script, if one exists.
920
735
  this._deleteScript(e.id);
@@ -926,14 +741,8 @@ class Blocks {
926
741
  // Moved to the new parent's input.
927
742
  // Don't obscure the shadow block.
928
743
  let oldShadow = null;
929
- if (
930
- Object.prototype.hasOwnProperty.call(
931
- this._blocks[e.newParent].inputs,
932
- e.newInput
933
- )
934
- ) {
935
- oldShadow =
936
- this._blocks[e.newParent].inputs[e.newInput].shadow;
744
+ if (Object.prototype.hasOwnProperty.call(this._blocks[e.newParent].inputs, e.newInput)) {
745
+ oldShadow = this._blocks[e.newParent].inputs[e.newInput].shadow;
937
746
  }
938
747
 
939
748
  // If the block being attached is itself a shadow, make sure to set
@@ -955,6 +764,7 @@ class Blocks {
955
764
  if (didChange) this.emitProjectChanged();
956
765
  }
957
766
 
767
+
958
768
  /**
959
769
  * Block management: run all blocks.
960
770
  * @param {!object} runtime Runtime to run all blocks in.
@@ -967,9 +777,7 @@ class Blocks {
967
777
  const targetId = this.getBlock(blockId).targetId;
968
778
  return {
969
779
  blockId,
970
- target: targetId ?
971
- runtime.getTargetById(targetId) :
972
- null
780
+ target: targetId ? runtime.getTargetById(targetId) : null
973
781
  };
974
782
  });
975
783
  }
@@ -1008,10 +816,8 @@ class Blocks {
1008
816
  this.deleteBlock(block.inputs[input].block);
1009
817
  }
1010
818
  // Delete obscured shadow blocks.
1011
- if (
1012
- block.inputs[input].shadow !== null &&
1013
- block.inputs[input].shadow !== block.inputs[input].block
1014
- ) {
819
+ if (block.inputs[input].shadow !== null &&
820
+ block.inputs[input].shadow !== block.inputs[input].block) {
1015
821
  this.deleteBlock(block.inputs[input].shadow);
1016
822
  }
1017
823
  }
@@ -1057,10 +863,7 @@ class Blocks {
1057
863
  } else if (blocks[blockId].fields.LIST) {
1058
864
  varOrListField = blocks[blockId].fields.LIST;
1059
865
  varType = Variable.LIST_TYPE;
1060
- } else if (
1061
- optIncludeBroadcast &&
1062
- blocks[blockId].fields.BROADCAST_OPTION
1063
- ) {
866
+ } else if (optIncludeBroadcast && blocks[blockId].fields.BROADCAST_OPTION) {
1064
867
  varOrListField = blocks[blockId].fields.BROADCAST_OPTION;
1065
868
  varType = Variable.BROADCAST_MESSAGE_TYPE;
1066
869
  }
@@ -1072,12 +875,10 @@ class Blocks {
1072
875
  type: varType
1073
876
  });
1074
877
  } else {
1075
- allReferences[currVarId] = [
1076
- {
1077
- referencingField: varOrListField,
1078
- type: varType
1079
- }
1080
- ];
878
+ allReferences[currVarId] = [{
879
+ referencingField: varOrListField,
880
+ type: varType
881
+ }];
1081
882
  }
1082
883
  }
1083
884
  }
@@ -1114,15 +915,9 @@ class Blocks {
1114
915
  updateTargetSpecificBlocks (isStage) {
1115
916
  const blocks = this._blocks;
1116
917
  for (const blockId in blocks) {
1117
- if (
1118
- isStage &&
1119
- blocks[blockId].opcode === 'event_whenthisspriteclicked'
1120
- ) {
918
+ if (isStage && blocks[blockId].opcode === 'event_whenthisspriteclicked') {
1121
919
  blocks[blockId].opcode = 'event_whenstageclicked';
1122
- } else if (
1123
- !isStage &&
1124
- blocks[blockId].opcode === 'event_whenstageclicked'
1125
- ) {
920
+ } else if (!isStage && blocks[blockId].opcode === 'event_whenstageclicked') {
1126
921
  blocks[blockId].opcode = 'event_whenthisspriteclicked';
1127
922
  }
1128
923
  }
@@ -1172,12 +967,10 @@ class Blocks {
1172
967
  let blockUpdated = false;
1173
968
  for (const blockId in blocks) {
1174
969
  const block = blocks[blockId];
1175
- if (
1176
- block.opcode === 'sensing_of' &&
970
+ if (block.opcode === 'sensing_of' &&
1177
971
  block.fields.PROPERTY.value === oldName &&
1178
972
  // If block and shadow are different, it means a block is inserted to OBJECT, and should be ignored.
1179
- block.inputs.OBJECT.block === block.inputs.OBJECT.shadow
1180
- ) {
973
+ block.inputs.OBJECT.block === block.inputs.OBJECT.shadow) {
1181
974
  const inputBlock = this.getBlock(block.inputs.OBJECT.block);
1182
975
  if (inputBlock.fields.OBJECT.value === targetName) {
1183
976
  block.fields.PROPERTY.value = newName;
@@ -1198,10 +991,7 @@ class Blocks {
1198
991
  */
1199
992
  _getCostumeField (blockId) {
1200
993
  const block = this.getBlock(blockId);
1201
- if (
1202
- block &&
1203
- Object.prototype.hasOwnProperty.call(block.fields, 'COSTUME')
1204
- ) {
994
+ if (block && Object.prototype.hasOwnProperty.call(block.fields, 'COSTUME')) {
1205
995
  return block.fields.COSTUME;
1206
996
  }
1207
997
  return null;
@@ -1216,10 +1006,7 @@ class Blocks {
1216
1006
  */
1217
1007
  _getSoundField (blockId) {
1218
1008
  const block = this.getBlock(blockId);
1219
- if (
1220
- block &&
1221
- Object.prototype.hasOwnProperty.call(block.fields, 'SOUND_MENU')
1222
- ) {
1009
+ if (block && Object.prototype.hasOwnProperty.call(block.fields, 'SOUND_MENU')) {
1223
1010
  return block.fields.SOUND_MENU;
1224
1011
  }
1225
1012
  return null;
@@ -1234,10 +1021,7 @@ class Blocks {
1234
1021
  */
1235
1022
  _getBackdropField (blockId) {
1236
1023
  const block = this.getBlock(blockId);
1237
- if (
1238
- block &&
1239
- Object.prototype.hasOwnProperty.call(block.fields, 'BACKDROP')
1240
- ) {
1024
+ if (block && Object.prototype.hasOwnProperty.call(block.fields, 'BACKDROP')) {
1241
1025
  return block.fields.BACKDROP;
1242
1026
  }
1243
1027
  return null;
@@ -1255,15 +1039,8 @@ class Blocks {
1255
1039
  if (!block) {
1256
1040
  return null;
1257
1041
  }
1258
- const spriteMenuNames = [
1259
- 'TOWARDS',
1260
- 'TO',
1261
- 'OBJECT',
1262
- 'VIDEOONMENU2',
1263
- 'DISTANCETOMENU',
1264
- 'TOUCHINGOBJECTMENU',
1265
- 'CLONE_OPTION'
1266
- ];
1042
+ const spriteMenuNames = ['TOWARDS', 'TO', 'OBJECT', 'VIDEOONMENU2',
1043
+ 'DISTANCETOMENU', 'TOUCHINGOBJECTMENU', 'CLONE_OPTION'];
1267
1044
  for (let i = 0; i < spriteMenuNames.length; i++) {
1268
1045
  const menuName = spriteMenuNames[i];
1269
1046
  if (Object.prototype.hasOwnProperty.call(block.fields, menuName)) {
@@ -1282,9 +1059,7 @@ class Blocks {
1282
1059
  * @return {string} String of XML representing this object's blocks.
1283
1060
  */
1284
1061
  toXML (comments) {
1285
- return this._scripts
1286
- .map(script => this.blockToXML(script, comments))
1287
- .join();
1062
+ return this._scripts.map(script => this.blockToXML(script, comments)).join();
1288
1063
  }
1289
1064
 
1290
1065
  /**
@@ -1301,8 +1076,9 @@ class Blocks {
1301
1076
  // this early exit allows the project to load.
1302
1077
  if (!block) return;
1303
1078
  // Encode properties of this block.
1304
- const tagName = block.shadow ? 'shadow' : 'block';
1305
- let xmlString = `<${tagName}
1079
+ const tagName = (block.shadow) ? 'shadow' : 'block';
1080
+ let xmlString =
1081
+ `<${tagName}
1306
1082
  id="${block.id}"
1307
1083
  type="${block.opcode}"
1308
1084
  ${block.topLevel ? `x="${block.x}" y="${block.y}"` : ''}
@@ -1313,14 +1089,10 @@ class Blocks {
1313
1089
  if (Object.prototype.hasOwnProperty.call(comments, commentId)) {
1314
1090
  xmlString += comments[commentId].toXML();
1315
1091
  } else {
1316
- log.warn(
1317
- `Could not find comment with id: ${commentId} in provided comment descriptions.`
1318
- );
1092
+ log.warn(`Could not find comment with id: ${commentId} in provided comment descriptions.`);
1319
1093
  }
1320
1094
  } else {
1321
- log.warn(
1322
- `Cannot serialize comment with id: ${commentId}; no comment descriptions provided.`
1323
- );
1095
+ log.warn(`Cannot serialize comment with id: ${commentId}; no comment descriptions provided.`);
1324
1096
  }
1325
1097
  }
1326
1098
  // Add any mutation. Must come before inputs.
@@ -1329,9 +1101,7 @@ class Blocks {
1329
1101
  }
1330
1102
  // Add any inputs on this block.
1331
1103
  for (const input in block.inputs) {
1332
- if (!Object.prototype.hasOwnProperty.call(block.inputs, input)) {
1333
- continue;
1334
- }
1104
+ if (!Object.prototype.hasOwnProperty.call(block.inputs, input)) continue;
1335
1105
  const blockInput = block.inputs[input];
1336
1106
  // Only encode a value tag if the value input is occupied.
1337
1107
  if (blockInput.block || blockInput.shadow) {
@@ -1339,10 +1109,7 @@ class Blocks {
1339
1109
  if (blockInput.block) {
1340
1110
  xmlString += this.blockToXML(blockInput.block, comments);
1341
1111
  }
1342
- if (
1343
- blockInput.shadow &&
1344
- blockInput.shadow !== blockInput.block
1345
- ) {
1112
+ if (blockInput.shadow && blockInput.shadow !== blockInput.block) {
1346
1113
  // Obscured shadow.
1347
1114
  xmlString += this.blockToXML(blockInput.shadow, comments);
1348
1115
  }
@@ -1351,9 +1118,7 @@ class Blocks {
1351
1118
  }
1352
1119
  // Add any fields on this block.
1353
1120
  for (const field in block.fields) {
1354
- if (!Object.prototype.hasOwnProperty.call(block.fields, field)) {
1355
- continue;
1356
- }
1121
+ if (!Object.prototype.hasOwnProperty.call(block.fields, field)) continue;
1357
1122
  const blockField = block.fields[field];
1358
1123
  xmlString += `<field name="${blockField.name}"`;
1359
1124
  const fieldId = blockField.id;
@@ -1372,10 +1137,7 @@ class Blocks {
1372
1137
  }
1373
1138
  // Add blocks connected to the next connection.
1374
1139
  if (block.next) {
1375
- xmlString += `<next>${this.blockToXML(
1376
- block.next,
1377
- comments
1378
- )}</next>`;
1140
+ xmlString += `<next>${this.blockToXML(block.next, comments)}</next>`;
1379
1141
  }
1380
1142
  xmlString += `</${tagName}>`;
1381
1143
  return xmlString;
@@ -1390,10 +1152,8 @@ class Blocks {
1390
1152
  let mutationString = `<${mutation.tagName}`;
1391
1153
  for (const prop in mutation) {
1392
1154
  if (prop === 'children' || prop === 'tagName') continue;
1393
- let mutationValue =
1394
- typeof mutation[prop] === 'string' ?
1395
- xmlEscape(mutation[prop]) :
1396
- mutation[prop];
1155
+ let mutationValue = (typeof mutation[prop] === 'string') ?
1156
+ xmlEscape(mutation[prop]) : mutation[prop];
1397
1157
 
1398
1158
  // Handle dynamic extension blocks
1399
1159
  if (prop === 'blockInfo') {