traits 0.4.0 → 0.5.0

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.
Files changed (106) hide show
  1. package/Assessment.ts +14 -0
  2. package/LICENSE +203 -0
  3. package/Source.ts +13 -0
  4. package/Trait.ts +51 -0
  5. package/TraitConflict.ts +52 -0
  6. package/TraitDerivation.ts +137 -0
  7. package/TraitEvaluation.ts +69 -0
  8. package/TraitStore.ts +88 -0
  9. package/TraitsConfig.ts +57 -0
  10. package/TraitsContext.ts +11 -0
  11. package/_util/Approval.ts +59 -0
  12. package/_util/Git.ts +25 -0
  13. package/_util/TraitsConfigProvider.ts +22 -0
  14. package/_util/TraitsTelemetry.ts +20 -0
  15. package/_util/words.ts +555 -0
  16. package/commands/init.ts +73 -0
  17. package/dist/Assessment.d.ts +12 -0
  18. package/dist/Assessment.d.ts.map +1 -0
  19. package/dist/Assessment.js +12 -0
  20. package/dist/Assessment.js.map +1 -0
  21. package/dist/Source.d.ts +21 -0
  22. package/dist/Source.d.ts.map +1 -0
  23. package/dist/Source.js +10 -0
  24. package/dist/Source.js.map +1 -0
  25. package/dist/Trait.d.ts +12 -0
  26. package/dist/Trait.d.ts.map +1 -0
  27. package/dist/Trait.js +44 -0
  28. package/dist/Trait.js.map +1 -0
  29. package/dist/TraitConflict.d.ts +56 -0
  30. package/dist/TraitConflict.d.ts.map +1 -0
  31. package/dist/TraitConflict.js +47 -0
  32. package/dist/TraitConflict.js.map +1 -0
  33. package/dist/TraitDerivation.d.ts +99 -0
  34. package/dist/TraitDerivation.d.ts.map +1 -0
  35. package/dist/TraitDerivation.js +109 -0
  36. package/dist/TraitDerivation.js.map +1 -0
  37. package/dist/TraitEvaluation.d.ts +68 -0
  38. package/dist/TraitEvaluation.d.ts.map +1 -0
  39. package/dist/TraitEvaluation.js +61 -0
  40. package/dist/TraitEvaluation.js.map +1 -0
  41. package/dist/TraitStore.d.ts +17 -0
  42. package/dist/TraitStore.d.ts.map +1 -0
  43. package/dist/TraitStore.js +57 -0
  44. package/dist/TraitStore.js.map +1 -0
  45. package/dist/TraitsConfig.d.ts +14 -0
  46. package/dist/TraitsConfig.d.ts.map +1 -0
  47. package/dist/TraitsConfig.js +40 -0
  48. package/dist/TraitsConfig.js.map +1 -0
  49. package/dist/TraitsContext.d.ts +11 -0
  50. package/dist/TraitsContext.d.ts.map +1 -0
  51. package/dist/TraitsContext.js +4 -0
  52. package/dist/TraitsContext.js.map +1 -0
  53. package/dist/_util/Approval.d.ts +28 -0
  54. package/dist/_util/Approval.d.ts.map +1 -0
  55. package/dist/_util/Approval.js +48 -0
  56. package/dist/_util/Approval.js.map +1 -0
  57. package/dist/_util/Git.d.ts +15 -0
  58. package/dist/_util/Git.d.ts.map +1 -0
  59. package/dist/_util/Git.js +17 -0
  60. package/dist/_util/Git.js.map +1 -0
  61. package/dist/_util/TraitsConfigProvider.d.ts +3 -0
  62. package/dist/_util/TraitsConfigProvider.d.ts.map +1 -0
  63. package/dist/_util/TraitsConfigProvider.js +17 -0
  64. package/dist/_util/TraitsConfigProvider.js.map +1 -0
  65. package/dist/_util/TraitsTelemetry.d.ts +3 -0
  66. package/dist/_util/TraitsTelemetry.d.ts.map +1 -0
  67. package/dist/_util/TraitsTelemetry.js +12 -0
  68. package/dist/_util/TraitsTelemetry.js.map +1 -0
  69. package/dist/_util/words.d.ts +2 -0
  70. package/dist/_util/words.d.ts.map +1 -0
  71. package/dist/_util/words.js +556 -0
  72. package/dist/_util/words.js.map +1 -0
  73. package/dist/commands/init.d.ts +4 -0
  74. package/dist/commands/init.d.ts.map +1 -0
  75. package/dist/commands/init.js +67 -0
  76. package/dist/commands/init.js.map +1 -0
  77. package/dist/index.d.ts +10 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +10 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/main.d.ts +3 -0
  82. package/dist/main.d.ts.map +1 -0
  83. package/dist/main.js +73 -0
  84. package/dist/main.js.map +1 -0
  85. package/dist/package.json +53 -0
  86. package/dist/toolkit/CheckTraits.d.ts +79 -0
  87. package/dist/toolkit/CheckTraits.d.ts.map +1 -0
  88. package/dist/toolkit/CheckTraits.js +110 -0
  89. package/dist/toolkit/CheckTraits.js.map +1 -0
  90. package/dist/toolkit/DeriveTrait.d.ts +108 -0
  91. package/dist/toolkit/DeriveTrait.d.ts.map +1 -0
  92. package/dist/toolkit/DeriveTrait.js +54 -0
  93. package/dist/toolkit/DeriveTrait.js.map +1 -0
  94. package/dist/toolkit/toolkit.d.ts +3 -0
  95. package/dist/toolkit/toolkit.d.ts.map +1 -0
  96. package/dist/toolkit/toolkit.js +6 -0
  97. package/dist/toolkit/toolkit.js.map +1 -0
  98. package/index.ts +9 -0
  99. package/main.ts +113 -0
  100. package/package.json +46 -0
  101. package/skills/traits/SKILL.md +307 -0
  102. package/toolkit/CheckTraits.ts +150 -0
  103. package/toolkit/DeriveTrait.ts +59 -0
  104. package/toolkit/toolkit.ts +9 -0
  105. 1289345811335-0.8567837113514543/lib/traits.js +0 -662
  106. 1289345811335-0.8567837113514543/package.json +0 -7
