diff --git a/core/field.js b/core/field.js
index d89c9c779..e815683b5 100644
--- a/core/field.js
+++ b/core/field.js
@@ -194,6 +194,17 @@ Blockly.Field.prototype.updateEditable = function() {
}
};
+/**
+ * Check whether this field is currently editable. Some fields are never
+ * editable (e.g. text labels). Those fields are not serialized to XML. Other
+ * fields may be editable, and therefore serialized, but may exist on
+ * non-editable blocks.
+ * @return {boolean} whether this field is editable and on an editable block
+ */
+Blockly.Field.prototype.isCurrentlyEditable = function() {
+ return this.EDITABLE && !!this.sourceBlock_ && this.sourceBlock_.isEditable();
+};
+
/**
* Gets whether this editable field is visible or not.
* @return {boolean} True if visible.
diff --git a/tests/jsunit/field_test.js b/tests/jsunit/field_test.js
new file mode 100644
index 000000000..6a0faebc8
--- /dev/null
+++ b/tests/jsunit/field_test.js
@@ -0,0 +1,99 @@
+/**
+ * @license
+ * Visual Blocks Editor
+ *
+ * Copyright 2017 Google Inc.
+ * https://developers.google.com/blockly/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ /**
+ * @fileoverview Tests for Blockly.Field
+ * @author fenichel@google.com (Rachel Fenichel)
+ */
+'use strict';
+
+function test_field_isEditable_simple() {
+ var field = new Blockly.Field("Dummy text");
+ // EDITABLE is true by default, but without a source block a field can't be
+ // edited.
+ assertFalse('Field without a block is not editable',
+ field.isCurrentlyEditable());
+}
+
+function test_field_isEditable_false() {
+ // Setting EDITABLE to false doesn't matter.
+ var field = new Blockly.Field("Dummy text");
+ field.EDITABLE = false;
+ assertFalse('Field without a block is not editable',
+ field.isCurrentlyEditable());
+}
+
+function test_field_isEditable_editableBlock() {
+ var editableBlock = {
+ isEditable: function() {
+ return true;
+ }
+ };
+
+ var field = new Blockly.Field("Dummy text");
+ field.sourceBlock_ = editableBlock;
+
+ assertTrue('Editable field with editable block is editable',
+ field.isCurrentlyEditable());
+}
+
+function test_field_isEditable_editableBlock_false() {
+ var editableBlock = {
+ isEditable: function() {
+ return true;
+ }
+ };
+
+ var field = new Blockly.Field("Dummy text");
+ field.sourceBlock_ = editableBlock;
+ field.EDITABLE = false;
+
+ assertFalse('Non-editable field with editable block is not editable',
+ field.isCurrentlyEditable());
+}
+
+function test_field_isEditable_nonEditableBlock() {
+ var nonEditableBlock = {
+ isEditable: function() {
+ return false;
+ }
+ };
+
+ var field = new Blockly.Field("Dummy text");
+ field.sourceBlock_ = nonEditableBlock;
+
+ assertFalse('Editable field with non-editable block is not editable',
+ field.isCurrentlyEditable());
+}
+
+function test_field_isEditable_nonEditableBlock_false() {
+ var nonEditableBlock = {
+ isEditable: function() {
+ return false;
+ }
+ };
+
+ var field = new Blockly.Field("Dummy text");
+ field.sourceBlock_ = nonEditableBlock;
+ field.EDITABLE = false;
+
+ assertFalse('Non-editable field with non-editable block is not editable',
+ field.isCurrentlyEditable());
+}
diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html
index 71623d384..c24a395ee 100644
--- a/tests/jsunit/index.html
+++ b/tests/jsunit/index.html
@@ -11,6 +11,7 @@
+