@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.
- package/dist/node/extension-worker.js +1 -1
- package/dist/node/scratch-vm.js +1 -1
- package/dist/node/scratch-vm.js.LICENSE.txt +337 -0
- package/dist/web/scratch-vm.js +1 -1
- package/dist/web/scratch-vm.js.LICENSE.txt +3 -1
- package/package.json +15 -15
- package/src/engine/blocks.js +133 -373
- package/src/engine/comment.js +1 -1
- package/src/engine/runtime.js +188 -405
package/src/engine/blocks.js
CHANGED
|
@@ -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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
e.
|
|
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.
|
|
504
|
-
currTarget.comments[e.commentId].y = e.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 === '
|
|
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
|
-
|
|
751
|
-
|
|
752
|
-
|
|
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.
|
|
767
|
-
|
|
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
|
-
|
|
810
|
-
|
|
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
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
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
|
-
|
|
879
|
-
|
|
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
|
-
|
|
890
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 !==
|
|
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
|
-
|
|
1078
|
-
|
|
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
|
-
'
|
|
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 =
|
|
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
|
-
|
|
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') {
|