@lumjs/core 1.5.0 → 1.5.2

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/lib/meta.js CHANGED
@@ -3,6 +3,8 @@
3
3
  * @module @lumjs/core/meta
4
4
  */
5
5
 
6
+ const {F,S,isArray,isa} = require('./types');
7
+
6
8
  /**
7
9
  * Get a stacktrace. Differs from browser to browser.
8
10
  *
@@ -30,20 +32,71 @@ exports.stacktrace = stacktrace;
30
32
  class AbstractClass
31
33
  {
32
34
  /**
33
- * You must override the constructor.
35
+ * If you want to mark a method as abstract use this.
34
36
  */
35
- constructor()
37
+ $abstract(name)
36
38
  {
37
- const name = this.constructor.name;
38
- throw new Error(`Cannot create instance of abstract class ${name}`);
39
+ if (name.indexOf('(') === -1)
40
+ { // Add empty method signature.
41
+ name += '()';
42
+ }
43
+ throw new Error(`Abstract method ${name} was not implemented`);
39
44
  }
40
45
 
41
46
  /**
42
- * If you want to mark a method as abstract use this.
47
+ * Check for required properties
48
+ *
49
+ * @param {...(string|Array)} needs - What is needed
50
+ *
51
+ * If this is a `string` it should be in a format like:
52
+ *
53
+ * - `methodName(arg1,arg2,arg3)`
54
+ * - `anotherMethod(number, string, object) : boolean`
55
+ * - `yetAnother (className) : resultClass`
56
+ *
57
+ * The names are case sensitive, and we'll look for the method after
58
+ * stripping off anything from the first *non-word* character.
59
+ *
60
+ * If this is an `Array`, the first item must be the name of a property,
61
+ * and each other item should be a type checking value, or array of type
62
+ * checking values from the [TYPES]{@link module:@lumjs/core/types.TYPES}
63
+ * object, as used by [isa()]{@link module:@lumjs/core/types.isa}.
64
+ *
65
+ * If you are calling this in an abstract class constructor, likely only
66
+ * the method checks will be useful, as the `super()` call must be done
67
+ * *before* any instance property assignments.
68
+ *
43
69
  */
44
- $abstract(name)
70
+ $needs(...needs)
45
71
  {
46
- throw new Error(`Abstract method ${name}() was not implemented`);
72
+ const className = this.constructor.name;
73
+
74
+ const getName = fullName => fullName.replace(/\W.*/, '');
75
+ const missing = propName =>
76
+ {
77
+ throw new Error(`${className} is missing ${propName}`);
78
+ }
79
+
80
+ for (const need of needs)
81
+ {
82
+ if (typeof need === S)
83
+ { // A simple method
84
+ const meth = getName(need);
85
+ if (typeof this[meth] !== F)
86
+ {
87
+ missing(need);
88
+ }
89
+ }
90
+ else if (isArray(need))
91
+ {
92
+ const prop = getName(need[0]);
93
+ const types = need.slice(1);
94
+ if (!isa(this[prop], ...types))
95
+ {
96
+ missing(need);
97
+ }
98
+ }
99
+ }
47
100
  }
48
101
 
49
102
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumjs/core",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "main": "lib/index.js",
5
5
  "exports":
