From bfb6e7068a0a5c344a1ba4c523ad815cc0436404 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Thu, 24 Jul 2014 01:54:15 -0400 Subject: [PATCH] Initial ProtoField implementation --- lib/proto/field/ProtoField.js | 96 ++++++++++++++++++++++++++++++ test/proto/field/ProtoFieldTest.js | 79 ++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 lib/proto/field/ProtoField.js create mode 100644 test/proto/field/ProtoFieldTest.js diff --git a/lib/proto/field/ProtoField.js b/lib/proto/field/ProtoField.js new file mode 100644 index 0000000..0c51c86 --- /dev/null +++ b/lib/proto/field/ProtoField.js @@ -0,0 +1,96 @@ +/** + * Class prototype field + * + * Copyright (C) 2014 Free Software Foundation, Inc. + * + * This file is part of GNU ease.js. + * + * ease.js is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * Initializes field with a datum + * + * The ProtoField itself is immutable in the sense that its value cannot be + * reassigned; but if DATUM references a mutable object, then that object is + * not prohibited from changing; doing so is, however, not recommended and + * such behavior is not defined, nor is it defined that DATUM's reference + * will be maintained (e.g. the referenced object may be at some point + * cloned). + * + * @type {*} datum field datum (value) + */ +function ProtoField( datum ) +{ + if ( !( this instanceof ProtoField ) ) { + return new ProtoField( datum ); + } + + this._datum = datum; +} + + +ProtoField.prototype = { + /** + * Retrieve the datum assigned to the field during construction + * + * It is not defined whether this datum will be strictly equal to the + * datum provided during construction (that is---reference the same + * object), but it will be guaranteed to be recursively (deep) + * equivalent. + * + * @return {*} field datum + */ + getDatum: function() + { + return this._datum; + }, + + + /** + * Produce a representation of the field suitable for use in a class + * prototype that contains, at a minimum, a datum that is recurisvely + * equivalent to the datum provided during construction + * + * The produced datum is not guaranteed to be strictly equal to the one + * provided during construction, or even to the one returned by the + * getValue method. Further, the datum may contain metadata that was not + * provided during construction. + * + * The produced datum should be treated as just that---a datum; opaque. + * To decompose it for processing, use ProtoField.parse. + * + * @return {*} datum suitable for use in a class prototype + */ + compile: function() + { + return this.getDatum(); + }, +}; + + +/** + * Consume a previously compiled ProtoField, producing a new ProtoField that + * is equivalent to the original ProtoField before compiling + * + * @param {*} compiled_field datum produced with ProtoField#compile + */ +ProtoField.parse = function( compiled_field ) +{ + return ProtoField( compiled_field ); +}; + + +module.exports = ProtoField; + diff --git a/test/proto/field/ProtoFieldTest.js b/test/proto/field/ProtoFieldTest.js new file mode 100644 index 0000000..d3dd782 --- /dev/null +++ b/test/proto/field/ProtoFieldTest.js @@ -0,0 +1,79 @@ +/** + * Tests class prototype field + * + * Copyright (C) 2014 Free Software Foundation, Inc. + * + * This file is part of GNU ease.js. + * + * ease.js is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +require( 'common' ).testCase( 'proto/field/ProtoField', +{ + /** + * This method is intended to provide a datum that is equivalent + * (recursively equal) to the datum provided during construction. As + * documented, there is no guarantee that the returned datum will be + * strictly equal to the one provided (it so happens that, at the time + * that this test case was written, it is; this API is intended not only + * for this prototype). + */ + 'Field datum retrieved is equivalent to assigned datum': + function() + { + var val = { foo: { bar: 'baz' } }; + + this.assertDeepEqual( + val, + this.Sut( val ).getDatum() + ); + }, + + + /** + * The purpose of the ProtoField family of prototypes is to produce + * fields suitable for a class prototype; this method will do so by + * producing both the datum assigned to it, as well as any other + * metadata that may be needed or desirable. + * + * At present, there is no additional metadata produced by ProtoField. + */ + 'Compiling field produces its datum': function() + { + var field = this.Sut( [ [ {} ] ] ); + + this.assertDeepEqual( + field.getDatum(), + field.compile() + ); + }, + + + /** + * In addition to producing a compiled field, we also support consuming + * a compiled field back into our internal representation for further + * processing (for example, this could be useful for static analysis). + */ + 'Parsing compiled field produces equivalent representation': function() + { + var value = { foo: [ 'bar', 'baz' ] }, + field = this.Sut( value ), + compiled = field.compile(), + parsed = this.Sut.parse( compiled ); + + this.assertDeepEqual( field.getDatum(), parsed.getDatum() ); + this.assertDeepEqual( compiled, parsed.compile() ); + }, +} ); +