ee-core 2.11.1 → 4.0.0-beta.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.
Files changed (96) hide show
  1. package/app/application.js +31 -0
  2. package/app/boot.js +81 -0
  3. package/app/dir.js +27 -0
  4. package/app/events.js +56 -0
  5. package/app/index.js +7 -0
  6. package/config/config_loader.js +66 -0
  7. package/config/default_config.js +110 -0
  8. package/config/index.js +21 -83
  9. package/const/channel.js +26 -16
  10. package/const/index.js +0 -4
  11. package/controller/controller_loader.js +78 -0
  12. package/controller/index.js +18 -19
  13. package/core/index.js +6 -5
  14. package/core/{lib/loader → loader}/file_loader.js +39 -156
  15. package/core/utils/index.js +83 -0
  16. package/core/{lib/utils → utils}/timing.js +3 -2
  17. package/cross/cross.js +152 -0
  18. package/cross/index.js +6 -181
  19. package/cross/spawnProcess.js +34 -51
  20. package/electron/app/index.js +38 -54
  21. package/electron/index.js +13 -17
  22. package/electron/window/index.js +260 -65
  23. package/exception/index.js +34 -32
  24. package/html/index.js +7 -10
  25. package/index.js +4 -52
  26. package/jobs/child/app.js +9 -9
  27. package/jobs/child/forkProcess.js +29 -45
  28. package/jobs/child/index.js +13 -10
  29. package/jobs/child-pool/index.js +13 -11
  30. package/jobs/index.js +2 -4
  31. package/loader/index.js +91 -144
  32. package/log/index.js +74 -57
  33. package/log/logger.js +76 -84
  34. package/message/childMessage.js +12 -13
  35. package/message/index.js +7 -16
  36. package/package.json +2 -2
  37. package/ps/index.js +137 -223
  38. package/socket/httpServer.js +46 -43
  39. package/socket/index.js +52 -69
  40. package/socket/ipcServer.js +80 -94
  41. package/socket/socketServer.js +31 -24
  42. package/storage/index.js +5 -37
  43. package/storage/sqliteStorage.js +18 -18
  44. package/utils/extend.js +10 -5
  45. package/utils/helper.js +38 -42
  46. package/utils/index.js +40 -23
  47. package/utils/ip.js +5 -45
  48. package/utils/is.js +107 -141
  49. package/utils/json.js +15 -7
  50. package/utils/pargv.js +5 -1
  51. package/utils/{get-port → port}/index.js +4 -26
  52. package/utils/wrap.js +8 -3
  53. package/addon/index.js +0 -35
  54. package/addon/window/index.js +0 -99
  55. package/bin/tools.js +0 -8
  56. package/config/cache.js +0 -42
  57. package/config/config.default.js +0 -331
  58. package/controller/baseContextClass.js +0 -25
  59. package/core/lib/ee.js +0 -216
  60. package/core/lib/loader/context_loader.js +0 -106
  61. package/core/lib/loader/ee_loader.js +0 -435
  62. package/core/lib/loader/mixin/addon.js +0 -32
  63. package/core/lib/loader/mixin/config.js +0 -130
  64. package/core/lib/loader/mixin/controller.js +0 -125
  65. package/core/lib/loader/mixin/service.js +0 -28
  66. package/core/lib/utils/base_context_class.js +0 -34
  67. package/core/lib/utils/function.js +0 -30
  68. package/core/lib/utils/index.js +0 -133
  69. package/core/lib/utils/sequencify.js +0 -59
  70. package/ee/appLoader.js +0 -48
  71. package/ee/application.js +0 -100
  72. package/ee/baseApp.js +0 -104
  73. package/ee/eeApp.js +0 -409
  74. package/ee/index.js +0 -58
  75. package/electron/window/winState.js +0 -186
  76. package/httpclient/index.js +0 -161
  77. package/jobs/baseJobClass.js +0 -16
  78. package/jobs/renderer/index.js +0 -141
  79. package/jobs/renderer/loadView.js +0 -41
  80. package/jobs/unification.js +0 -64
  81. package/main/index.js +0 -57
  82. package/old-utils/index.js +0 -91
  83. package/services/baseContextClass.js +0 -24
  84. package/services/index.js +0 -41
  85. package/socket/io.js +0 -28
  86. package/storage/jsondb/adapters/Base.js +0 -23
  87. package/storage/jsondb/adapters/FileSync.js +0 -64
  88. package/storage/jsondb/main.js +0 -55
  89. package/storage/jsondbStorage.js +0 -196
  90. package/utils/co.js +0 -237
  91. package/utils/copyto.js +0 -161
  92. package/utils/depd/index.js +0 -538
  93. package/utils/depd/lib/browser/index.js +0 -77
  94. package/utils/get-port/index.d.ts +0 -64
  95. package/utils/time/index.js +0 -20
  96. package/utils/time/ms.js +0 -162