6
6
  {
@@ -1,93 +0,0 @@
1
- # Changelog → 1.0-beta.x
2
-
3
- This is the changelog for the `1.0-beta.x` versions.
4
-
5
- See [Changelogs](index.md) for more information on the changelogs.
6
-
7
- ## [1.0.0-beta.6]
8
- - This is the **final** beta version.
9
- - Version `1.0.0` will be this but with the docs updated a bit.
10
- ### Added
11
- - More tests for the `types` module.
12
- - Changelog file for the upcoming `1.x` *stable* releases.
13
- ### Changed
14
- - Removed some convoluted options from `def()`.
15
- - Reworked `types.stringify()` to handle recursive mode better.
16
- - Added `Error` stringification to `types.stringify()`
17
-
18
- ## [1.0.0-beta.5] - 2022-07-18
19
- ### Added
20
- - A new `types.stringify()` method.
21
- - Shortcut `string` options for the `types.def()` method.
22
- - A `build-docs` script in `package.json`.
23
- ### Changed
24
- - Overhauled all DocBlocks to conform to `JSDoc 3` format.
25
- - Changed `context.has` to support a magic `Proxy` version.
26
- - Some tweaks to `Enum` to cleanup some things.
27
- - Both `Enum` and `observable` use `TYPES.add()` now.
28
- - In `modules.name()` nixed `opts.noAuto` and added `opts.useAuto` instead.
29
- - Created explicit `exports` definition in `package.json` with our sub-modules.
30
- ### Fixed
31
- - Fixed a property definition issue in `obj.SOA()`.
32
-
33
- ## [1.0.0-beta.4] - 2022-07-15
34
- ### Added
35
- - Two new clone modes:
36
- - `CLONE.DEEP` : A recursive clone of enumerable properties.
37
- - `CLONE.ENTIRE` : A recursive clone of all properties.
38
- - Added `types.isa()` which wraps `isType()` and `isInstance()` along with some added magic that makes it a generic *smart match* function.
39
- - Added `types.needs()` which does for `isa()` what `needOb()` and `needType()` do for `isObj()` and `isType()` respectively.
40
- - A `jsdoc.json` based on the one from the old [Lum.js](https://github.com/supernovus/lum.js) codebase.
41
- - A temporary `test` script to the `package.json` which uses the `prove` utility from Perl 5.
42
- ### Removed
43
- - Removed `descriptors` and `prop()` modules.
44
- - They'll be in a new `@lumjs/compat` library for legacy compatibility code.
45
- ### Changed
46
- - Updated this *changelog* which I forgot to do last time.
47
- - Fixed some formatting in the changelog.
48
- - Split `types` into separated files.
49
- - Moved/renamed a few functions:
50
- - `types.containsAny()` → `arrays.containsAny()`
51
- - `types.containsAll()` → `arrays.containsAll()`
52
- - `types.removeFromArray()` → `arrays.removeItems()`
53
- - `types.NYI()` → `meta.NYI()`
54
- - Updated tests to reflect the moved/renamed functions.
55
- - Enhanced `def()` function as it has fully replaced `prop()` now.
56
- - Has a new `opts` parameter which can be used for a few different options.
57
- - Allows assigning a *getter* and *setter* without using a descriptor.
58
- - Updated `lazy()` to be an extension of `def()` instead of `prop()`.
59
- - Updated `obj/clone` and `obj/lock` to remove use of `descriptors` magic.
60
- - Updated `CLONE` mode documentation to use a table format.
61
- - A few minor tweaks and cleanups related to the rest of the above changes.
62
- - Updated [../../TODO.md](TODO.md) with the plans for the final `1.0.0` release.
63
-
64
- ## [1.0.0-beta.3] - 2022-07-11
65
- ### Added
66
- - `core.context.hasRequire`: A boolean value indicating `require()`
67
- - `core.context.isNode`: A boolean value guessing the environment is node.js
68
- ### Changed
69
- - `core.context.CJS`: Made slightly tighter in definition.
70
- - `core.modules.name()`: Made it more flexible.
71
- - `core.obj`: Changed namespace exports.
72
- ### Fixed
73
- - `core.modules.name()`: Actually return the value!
74
-
75
- ## [1.0.0-beta.2] - 2022-07-08
76
- ### Changed
77
- - Renamed `src` to `lib` as we're not compiling/transpiling this code.
78
- - Moved `index.js` into `lib` with the rest of the module files.
79
- - Added `modules.js` with a method for generating a name/id for a module.
80
- - Added `isSearch()`,`isReplacement()`, and `replaceItems()` to `strings.js`.
81
-
82
- ## [1.0.0-beta.1] - 2022-07-07
83
- ### Added
84
- - Initial release.
85
- - Pulled a bunch of the core libraries from the old Lum.js project.
86
- - Refactored and reorganized the libraries a lot.
87
-
88
- [1.0.0-beta.6]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.5...v1.0.0-beta.6
89
- [1.0.0-beta.5]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.4...v1.0.0-beta.5
90
- [1.0.0-beta.4]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.3...v1.0.0-beta.4
91
- [1.0.0-beta.3]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.2...v1.0.0-beta.3
92
- [1.0.0-beta.2]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.1...v1.0.0-beta.2
93
- [1.0.0-beta.1]: https://github.com/supernovus/lum.core.js/releases/tag/v1.0.0-beta.1
@@ -1,103 +0,0 @@
1
- # Changelog → 1.x
2
-
3
- This is the changelog for the `1.x` versions.
4
-
5
- See [Changelogs](index.md) for more information on the changelogs.
6
-
7
- ## [Unreleased]
8
-
9
- ## [1.5.0] - 2022-09-27
10
- ### Changed
11
- - Updated a few DocBlocks.
12
- - Added a couple explicitly named options to `def()`
13
- - Rewrote the default module to use `def()` to define its exported properties.
14
- - Made `arrays`, `strings`, `flags`, `opt`, `modules`, and `observable` use `lazy()`.
15
- ### Fixed
16
- - Fixed `def()` so that the descriptor defaults are applied properly.
17
- - Fixed `lazy()` so it returns a proper value and not a descriptor on first access.
18
-
19
- ## [1.4.0] - 2022-09-26
20
- ### Changed
21
- - Moved `lazy` into `types` module by default (leaving an alias in `core`).
22
- - Completely rewrote the `lazy` function entirely.
23
- - Greatly extended the documentation for `lazy` function.
24
- - Removed an unused development artefact from `types.needs`.
25
-
26
- ## [1.3.1] - 2022-09-23
27
- ### Fixed
28
- - The `arrays` module exports `powerset` and `random` as it should.
29
- - Recursive dependency order issues with `clone`, `lock`, and `enum` resolved.
30
- - Custom `lock` options in `enum` module actually work now.
31
- ### Changed
32
- - The `Enum()` function now has `configurable` and `enumerable` options.
33
- - The `configurable` property in `enums` defaults to `false` now.
34
- - Tweaked the *changelogs* a bit and added a new [changelog listing](index.md).
35
-
36
- ## [1.3.0] - 2022-09-11
37
- ### Changed
38
- - Overhauled the `obj.clone()` method.
39
- - Added *named options* for all of the behaviours that the `CLONE` *modes* affect.
40
- While this technically could make the *modes* obsolete, I'm leaving them in as
41
- simple sets of default options that can be used instead of manually choosing all
42
- of the individual options.
43
- - Added a new `CLONE.N` *mode* which has **no** options turned on.
44
- It will always remain first in the *enum* list so it's value will always be `0`.
45
- - Added the ability to clone properties using their descriptors.
46
- It is enabled by default on most of the *modes* now, as it simply makes sense.
47
- - Added the ability to set the `prototype` on the cloned object.
48
- - The `opts` parameter of `clone()` may be a `CLONE.*` enum value.
49
- It's a shortcut for `{mode: CLONE.MODE}` for convenience.
50
- - A small tweak to `obj.copyProps()`, not important, just a cleanup.
51
- ### Fixed
52
- - A reference in the DocBlock for `obj.getProperty()`.
53
-
54
- ## [1.2.1] - 2022-09-05
55
- ### Added
56
- - `core.InternalObjectId#untag()`
57
- ### Changed
58
- - Cleaned up the wording in a docblock, and updated a test to use `done()`.
59
-
60
- ## [1.2.0] - 2022-08-10
61
- ### Added
62
- - Moved the `array.powerset()` and `array.random()` methods from Lum.js v4 into `core.arrays`.
63
- - Added a new `core.context.isCommonJS()` method which is only used in certain circumstances.
64
-
65
- ### Fixed
66
- - A typo in one of the `package.json` exports.
67
- - Commented out a debugging line.
68
-
69
- ## [1.1.1] - 2022-08-02
70
- ### Fixed
71
- - A couple missing constants in some functions.
72
-
73
- ## [1.1.0] - 2022-07-29
74
- ### Added
75
- - `types.doesDescriptorTemplate()` method.
76
- - `obj.getProperty()` method (used to be in the `descriptors` sub-module.)
77
- ### Changed
78
- - Tweaked documentation for:
79
- - `obj.getObjectPath()`
80
- - `obj.setObjectPath()`
81
- - `obj.getNamespace()`
82
- - `obj.setNamespace()`
83
- - Updated error messages in `obj.setObjectPath()`
84
- - Made `obj.setObjectPath()` use `types.doesDescriptorTemplate()` for validation of `opts.desc` option.
85
- - Changed `obj.getObjectPath()` and `obj.setObjectPath()` to support `function` parent objects.
86
- - Enhanced `types.stringify()` to support `RegExp` as well as supporting custom extensions down the road.
87
-
88
- ## [1.0.0] - 2022-07-27
89
- ### Changed
90
- - Initial *stable* release.
91
- - See [1.0-beta.md](1.0-beta.md) for the beta versions of `1.0`
92
- - See [lum.js](https://github.com/supernovus/lum.js) for the original library set this is replacing.
93
-
94
- [Unreleased]: https://github.com/supernovus/lum.core.js/compare/v1.5.0...HEAD
95
- [1.5.0]: https://github.com/supernovus/lum.core.js/compare/v1.4.0...v1.5.0
96
- [1.4.0]: https://github.com/supernovus/lum.core.js/compare/v1.3.1...v1.4.0
97
- [1.3.1]: https://github.com/supernovus/lum.core.js/compare/v1.3.0...v1.3.1
98
- [1.3.0]: https://github.com/supernovus/lum.core.js/compare/v1.2.1...v1.3.0
99
- [1.2.1]: https://github.com/supernovus/lum.core.js/compare/v1.2.0...v1.2.1
100
- [1.2.0]: https://github.com/supernovus/lum.core.js/compare/v1.1.1...v1.2.0
101
- [1.1.1]: https://github.com/supernovus/lum.core.js/compare/v1.1.0...v1.1.1
102
- [1.1.0]: https://github.com/supernovus/lum.core.js/compare/v1.0.0...v1.1.0
103
- [1.0.0]: https://github.com/supernovus/lum.core.js/releases/tag/v1.0.0
@@ -1,19 +0,0 @@
1
- # Changelogs
2
-
3
- All notable changes to this project will be documented in these files.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## Versions
9
-
10
- To avoid the changelogs getting too big, I'm planning on splitting them up based
11
- on the major version changes.
12
-
13
- Each major version will be listed here in reverse chronological order (newest first.)
14
-
15
- - [1.x](1.x.md) → The first standalone core library.
16
- - [1.0-beta.x](1.0-beta.md)
17
- → The *pre-releases* from when this split off of the older
18
- [Lum.js](https://github.com/supernovus/lum.js) library collection.
19
-
package/test/arrays.js DELETED
@@ -1,19 +0,0 @@
1
- // Current test count.
2
- const plan = 5;
3
- // A new test instance.
4
- const t = require('@lumjs/tests').new({module, plan});
5
- // The arrays core module
6
- const arr = require('../lib/arrays');
7
-
8
- t.ok(arr.containsAny(['hello','world'], 'world'), 'containsAny([a], a)');
9
- t.ok(!arr.containsAny(['hello','world'], 'universe'), '!containsAny([a], b)');
10
- t.ok(arr.containsAll(['hello','darkness','my','old','friend'], 'hello', 'friend'), 'containsAll([a,b,c], a, c)');
11
- t.ok(!arr.containsAll(['nothing','to','see'], 'nothing', 'here'), '!containsAll([a,b,c], a, d)');
12
-
13
- const a1 = ['hello', 'darkness', 'my', 'old', 'friend'];
14
- arr.removeItems(a1, 'darkness');
15
- t.isJSON(a1, ['hello','my','old','friend'], 'removeFromArray(...)');
16
-
17
- // All done.
18
- t.output();
19
-
package/test/meta.js DELETED
@@ -1,17 +0,0 @@
1
- // Current test count.
2
- const plan = 1;
3
- // A new test instance.
4
- const t = require('@lumjs/tests').new({module, plan});
5
- // The meta core module
6
- const meta = require('../lib/meta');
7
-
8
- t.dies(()=>meta.NYI(), 'NYI()');
9
-
10
- // TODO:
11
- // - stacktrace()
12
- // - AbstractClass
13
- // - Functions.*
14
-
15
- // All done.
16
- t.output();
17
-
package/test/types.js DELETED
@@ -1,268 +0,0 @@
1
- // Current test count.
2
- const plan = 120;
3
- // A new test instance.
4
- const t = require('@lumjs/tests').new({module, plan});
5
- // The types core module
6
- const types = require('../lib/types');
7
-
8
- // A quick reference to the type names.
9
- const TYP = types.TYPES;
10
- // And the stringify function.
11
- const stringify = types.stringify;
12
-
13
- // Now for some further basics.
14
- t.ok(types.isObj({}), 'isObj({})');
15
- t.ok(types.isComplex({}), 'isComplex(object)');
16
- t.ok(types.isComplex(function(){}), 'isComplex(function)');
17
- t.ok(types.isNil(undefined), 'isNil(undefined)');
18
- t.ok(types.isNil(null), 'isNil(null)');
19
- t.ok(types.notNil(true), 'notNil(true)');
20
- t.ok(types.notNil(false), 'notNil(false)');
21
- t.ok(types.notNil(''), "notNil('')");
22
- t.ok(types.isScalar(true), 'isScalar(true)');
23
- t.ok(types.isScalar(0), 'isScalar(0)');
24
- t.ok(!types.isScalar({}), '!isScalar({})');
25
- t.ok(!types.isScalar(null), '!isScalar(null)');
26
- t.ok(types.isArray([]), 'isArray([])');
27
- t.ok(types.isTypedArray(new Int8Array(8)), 'isTypedArray(Int8Array)');
28
- t.ok(types.nonEmptyArray([1,2,3]), 'nonEmptyArray([1,2,3])');
29
- t.ok(!types.nonEmptyArray([]), '!nonEmptyArray([])');
30
- t.ok(types.isProperty('hi'), 'isProperty(string)');
31
- t.ok(types.isProperty(Symbol('hi')), 'isProperty(Symbol)');
32
- t.ok(!types.isProperty(false), '!isProperty(false)')
33
-
34
- function getArguments() { return arguments; }
35
-
36
- t.ok(types.isArguments(getArguments()), 'isArguments(arguments)');
37
- t.ok(!types.isArguments({}), '!isArguments({})');
38
-
39
- class TypeClass
40
- {
41
- notUnbound()
42
- {
43
- t.ok(!types.unbound(this), '!unbound(instanceThis)');
44
- }
45
- }
46
-
47
- class SubtypeClass extends TypeClass {}
48
-
49
- const typesInstance = new TypeClass();
50
- const subtypeInstance = new SubtypeClass();
51
-
52
- class DifferentClass {}
53
-
54
- const differentInstance = new DifferentClass();
55
-
56
- t.ok(types.isInstance(typesInstance, TypeClass), 'isInstance(typeInstance,TypeClass)');
57
- t.ok(types.isInstance(subtypeInstance, SubtypeClass), 'isInstance(subtypeInstance, SubtypeClass)');
58
- t.ok(types.isInstance(subtypeInstance, TypeClass), 'isInstance(subtypeInstance, TypeClass)');
59
- t.ok(!types.isInstance(typesInstance, SubtypeClass), '!isInstance(typeInstance, SubtypeClass)');
60
- t.ok(!types.isInstance(differentInstance, TypeClass), '!isInstance(differentInstance, TypeClass)');
61
- t.ok(!types.isInstance(typesInstance, DifferentClass), '!isInstance(typesInstance, DifferentClass)');
62
-
63
- function doesDesc (tests, not=false)
64
- {
65
- for (const it of tests)
66
- {
67
- let result = types.doesDescriptor(it);
68
- if (not) result = !result;
69
- const desc = (not?'!':'')+'doesDescriptor'+stringify(it)+')';
70
- t.ok(result, desc);
71
- }
72
- }
73
-
74
- doesDesc(
75
- [
76
- {value: true},
77
- {value: {}, writable: true},
78
- {get: function(){}},
79
- {set: function(){}},
80
- {get: function(){}, set: function(){}},
81
- {get: function(){}, configurable: true},
82
- ]);
83
-
84
- doesDesc(
85
- [
86
- {},
87
- {value: true, get: function(){}},
88
- {value: true, set: function(){}},
89
- {get: function(){}, writable: true},
90
- {set: function(){}, writable: true},
91
- ], true);
92
-
93
- function testIsType (tests, not=false)
94
- {
95
- for (const it of tests)
96
- {
97
- let result = types.isType(it[0], it[1]);
98
- if (not) result = !result;
99
- const desc = (it.length > 2)
100
- ? it[2]
101
- : (it[0]+','+stringify(it[1]));
102
- t.ok(result, (not?'!':'')+'isType('+desc+')');
103
- }
104
- }
105
-
106
- testIsType(
107
- [
108
- [TYP.O, {}],
109
- [TYP.F, function(){}],
110
- [TYP.S, 'hello'],
111
- [TYP.B, true],
112
- [TYP.B, false],
113
- [TYP.N, 100],
114
- [TYP.U, undefined],
115
- [TYP.SY, Symbol('foo'), TYP.SY+',Symbol'],
116
- [TYP.BI, BigInt(12345), TYP.BI+',BigInt(12345)'],
117
- [TYP.BI, 54321n, TYP.BI+',54321n'],
118
- [TYP.ARGS, getArguments()],
119
- [TYP.ARRAY, []],
120
- [TYP.NULL, null],
121
- [TYP.TYPEDARRAY, new Int16Array(16), TYP.TYPEDARRAY+',Int16Array(16)'],
122
- [TYP.DESCRIPTOR, {value: true}],
123
- [TYP.DESCRIPTOR, {get: function(){}}],
124
- [TYP.COMPLEX, {}],
125
- [TYP.COMPLEX, function(){}],
126
- [TYP.SCALAR, true],
127
- [TYP.SCALAR, 'hi'],
128
- [TYP.PROP, 'woah'],
129
- [TYP.PROP, Symbol('woah')],
130
- ]);
131
-
132
- testIsType(
133
- [
134
- [TYP.O, 'foo'],
135
- [TYP.O, null],
136
- [TYP.F, {}],
137
- [TYP.B, 0],
138
- [TYP.B, 1],
139
- [TYP.N, '0'],
140
- [TYP.U, null],
141
- [TYP.SY, 'foo'],
142
- [TYP.BI, 12345],
143
- [TYP.ARGS, {}],
144
- [TYP.ARRAY, {}],
145
- [TYP.NULL, false],
146
- [TYP.TYPEDARRAY, []],
147
- [TYP.DESCRIPTOR, {value: true, get: function(){}}],
148
- [TYP.DESCRIPTOR, {}],
149
- [TYP.COMPLEX, 'a string'],
150
- [TYP.SCALAR, {}],
151
- [TYP.PROP, null],
152
- ], true);
153
-
154
- (function(){ t.ok(types.unbound(this), 'unbound(unboundThis)'); })();
155
- (function(){ t.ok(!types.unbound(this), '!unbound(boundThis)') }).bind({})();
156
- typesInstance.notUnbound();
157
-
158
- t.ok((function(){types.needObj({}); return true})(), 'needObj({})');
159
- t.dies(function(){types.needObj(null); return true}, '!needObj(null)');
160
-
161
- t.ok((function(){types.needType(TYP.S, 'hi'); return true})(), "needType('string','hi')");
162
- t.dies(function(){types.needType(TYP.O, null); return true}, "!needType('object',null)");
163
-
164
- { // Tests of isa() method.
165
- let wants = [TYP.S, TYP.N];
166
- t.ok(types.isa('hi', ...wants), 'isa(val, ...types)');
167
- t.isa('hello', wants, ' ^ using Test.isa()');
168
- t.isa(42, wants, ' ^ with second type');
169
- t.ok(!types.isa({}, ...wants), '!isa(val, ...types)');
170
- t.nota({}, wants, ' ^ using Test.nota()');
171
-
172
- wants = [SubtypeClass, DifferentClass];
173
- t.isa(subtypeInstance, wants, 'isa(val, ...classes)');
174
- t.isa(differentInstance, wants, ' ^ with second class');
175
- t.nota(typesInstance, wants, 'nota(val, ...classes)');
176
-
177
- wants = [TYP.B, TypeClass];
178
- t.isa(true, wants, 'isa() → with mixed types/classes');
179
- t.isa(subtypeInstance, wants, ' ^ with second type/class');
180
- }
181
-
182
- { // Tests of needs() method.
183
- let needs = [TYP.S, TYP.N];
184
- t.lives(() => types.needs('hi', ...needs), 'needs(val, ...types)');
185
- t.lives(() => types.needs(42, ...needs), ' ^ with second type');
186
- t.dies(() => types.needs({}, ...needs), ' ^ throws on failure');
187
-
188
- needs = [SubtypeClass, DifferentClass];
189
- t.lives(() => types.needs(subtypeInstance, ...needs), 'needs(val, ...classes)');
190
- t.lives(() => types.needs(differentInstance, ...needs), ' ^ with second class');
191
- t.dies(() => types.needs(typesInstance, ...needs), ' ^ throws on failure');
192
-
193
- needs = [TYP.B, TypeClass];
194
- t.lives(() => types.needs(true, ...needs), 'needs() → with mixed types/classes');
195
- t.lives(() => types.needs(subtypeInstance, ...needs), ' ^ with second type/class');
196
- }
197
-
198
- { // Try a few versions of 'def'
199
- const obj = {};
200
- types.def(obj, 'test1', 'Test 1');
201
- t.is(obj.test1, 'Test 1', 'def(obj, name, value)');
202
- types.def(obj)('test2', 'Test 2');
203
- t.is(obj.test2, 'Test 2', 'def(obj)(name, value)');
204
- obj.test2 = '2 Test';
205
- t.is(obj.test2, 'Test 2', 'def() is read-only by default');
206
-
207
- types.def(obj, true)('test3', 'Test 3');
208
- t.is(Object.keys(obj).length, 1, 'def(obj, true)(...)');
209
-
210
- types.def(obj, 'a1', function()
211
- { // Returning a different property.
212
- return this.test2;
213
- },
214
- function(val)
215
- { // Assigning to a different property.
216
- this.$$ = val;
217
- });
218
-
219
- const gs = 'def(obj, name, getter, setter)';
220
- t.is(obj.a1, 'Test 2', gs+'~getter');
221
- obj.a1 = 'A1->$$';
222
- t.is(obj.$$, 'A1->$$', gs+'~setter');
223
-
224
- types.def(obj, 'test4', 'Test 4', {writable: true});
225
- t.is(obj.test4, 'Test 4', 'def(..., {writable}) → added property');
226
- obj.test4 = '4 Test';
227
- t.is(obj.test4, '4 Test', ' ^ and it was writable');
228
-
229
- const td = types.def(obj);
230
- td('getOnly', {get: function() { return 'GETTER'; }});
231
- obj.getOnly = 'blah blah blah';
232
- t.is(obj.getOnly, 'GETTER', 'def(..., {get: getter}) → getter worked');
233
- td('setOnly', {set: function(val) { this.__ = val; }});
234
- obj.setOnly = 'SETTER';
235
- t.is(obj.__, 'SETTER', 'def(..., {set: setter}) → setter worked');
236
- t.is(obj.setOnly, undefined, ' ^ get is undefined');
237
-
238
- td('foobar', {value: 'FOO BAR'});
239
- t.is(obj.foobar, 'FOO BAR', 'def(..., {value})');
240
-
241
- let anObj = {value: 'BAR FOO'};
242
- td('barfoo', anObj, false);
243
- t.is(obj.barfoo, anObj, 'def(..., descriptor, false) → assigned object as value');
244
-
245
- td('barfoo2', anObj);
246
- t.is(anObj.configurable, true, 'def(..., descriptor) → descriptor is a reference');
247
-
248
- anObj = {value: 'new test'};
249
- td('barfoo3', anObj, true);
250
-
251
- t.is(anObj.configurable, undefined, 'def(..., descriptor, true) → cloned descriptor');
252
- t.is(obj.barfoo3, 'new test', ' ^ value was correct')
253
-
254
- td(
255
- {
256
- hello: 'World',
257
- goodbye: 'Universe',
258
- });
259
-
260
- t.ok((obj.hello === 'World' && obj.goodbye === 'Universe'), 'def(obj, {prop1: value1, prop2: value2})')
261
- }
262
-
263
- // TODO: isa() and needs()
264
- // TODO: stringify()
265
-
266
- // All done.
267
- t.done();
268
-