@@ -1,662 +0,0 @@
1
- // Copyright (C) 2010 Google Inc.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
-
15
- // See http://code.google.com/p/es-lab/wiki/Traits
16
- // for background on traits and a description of this library
17
-
18
- var Trait = (function(){
19
-
20
- // == Ancillary functions ==
21
-
22
- var SUPPORTS_DEFINEPROP = (function() {
23
- try {
24
- var test = {};
25
- Object.defineProperty(test, 'x', {get: function() { return 0; } } );
26
- return test.x === 0;
27
- } catch(e) {
28
- return false;
29
- }
30
- })();
31
-
32
- // IE8 implements Object.defineProperty and Object.getOwnPropertyDescriptor
33
- // only for DOM objects. These methods don't work on plain objects.
34
- // Hence, we need a more elaborate feature-test to see whether the
35
- // browser truly supports these methods:
36
- function supportsGOPD() {
37
- try {
38
- if (Object.getOwnPropertyDescriptor) {
39
- var test = {x:0};
40
- return !!Object.getOwnPropertyDescriptor(test,'x');
41
- }
42
- } catch(e) {}
43
- return false;
44
- };
45
- function supportsDP() {
46
- try {
47
- if (Object.defineProperty) {
48
- var test = {};
49
- Object.defineProperty(test,'x',{value:0});
50
- return test.x === 0;
51
- }
52
- } catch(e) {}
53
- return false;
54
- };
55
-
56
- var call = Function.prototype.call;
57
-
58
- /**
59
- * An ad hoc version of bind that only binds the 'this' parameter.
60
- */
61
- var bindThis = Function.prototype.bind ?
62
- function(fun, self) { return Function.prototype.bind.call(fun, self); } :
63
- function(fun, self) {
64
- function funcBound(var_args) {
65
- return fun.apply(self, arguments);
66
- }
67
- return funcBound;
68
- };
69
-
70
- var hasOwnProperty = bindThis(call, Object.prototype.hasOwnProperty);
71
- var slice = bindThis(call, Array.prototype.slice);
72
-
73
- // feature testing such that traits.js runs on both ES3 and ES5
74
- var forEach = Array.prototype.forEach ?
75
- bindThis(call, Array.prototype.forEach) :
76
- function(arr, fun) {
77
- for (var i = 0, len = arr.length; i < len; i++) { fun(arr[i]); }
78
- };
79
-
80
- var freeze = Object.freeze || function(obj) { return obj; };
81
- var getPrototypeOf = Object.getPrototypeOf || function(obj) {
82
- return Object.prototype;
83
- };
84
- var getOwnPropertyNames = Object.getOwnPropertyNames ||
85
- function(obj) {
86
- var props = [];
87
- for (var p in obj) { if (hasOwnProperty(obj,p)) { props.push(p); } }
88
- return props;
89
- };
90
- var getOwnPropertyDescriptor = supportsGOPD() ?
91
- Object.getOwnPropertyDescriptor :
92
- function(obj, name) {
93
- return {
94
- value: obj[name],
95
- enumerable: true,
96
- writable: true,
97
- configurable: true
98
- };
99
- };
100
- var defineProperty = supportsDP() ? Object.defineProperty :
101
- function(obj, name, pd) {
102
- obj[name] = pd.value;
103
- };
104
- var defineProperties = Object.defineProperties ||
105
- function(obj, propMap) {
106
- for (var name in propMap) {
107
- if (hasOwnProperty(propMap, name)) {
108
- defineProperty(obj, name, propMap[name]);
109
- }
110
- }
111
- };
112
- var Object_create = Object.create ||
113
- function(proto, propMap) {
114
- var self;
115
- function dummy() {};
116
- dummy.prototype = proto || Object.prototype;
117
- self = new dummy();
118
- if (propMap) {
119
- defineProperties(self, propMap);
120
- }
121
- return self;
122
- };
123
- var getOwnProperties = Object.getOwnProperties ||
124
- function(obj) {
125
- var map = {};
126
- forEach(getOwnPropertyNames(obj), function (name) {
127
- map[name] = getOwnPropertyDescriptor(obj, name);
128
- });
129
- return map;
130
- };
131
-
132
- // end of ES3 - ES5 compatibility functions
133
-
134
- function makeConflictAccessor(name) {
135
- var accessor = function(var_args) {
136
- throw new Error("Conflicting property: "+name);
137
- };
138
- freeze(accessor.prototype);
139
- return freeze(accessor);
140
- };
141
-
142
- function makeRequiredPropDesc(name) {
143
- return freeze({
144
- value: undefined,
145
- enumerable: false,
146
- required: true
147
- });
148
- }
149
-
150
- function makeConflictingPropDesc(name) {
151
- var conflict = makeConflictAccessor(name);
152
- if (SUPPORTS_DEFINEPROP) {
153
- return freeze({
154
- get: conflict,
155
- set: conflict,
156
- enumerable: false,
157
- conflict: true
158
- });
159
- } else {
160
- return freeze({
161
- value: conflict,
162
- enumerable: false,
163
- conflict: true
164
- });
165
- }
166
- }
167
-
168
- /**
169
- * Are x and y not observably distinguishable?
170
- */
171
- function identical(x, y) {
172
- if (x === y) {
173
- // 0 === -0, but they are not identical
174
- return x !== 0 || 1/x === 1/y;
175
- } else {
176
- // NaN !== NaN, but they are identical.
177
- // NaNs are the only non-reflexive value, i.e., if x !== x,
178
- // then x is a NaN.
179
- return x !== x && y !== y;
180
- }
181
- }
182
-
183
- // Note: isSameDesc should return true if both
184
- // desc1 and desc2 represent a 'required' property
185
- // (otherwise two composed required properties would be turned into
186
- // a conflict)
187
- function isSameDesc(desc1, desc2) {
188
- // for conflicting properties, don't compare values because
189
- // the conflicting property values are never equal
190
- if (desc1.conflict && desc2.conflict) {
191
- return true;
192
- } else {
193
- return ( desc1.get === desc2.get
194
- && desc1.set === desc2.set
195
- && identical(desc1.value, desc2.value)
196
- && desc1.enumerable === desc2.enumerable
197
- && desc1.required === desc2.required
198
- && desc1.conflict === desc2.conflict);
199
- }
200
- }
201
-
202
- function freezeAndBind(meth, self) {
203
- return freeze(bindThis(meth, self));
204
- }
205
-
206
- /* makeSet(['foo', ...]) => { foo: true, ...}
207
- *
208
- * makeSet returns an object whose own properties represent a set.
209
- *
210
- * Each string in the names array is added to the set.
211
- *
212
- * To test whether an element is in the set, perform:
213
- * hasOwnProperty(set, element)
214
- */
215
- function makeSet(names) {
216
- var set = {};
217
- forEach(names, function (name) {
218
- set[name] = true;
219
- });
220
- return freeze(set);
221
- }
222
-
223
- // == singleton object to be used as the placeholder for a required
224
- // property ==
225
-
226
- var required = freeze({
227
- toString: function() { return '<Trait.required>'; }
228
- });
229
-
230
- // == The public API methods ==
231
-
232
- /**
233
- * var newTrait = trait({ foo:required, ... })
234
- *
235
- * @param object an object record (in principle an object literal)
236
- * @returns a new trait describing all of the own properties of the object
237
- * (both enumerable and non-enumerable)
238
- *
239
- * As a general rule, 'trait' should be invoked with an object
240
- * literal, since the object merely serves as a record
241
- * descriptor. Both its identity and its prototype chain are
242
- * irrelevant.
243
- *
244
- * Data properties bound to function objects in the argument will be
245
- * flagged as 'method' properties. The prototype of these function
246
- * objects is frozen.
247
- *
248
- * Data properties bound to the 'required' singleton exported by
249
- * this module will be marked as 'required' properties.
250
- *
251
- * The <tt>trait</tt> function is pure if no other code can witness
252
- * the side-effects of freezing the prototypes of the methods. If
253
- * <tt>trait</tt> is invoked with an object literal whose methods
254
- * are represented as in-place anonymous functions, this should
255
- * normally be the case.
256
- */
257
- function trait(obj) {
258
- var map = {};
259
- forEach(getOwnPropertyNames(obj), function (name) {
260
- var pd = getOwnPropertyDescriptor(obj, name);
261
- if (pd.value === required) {
262
- pd = makeRequiredPropDesc(name);
263
- } else if (typeof pd.value === 'function') {
264
- pd.method = true;
265
- if ('prototype' in pd.value) {
266
- freeze(pd.value.prototype);
267
- }
268
- } else {
269
- if (pd.get && pd.get.prototype) { freeze(pd.get.prototype); }
270
- if (pd.set && pd.set.prototype) { freeze(pd.set.prototype); }
271
- }
272
- map[name] = pd;
273
- });
274
- return map;
275
- }
276
-
277
- /**
278
- * var newTrait = compose(trait_1, trait_2, ..., trait_N)
279
- *
280
- * @param trait_i a trait object
281
- * @returns a new trait containing the combined own properties of
282
- * all the trait_i.
283
- *
284
- * If two or more traits have own properties with the same name, the new
285
- * trait will contain a 'conflict' property for that name. 'compose' is
286
- * a commutative and associative operation, and the order of its
287
- * arguments is not significant.
288
- *
289
- * If 'compose' is invoked with < 2 arguments, then:
290
- * compose(trait_1) returns a trait equivalent to trait_1
291
- * compose() returns an empty trait
292
- */
293
- function compose(var_args) {
294
- var traits = slice(arguments, 0);
295
- var newTrait = {};
296
-
297
- forEach(traits, function (trait) {
298
- forEach(getOwnPropertyNames(trait), function (name) {
299
- var pd = trait[name];
300
- if (hasOwnProperty(newTrait, name) &&
301
- !newTrait[name].required) {
302
-
303
- // a non-required property with the same name was previously
304
- // defined this is not a conflict if pd represents a
305
- // 'required' property itself:
306
- if (pd.required) {
307
- return; // skip this property, the required property is
308
- // now present
309
- }
310
-
311
- if (!isSameDesc(newTrait[name], pd)) {
312
- // a distinct, non-required property with the same name
313
- // was previously defined by another trait => mark as
314
- // conflicting property
315
- newTrait[name] = makeConflictingPropDesc(name);
316
- } // else,
317
- // properties are not in conflict if they refer to the same value
318
-
319
- } else {
320
- newTrait[name] = pd;
321
- }
322
- });
323
- });
324
-
325
- return freeze(newTrait);
326
- }
327
-
328
- /* var newTrait = exclude(['name', ...], trait)
329
- *
330
- * @param names a list of strings denoting property names.
331
- * @param trait a trait some properties of which should be excluded.
332
- * @returns a new trait with the same own properties as the original trait,
333
- * except that all property names appearing in the first argument
334
- * are replaced by required property descriptors.
335
- *
336
- * Note: exclude(A, exclude(B,t)) is equivalent to exclude(A U B, t)
337
- */
338
- function exclude(names, trait) {
339
- var exclusions = makeSet(names);
340
- var newTrait = {};
341
-
342
- forEach(getOwnPropertyNames(trait), function (name) {
343
- // required properties are not excluded but ignored
344
- if (!hasOwnProperty(exclusions, name) || trait[name].required) {
345
- newTrait[name] = trait[name];
346
- } else {
347
- // excluded properties are replaced by required properties
348
- newTrait[name] = makeRequiredPropDesc(name);
349
- }
350
- });
351
-
352
- return freeze(newTrait);
353
- }
354
-
355
- /**
356
- * var newTrait = override(trait_1, trait_2, ..., trait_N)
357
- *
358
- * @returns a new trait with all of the combined properties of the
359
- * argument traits. In contrast to 'compose', 'override'
360
- * immediately resolves all conflicts resulting from this
361
- * composition by overriding the properties of later
362
- * traits. Trait priority is from left to right. I.e. the
363
- * properties of the leftmost trait are never overridden.
364
- *
365
- * override is associative:
366
- * override(t1,t2,t3) is equivalent to override(t1, override(t2, t3)) or
367
- * to override(override(t1, t2), t3)
368
- * override is not commutative: override(t1,t2) is not equivalent
369
- * to override(t2,t1)
370
- *
371
- * override() returns an empty trait
372
- * override(trait_1) returns a trait equivalent to trait_1
373
- */
374
- function override(var_args) {
375
- var traits = slice(arguments, 0);
376
- var newTrait = {};
377
- forEach(traits, function (trait) {
378
- forEach(getOwnPropertyNames(trait), function (name) {
379
- var pd = trait[name];
380
- // add this trait's property to the composite trait only if
381
- // - the trait does not yet have this property
382
- // - or, the trait does have the property, but it's a required property
383
- if (!hasOwnProperty(newTrait, name) || newTrait[name].required) {
384
- newTrait[name] = pd;
385
- }
386
- });
387
- });
388
- return freeze(newTrait);
389
- }
390
-
391
- /**
392
- * var newTrait = override(dominantTrait, recessiveTrait)
393
- *
394
- * @returns a new trait with all of the properties of dominantTrait
395
- * and all of the properties of recessiveTrait not in dominantTrait
396
- *
397
- * Note: override is associative:
398
- * override(t1, override(t2, t3)) is equivalent to
399
- * override(override(t1, t2), t3)
400
- */
401
- /*function override(frontT, backT) {
402
- var newTrait = {};
403
- // first copy all of backT's properties into newTrait
404
- forEach(getOwnPropertyNames(backT), function (name) {
405
- newTrait[name] = backT[name];
406
- });
407
- // now override all these properties with frontT's properties
408
- forEach(getOwnPropertyNames(frontT), function (name) {
409
- var pd = frontT[name];
410
- // frontT's required property does not override the provided property
411
- if (!(pd.required && hasOwnProperty(newTrait, name))) {
412
- newTrait[name] = pd;
413
- }
414
- });
415
-
416
- return freeze(newTrait);
417
- }*/
418
-
419
- /**
420
- * var newTrait = rename(map, trait)
421
- *
422
- * @param map an object whose own properties serve as a mapping from
423
- old names to new names.
424
- * @param trait a trait object
425
- * @returns a new trait with the same properties as the original trait,
426
- * except that all properties whose name is an own property
427
- * of map will be renamed to map[name], and a 'required' property
428
- * for name will be added instead.
429
- *
430
- * rename({a: 'b'}, t) eqv compose(exclude(['a'],t),
431
- * { a: { required: true },
432
- * b: t[a] })
433
- *
434
- * For each renamed property, a required property is generated. If
435
- * the map renames two properties to the same name, a conflict is
436
- * generated. If the map renames a property to an existing
437
- * unrenamed property, a conflict is generated.
438
- *
439
- * Note: rename(A, rename(B, t)) is equivalent to rename(\n ->
440
- * A(B(n)), t) Note: rename({...},exclude([...], t)) is not eqv to
441
- * exclude([...],rename({...}, t))
442
- */
443
- function rename(map, trait) {
444
- var renamedTrait = {};
445
- forEach(getOwnPropertyNames(trait), function (name) {
446
- // required props are never renamed
447
- if (hasOwnProperty(map, name) && !trait[name].required) {
448
- var alias = map[name]; // alias defined in map
449
- if (hasOwnProperty(renamedTrait, alias) &&
450
- !renamedTrait[alias].required) {
451
- // could happen if 2 props are mapped to the same alias
452
- renamedTrait[alias] = makeConflictingPropDesc(alias);
453
- } else {
454
- // add the property under an alias
455
- renamedTrait[alias] = trait[name];
456
- }
457
- // add a required property under the original name
458
- // but only if a property under the original name does not exist
459
- // such a prop could exist if an earlier prop in the trait was
460
- // previously aliased to this name
461
- if (!hasOwnProperty(renamedTrait, name)) {
462
- renamedTrait[name] = makeRequiredPropDesc(name);
463
- }
464
- } else { // no alias defined
465
- if (hasOwnProperty(renamedTrait, name)) {
466
- // could happen if another prop was previously aliased to name
467
- if (!trait[name].required) {
468
- renamedTrait[name] = makeConflictingPropDesc(name);
469
- }
470
- // else required property overridden by a previously aliased
471
- // property and otherwise ignored
472
- } else {
473
- renamedTrait[name] = trait[name];
474
- }
475
- }
476
- });
477
-
478
- return freeze(renamedTrait);
479
- }
480
-
481
- /**
482
- * var newTrait = resolve({ oldName: 'newName', excludeName:
483
- * undefined, ... }, trait)
484
- *
485
- * This is a convenience function combining renaming and
486
- * exclusion. It can be implemented as <tt>rename(map,
487
- * exclude(exclusions, trait))</tt> where map is the subset of
488
- * mappings from oldName to newName and exclusions is an array of
489
- * all the keys that map to undefined (or another falsy value).
490
- *
491
- * @param resolutions an object whose own properties serve as a
492
- mapping from old names to new names, or to undefined if
493
- the property should be excluded
494
- * @param trait a trait object
495
- * @returns a resolved trait with the same own properties as the
496
- * original trait.
497
- *
498
- * In a resolved trait, all own properties whose name is an own property
499
- * of resolutions will be renamed to resolutions[name] if it is truthy,
500
- * or their value is changed into a required property descriptor if
501
- * resolutions[name] is falsy.
502
- *
503
- * Note, it's important to _first_ exclude, _then_ rename, since exclude
504
- * and rename are not associative, for example:
505
- * rename({a: 'b'}, exclude(['b'], trait({ a:1,b:2 }))) eqv trait({b:1})
506
- * exclude(['b'], rename({a: 'b'}, trait({ a:1,b:2 }))) eqv
507
- * trait({b:Trait.required})
508
- *
509
- * writing resolve({a:'b', b: undefined},trait({a:1,b:2})) makes it
510
- * clear that what is meant is to simply drop the old 'b' and rename
511
- * 'a' to 'b'
512
- */
513
- function resolve(resolutions, trait) {
514
- var renames = {};
515
- var exclusions = [];
516
- // preprocess renamed and excluded properties
517
- for (var name in resolutions) {
518
- if (hasOwnProperty(resolutions, name)) {
519
- if (resolutions[name]) { // old name -> new name
520
- renames[name] = resolutions[name];
521
- } else { // name -> undefined
522
- exclusions.push(name);
523
- }
524
- }
525
- }
526
- return rename(renames, exclude(exclusions, trait));
527
- }
528
-
529
- /**
530
- * var obj = create(proto, trait)
531
- *
532
- * @param proto denotes the prototype of the completed object
533
- * @param trait a trait object to be turned into a complete object
534
- * @returns an object with all of the properties described by the trait.
535
- * @throws 'Missing required property' the trait still contains a
536
- * required property.
537
- * @throws 'Remaining conflicting property' if the trait still
538
- * contains a conflicting property.
539
- *
540
- * Trait.create is like Object.create, except that it generates
541
- * high-integrity or final objects. In addition to creating a new object
542
- * from a trait, it also ensures that:
543
- * - an exception is thrown if 'trait' still contains required properties
544
- * - an exception is thrown if 'trait' still contains conflicting
545
- * properties
546
- * - the object is and all of its accessor and method properties are frozen
547
- * - the 'this' pseudovariable in all accessors and methods of
548
- * the object is bound to the composed object.
549
- *
550
- * Use Object.create instead of Trait.create if you want to create
551
- * abstract or malleable objects. Keep in mind that for such objects:
552
- * - no exception is thrown if 'trait' still contains required properties
553
- * (the properties are simply dropped from the composite object)
554
- * - no exception is thrown if 'trait' still contains conflicting
555
- * properties (these properties remain as conflicting
556
- * properties in the composite object)
557
- * - neither the object nor its accessor and method properties are frozen
558
- * - the 'this' pseudovariable in all accessors and methods of
559
- * the object is left unbound.
560
- */
561
- function create(proto, trait) {
562
- var self = Object_create(proto);
563
- var properties = {};
564
-
565
- forEach(getOwnPropertyNames(trait), function (name) {
566
- var pd = trait[name];
567
- // check for remaining 'required' properties
568
- // Note: it's OK for the prototype to provide the properties
569
- if (pd.required) {
570
- if (!(name in proto)) {
571
- throw new Error('Missing required property: '+name);
572
- }
573
- } else if (pd.conflict) { // check for remaining conflicting properties
574
- throw new Error('Remaining conflicting property: '+name);
575
- } else if ('value' in pd) { // data property
576
- // freeze all function properties and their prototype
577
- if (pd.method) { // the property is meant to be used as a method
578
- // bind 'this' in trait method to the composite object
579
- properties[name] = {
580
- value: freezeAndBind(pd.value, self),
581
- enumerable: pd.enumerable,
582
- configurable: pd.configurable,
583
- writable: pd.writable
584
- };
585
- } else {
586
- properties[name] = pd;
587
- }
588
- } else { // accessor property
589
- properties[name] = {
590
- get: pd.get ? freezeAndBind(pd.get, self) : undefined,
591
- set: pd.set ? freezeAndBind(pd.set, self) : undefined,
592
- enumerable: pd.enumerable,
593
- configurable: pd.configurable
594
- };
595
- }
596
- });
597
-
598
- defineProperties(self, properties);
599
- return freeze(self);
600
- }
601
-
602
- /** A shorthand for create(Object.prototype, trait({...}), options) */
603
- function object(record, options) {
604
- return create(Object.prototype, trait(record), options);
605
- }
606
-
607
- /**
608
- * Tests whether two traits are equivalent. T1 is equivalent to T2 iff
609
- * both describe the same set of property names and for all property
610
- * names n, T1[n] is equivalent to T2[n]. Two property descriptors are
611
- * equivalent if they have the same value, accessors and attributes.
612
- *
613
- * @return a boolean indicating whether the two argument traits are
614
- * equivalent.
615
- */
616
- function eqv(trait1, trait2) {
617
- var names1 = getOwnPropertyNames(trait1);
618
- var names2 = getOwnPropertyNames(trait2);
619
- var name;
620
- if (names1.length !== names2.length) {
621
- return false;
622
- }
623
- for (var i = 0; i < names1.length; i++) {
624
- name = names1[i];
625
- if (!trait2[name] || !isSameDesc(trait1[name], trait2[name])) {
626
- return false;
627
- }
628
- }
629
- return true;
630
- }
631
-
632
- // if this code is ran in ES3 without an Object.create function, this
633
- // library will define it on Object:
634
- if (!Object.create) {
635
- Object.create = Object_create;
636
- }
637
- // ES5 does not by default provide Object.getOwnProperties
638
- // if it's not defined, the Traits library defines this utility
639
- // function on Object
640
- if(!Object.getOwnProperties) {
641
- Object.getOwnProperties = getOwnProperties;
642
- }
643
-
644
- // expose the public API of this module
645
- function Trait(record) {
646
- // calling Trait as a function creates a new atomic trait
647
- return trait(record);
648
- }
649
- Trait.required = freeze(required);
650
- Trait.compose = freeze(compose);
651
- Trait.resolve = freeze(resolve);
652
- Trait.override = freeze(override);
653
- Trait.create = freeze(create);
654
- Trait.eqv = freeze(eqv);
655
- Trait.object = freeze(object); // not essential, cf. create + trait
656
- return freeze(Trait);
657
-
658
- })();
659
-
660
- if (typeof exports !== "undefined") { // CommonJS module support
661
- exports.Trait = Trait;
662
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "traits",
3
- "version": "0.4.0",
4
- "author": "Tom Van Cutsem",
5
- "main": "./lib/traits",
6
- "directories": "./lib"
7
- }