@@ -1,64 +0,0 @@
1
- const Base = require('./Base')
2
- const fs = require('fs')
3
- const Log = require('../../../log')
4
-
5
- class FileSync extends Base {
6
-
7
- constructor(options = {}) {
8
- const { source, isSysDB } = options;
9
- super(source);
10
- this.isSysDB = isSysDB;
11
- }
12
-
13
- read() {
14
- if (fs.existsSync(this.source)) {
15
- // Read database
16
- let data = fs.readFileSync(this.source, {encoding: 'utf8'}).trim();
17
-
18
- // 是否可以正常解析
19
- let canDeserialized = this._canDeserialized(data);
20
- if (!canDeserialized) {
21
- let errMessage = `[ee-core] [storage/jsondb] malformed json in file: ${this.source}\n${data}`;
22
- Log.coreLogger.error(errMessage);
23
-
24
- // 是否文件结尾多一个括号,尝试处理
25
- data = data.trim().slice(0, -1);
26
- canDeserialized = this._canDeserialized(data);
27
- if (canDeserialized) {
28
- // 转换为对象,并写入
29
- const newData = JSON.parse(data);
30
- this._fsWrite(newData);
31
- } else {
32
- // [todo] 重置 system.json ,不处理用户数据
33
- if (this.isSysDB) {
34
- this._fsWrite(this.defaultValue);
35
- }
36
- errMessage = '[ee-core] [storage/jsondb] malformed json that cannot be handled!';
37
- Log.coreLogger.error(errMessage);
38
- }
39
- }
40
- const value = canDeserialized ? this.deserialize(data) : this.defaultValue;
41
- return value;
42
- } else {
43
- // Initialize
44
- this._fsWrite(this.defaultValue);
45
- return this.defaultValue
46
- }
47
- }
48
-
49
- write(data) {
50
- return this._fsWrite(data);
51
- }
52
-
53
- _fsWrite(data) {
54
- const isObject = Object.prototype.toString.call(data) === '[object Object]';
55
- if (!isObject) {
56
- Log.coreLogger.error('[ee-core] [storage/jsondb] Variable is not an object :', data);
57
- return
58
- }
59
-
60
- return fs.writeFileSync(this.source, this.serialize(data), {flag:'w+'})
61
- }
62
- }
63
-
64
- module.exports = FileSync
@@ -1,55 +0,0 @@
1
- const lodash = require('lodash');
2
- const assert = require('assert');
3
- const is = require('is-type-of');
4
- const FileSync = require('./adapters/FileSync');
5
-
6
- class JsonDBMain {
7
-
8
- constructor(options = {}) {
9
- this.opt = options;
10
- }
11
-
12
- create() {
13
- const adapter = new FileSync(this.opt);
14
-
15
- assert(typeof adapter === 'object', 'An adapter must be provided');
16
-
17
- // Create a fresh copy of lodash
18
- const _ = lodash.runInContext()
19
- const db = _.chain({})
20
-
21
- // Add write function to lodash
22
- // Calls save before returning result
23
- _.prototype.write = _.wrap(_.prototype.value, function(func) {
24
- const funcRes = func.apply(this)
25
- return db.write(funcRes)
26
- })
27
-
28
- function plant(state) {
29
- db.__wrapped__ = state
30
- return db
31
- }
32
-
33
- // Expose _ for mixins
34
- db._ = _
35
-
36
- db.read = () => {
37
- const r = adapter.read()
38
- return is.promise(r) ? r.then(plant) : plant(r)
39
- }
40
-
41
- db.write = returnValue => {
42
- const w = adapter.write(db.getState())
43
- return is.promise(w) ? w.then(() => returnValue) : returnValue
44
- }
45
-
46
- db.getState = () => db.__wrapped__
47
-
48
- db.setState = state => plant(state)
49
-
50
- return db.read()
51
- }
52
-
53
- }
54
-
55
- module.exports = JsonDBMain;
@@ -1,196 +0,0 @@
1
- const assert = require('assert');
2
- const fs = require('fs');
3
- const path = require('path');
4
- const JsonDBMain = require('./jsondb/main');
5
- const _ = require('lodash');
6
- const Constants = require('../const');
7
- const Helper = require('../utils/helper');
8
- const Ps = require('../ps');
9
-
10
- class JsondbStorage {
11
- constructor (name, opt = {}) {
12
- assert(name, `db name ${name} Cannot be empty`);
13
-
14
- // 补全文件名
15
- name = this._addExtname(name);
16
- this.name = name;
17
- this.mode = this.getMode(name);
18
- this.storageDir = this._createStorageDir();
19
- this.fileName = this._formatFileName(name);
20
- this.storageKey = Constants.storageKey;
21
-
22
- this.db = this.table();
23
- }
24
-
25
- /**
26
- * 创建 table
27
- */
28
- table() {
29
- const dbFile = this.getFilePath();
30
- const isSysDB = this.isSystemDB();
31
- const opt = {
32
- source: dbFile,
33
- isSysDB: isSysDB
34
- }
35
-
36
- const jdbMain = new JsonDBMain(opt);
37
- const db = jdbMain.create();
38
-
39
- assert(fs.existsSync(dbFile), `error: storage ${dbFile} not exists`);
40
-
41
- return db;
42
- }
43
-
44
- /**
45
- * 补全扩展名
46
- */
47
- _addExtname(name) {
48
- if (path.extname(name) != '.json') {
49
- name += ".json";
50
- }
51
-
52
- return name;
53
- }
54
-
55
- /**
56
- * 创建storage目录
57
- */
58
- _createStorageDir() {
59
- let storageDir = Ps.getStorageDir();
60
-
61
- if (this.mode == 'absolute') {
62
- storageDir = path.dirname(this.name);
63
- }
64
-
65
- if (!fs.existsSync(storageDir)) {
66
- Helper.mkdir(storageDir);
67
- Helper.chmodPath(storageDir, '777');
68
- }
69
-
70
- return storageDir;
71
- }
72
-
73
- /**
74
- * 获取文件名
75
- */
76
- _formatFileName(name) {
77
- let fileName = path.basename(name);
78
- return fileName;
79
- }
80
-
81
- /**
82
- * is system db
83
- */
84
- isSystemDB() {
85
- return (this.name == 'system.json') ? true : false;
86
- }
87
-
88
- /**
89
- * 获取文件绝对路径
90
- */
91
- getFilePath() {
92
- const dbFile = path.join(this.storageDir, this.fileName);
93
- return dbFile;
94
- }
95
-
96
- /**
97
- * 获取file path 模式
98
- */
99
- getMode(name) {
100
- let mode = 'relative';
101
-
102
- // 路径模式
103
- name = name.replace(/[/\\]/g, '/');
104
- if (name.indexOf('/') !== -1) {
105
- const isAbsolute = path.isAbsolute(name);
106
- if (isAbsolute) {
107
- mode = 'absolute';
108
- }
109
- }
110
-
111
- return mode;
112
- }
113
-
114
- /**
115
- * 获取storage目录
116
- */
117
- getStorageDir() {
118
- return this.storageDir;
119
- }
120
-
121
- /**
122
- * 为指定的 name 设置一个对应的值
123
- */
124
- setItem (key, value) {
125
- assert(_.isString(key), `key must be a string`);
126
- assert(key.length != 0, `key cannot be empty`);
127
- assert(!this.storageKey.hasOwnProperty(key), `${key} is not allowed`);
128
-
129
- let cacheKey = this.storageKey.cache;
130
- if (!this.db.has(cacheKey).value()) {
131
- this.db.set(cacheKey, {}).write();
132
- }
133
-
134
- let keyId = cacheKey + "." + key;
135
- this.db
136
- .set(keyId, value)
137
- .write();
138
-
139
- return true;
140
- }
141
-
142
- /**
143
- * 根据指定的名字 name 获取对应的值
144
- */
145
- getItem (key) {
146
- assert(_.isString(key), `key must be a string`);
147
- assert(key.length != 0, `key cannot be empty`);
148
-
149
- let cacheKey = this.storageKey.cache;
150
- let keyId = cacheKey + "." + key;
151
- const data = this.db
152
- .get(keyId)
153
- .value();
154
-
155
- return data;
156
- }
157
-
158
- /**
159
- * 设置config对象key属性的值
160
- */
161
- setConfigItem (key, value) {
162
- assert(_.isString(key), `key must be a string`);
163
- assert(key.length != 0, `key cannot be empty`);
164
- assert(!this.storageKey.hasOwnProperty(key), `${key} is not allowed`);
165
-
166
- let cacheKey = this.storageKey.cacheConfig;
167
- if (!this.db.has(cacheKey).value()) {
168
- this.db.set(cacheKey, {}).write();
169
- }
170
-
171
- let keyId = cacheKey + "." + key;
172
- this.db
173
- .set(keyId, value)
174
- .write();
175
-
176
- return true;
177
- }
178
-
179
- /**
180
- * 获取config对象key属性的值
181
- */
182
- getConfigItem (key) {
183
- assert(_.isString(key), `key must be a string`);
184
- assert(key.length != 0, `key cannot be empty`);
185
-
186
- let cacheKey = this.storageKey.cacheConfig;
187
- let keyId = cacheKey + "." + key;
188
- const data = this.db
189
- .get(keyId)
190
- .value();
191
-
192
- return data;
193
- }
194
- }
195
-
196
- module.exports = JsondbStorage;
package/utils/co.js DELETED
@@ -1,237 +0,0 @@
1
-
2
- /**
3
- * slice() reference.
4
- */
5
-
6
- var slice = Array.prototype.slice;
7
-
8
- /**
9
- * Expose `co`.
10
- */
11
-
12
- module.exports = co['default'] = co.co = co;
13
-
14
- /**
15
- * Wrap the given generator `fn` into a
16
- * function that returns a promise.
17
- * This is a separate function so that
18
- * every `co()` call doesn't create a new,
19
- * unnecessary closure.
20
- *
21
- * @param {GeneratorFunction} fn
22
- * @return {Function}
23
- * @api public
24
- */
25
-
26
- co.wrap = function (fn) {
27
- createPromise.__generatorFunction__ = fn;
28
- return createPromise;
29
- function createPromise() {
30
- return co.call(this, fn.apply(this, arguments));
31
- }
32
- };
33
-
34
- /**
35
- * Execute the generator function or a generator
36
- * and return a promise.
37
- *
38
- * @param {Function} fn
39
- * @return {Promise}
40
- * @api public
41
- */
42
-
43
- function co(gen) {
44
- var ctx = this;
45
- var args = slice.call(arguments, 1)
46
-
47
- // we wrap everything in a promise to avoid promise chaining,
48
- // which leads to memory leak errors.
49
- // see https://github.com/tj/co/issues/180
50
- return new Promise(function(resolve, reject) {
51
- if (typeof gen === 'function') gen = gen.apply(ctx, args);
52
- if (!gen || typeof gen.next !== 'function') return resolve(gen);
53
-
54
- onFulfilled();
55
-
56
- /**
57
- * @param {Mixed} res
58
- * @return {Promise}
59
- * @api private
60
- */
61
-
62
- function onFulfilled(res) {
63
- var ret;
64
- try {
65
- ret = gen.next(res);
66
- } catch (e) {
67
- return reject(e);
68
- }
69
- next(ret);
70
- }
71
-
72
- /**
73
- * @param {Error} err
74
- * @return {Promise}
75
- * @api private
76
- */
77
-
78
- function onRejected(err) {
79
- var ret;
80
- try {
81
- ret = gen.throw(err);
82
- } catch (e) {
83
- return reject(e);
84
- }
85
- next(ret);
86
- }
87
-
88
- /**
89
- * Get the next value in the generator,
90
- * return a promise.
91
- *
92
- * @param {Object} ret
93
- * @return {Promise}
94
- * @api private
95
- */
96
-
97
- function next(ret) {
98
- if (ret.done) return resolve(ret.value);
99
- var value = toPromise.call(ctx, ret.value);
100
- if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
101
- return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
102
- + 'but the following object was passed: "' + String(ret.value) + '"'));
103
- }
104
- });
105
- }
106
-
107
- /**
108
- * Convert a `yield`ed value into a promise.
109
- *
110
- * @param {Mixed} obj
111
- * @return {Promise}
112
- * @api private
113
- */
114
-
115
- function toPromise(obj) {
116
- if (!obj) return obj;
117
- if (isPromise(obj)) return obj;
118
- if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj);
119
- if ('function' == typeof obj) return thunkToPromise.call(this, obj);
120
- if (Array.isArray(obj)) return arrayToPromise.call(this, obj);
121
- if (isObject(obj)) return objectToPromise.call(this, obj);
122
- return obj;
123
- }
124
-
125
- /**
126
- * Convert a thunk to a promise.
127
- *
128
- * @param {Function}
129
- * @return {Promise}
130
- * @api private
131
- */
132
-
133
- function thunkToPromise(fn) {
134
- var ctx = this;
135
- return new Promise(function (resolve, reject) {
136
- fn.call(ctx, function (err, res) {
137
- if (err) return reject(err);
138
- if (arguments.length > 2) res = slice.call(arguments, 1);
139
- resolve(res);
140
- });
141
- });
142
- }
143
-
144
- /**
145
- * Convert an array of "yieldables" to a promise.
146
- * Uses `Promise.all()` internally.
147
- *
148
- * @param {Array} obj
149
- * @return {Promise}
150
- * @api private
151
- */
152
-
153
- function arrayToPromise(obj) {
154
- return Promise.all(obj.map(toPromise, this));
155
- }
156
-
157
- /**
158
- * Convert an object of "yieldables" to a promise.
159
- * Uses `Promise.all()` internally.
160
- *
161
- * @param {Object} obj
162
- * @return {Promise}
163
- * @api private
164
- */
165
-
166
- function objectToPromise(obj){
167
- var results = new obj.constructor();
168
- var keys = Object.keys(obj);
169
- var promises = [];
170
- for (var i = 0; i < keys.length; i++) {
171
- var key = keys[i];
172
- var promise = toPromise.call(this, obj[key]);
173
- if (promise && isPromise(promise)) defer(promise, key);
174
- else results[key] = obj[key];
175
- }
176
- return Promise.all(promises).then(function () {
177
- return results;
178
- });
179
-
180
- function defer(promise, key) {
181
- // predefine the key in the result
182
- results[key] = undefined;
183
- promises.push(promise.then(function (res) {
184
- results[key] = res;
185
- }));
186
- }
187
- }
188
-
189
- /**
190
- * Check if `obj` is a promise.
191
- *
192
- * @param {Object} obj
193
- * @return {Boolean}
194
- * @api private
195
- */
196
-
197
- function isPromise(obj) {
198
- return 'function' == typeof obj.then;
199
- }
200
-
201
- /**
202
- * Check if `obj` is a generator.
203
- *
204
- * @param {Mixed} obj
205
- * @return {Boolean}
206
- * @api private
207
- */
208
-
209
- function isGenerator(obj) {
210
- return 'function' == typeof obj.next && 'function' == typeof obj.throw;
211
- }
212
-
213
- /**
214
- * Check if `obj` is a generator function.
215
- *
216
- * @param {Mixed} obj
217
- * @return {Boolean}
218
- * @api private
219
- */
220
- function isGeneratorFunction(obj) {
221
- var constructor = obj.constructor;
222
- if (!constructor) return false;
223
- if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true;
224
- return isGenerator(constructor.prototype);
225
- }
226
-
227
- /**
228
- * Check for plain object.
229
- *
230
- * @param {Mixed} val
231
- * @return {Boolean}
232
- * @api private
233
- */
234
-
235
- function isObject(val) {
236
- return Object == val.constructor;
237
- }
package/utils/copyto.js DELETED
@@ -1,161 +0,0 @@
1
- /*!
2
- * copy-to - index.js
3
- * Copyright(c) 2014 dead_horse <dead_horse@qq.com>
4
- * MIT Licensed
5
- */
6
-
7
- 'use strict';
8
-
9
- /**
10
- * slice() reference.
11
- */
12
-
13
- var slice = Array.prototype.slice;
14
-
15
- /**
16
- * Expose copy
17
- *
18
- * ```
19
- * copy({foo: 'nar', hello: 'copy'}).to({hello: 'world'});
20
- * copy({foo: 'nar', hello: 'copy'}).toCover({hello: 'world'});
21
- * ```
22
- *
23
- * @param {Object} src
24
- * @return {Copy}
25
- */
26
-
27
- module.exports = Copy;
28
-
29
-
30
- /**
31
- * Copy
32
- * @param {Object} src
33
- * @param {Boolean} withAccess
34
- */
35
-
36
- function Copy(src, withAccess) {
37
- if (!(this instanceof Copy)) return new Copy(src, withAccess);
38
- this.src = src;
39
- this._withAccess = withAccess;
40
- }
41
-
42
- /**
43
- * copy properties include getter and setter
44
- * @param {[type]} val [description]
45
- * @return {[type]} [description]
46
- */
47
-
48
- Copy.prototype.withAccess = function (w) {
49
- this._withAccess = w !== false;
50
- return this;
51
- };
52
-
53
- /**
54
- * pick keys in src
55
- *
56
- * @api: public
57
- */
58
-
59
- Copy.prototype.pick = function(keys) {
60
- if (!Array.isArray(keys)) {
61
- keys = slice.call(arguments);
62
- }
63
- if (keys.length) {
64
- this.keys = keys;
65
- }
66
- return this;
67
- };
68
-
69
- /**
70
- * copy src to target,
71
- * do not cover any property target has
72
- * @param {Object} to
73
- *
74
- * @api: public
75
- */
76
-
77
- Copy.prototype.to = function(to) {
78
- to = to || {};
79
-
80
- if (!this.src) return to;
81
- var keys = this.keys || Object.keys(this.src);
82
-
83
- if (!this._withAccess) {
84
- for (var i = 0; i < keys.length; i++) {
85
- var key = keys[i];
86
- if (to[key] !== undefined) continue;
87
- to[key] = this.src[key];
88
- }
89
- return to;
90
- }
91
-
92
- for (var i = 0; i < keys.length; i++) {
93
- var key = keys[i];
94
- if (!notDefined(to, key)) continue;
95
- var getter = this.src.__lookupGetter__(key);
96
- var setter = this.src.__lookupSetter__(key);
97
- if (getter) to.__defineGetter__(key, getter);
98
- if (setter) to.__defineSetter__(key, setter);
99
-
100
- if (!getter && !setter) {
101
- to[key] = this.src[key];
102
- }
103
- }
104
- return to;
105
- };
106
-
107
- /**
108
- * copy src to target,
109
- * override any property target has
110
- * @param {Object} to
111
- *
112
- * @api: public
113
- */
114
-
115
- Copy.prototype.toCover = function(to) {
116
- var keys = this.keys || Object.keys(this.src);
117
-
118
- for (var i = 0; i < keys.length; i++) {
119
- var key = keys[i];
120
- delete to[key];
121
- var getter = this.src.__lookupGetter__(key);
122
- var setter = this.src.__lookupSetter__(key);
123
- if (getter) to.__defineGetter__(key, getter);
124
- if (setter) to.__defineSetter__(key, setter);
125
-
126
- if (!getter && !setter) {
127
- to[key] = this.src[key];
128
- }
129
- }
130
- };
131
-
132
- Copy.prototype.override = Copy.prototype.toCover;
133
-
134
- /**
135
- * append another object to src
136
- * @param {Obj} obj
137
- * @return {Copy}
138
- */
139
-
140
- Copy.prototype.and = function (obj) {
141
- var src = {};
142
- this.to(src);
143
- this.src = obj;
144
- this.to(src);
145
- this.src = src;
146
-
147
- return this;
148
- };
149
-
150
- /**
151
- * check obj[key] if not defiend
152
- * @param {Object} obj
153
- * @param {String} key
154
- * @return {Boolean}
155
- */
156
-
157
- function notDefined(obj, key) {
158
- return obj[key] === undefined
159
- && obj.__lookupGetter__(key) === undefined
160
- && obj.__lookupSetter__(key) === undefined;
161
- }