2 This file is part of the WebKit open source project.
3 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
25 #include "JSInjectedScriptHost.h"
27 #include "ExceptionCode.h"
28 #include "InjectedScriptHost.h"
29 #include "JSDOMBinding.h"
30 #include <runtime/Error.h>
31 #include <wtf/GetPtr.h>
37 ASSERT_CLASS_FITS_IN_CELL(JSInjectedScriptHost);
41 #define THUNK_GENERATOR(generator) , generator
43 #define THUNK_GENERATOR(generator)
46 #define INTRINSIC(intrinsic) , intrinsic
48 #define INTRINSIC(intrinsic)
51 static const HashTableValue JSInjectedScriptHostTableValues[] =
53 { "constructor", DontEnum | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsInjectedScriptHostConstructor), (intptr_t)0 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
54 { 0, 0, 0, 0 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) }
57 #undef THUNK_GENERATOR
58 static const HashTable JSInjectedScriptHostTable = { 2, 1, JSInjectedScriptHostTableValues, 0 };
59 /* Hash table for constructor */
61 #define THUNK_GENERATOR(generator) , generator
63 #define THUNK_GENERATOR(generator)
66 #define INTRINSIC(intrinsic) , intrinsic
68 #define INTRINSIC(intrinsic)
71 static const HashTableValue JSInjectedScriptHostConstructorTableValues[] =
73 { 0, 0, 0, 0 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) }
76 #undef THUNK_GENERATOR
77 static const HashTable JSInjectedScriptHostConstructorTable = { 1, 0, JSInjectedScriptHostConstructorTableValues, 0 };
78 const ClassInfo JSInjectedScriptHostConstructor::s_info = { "InjectedScriptHostConstructor", &DOMConstructorObject::s_info, &JSInjectedScriptHostConstructorTable, 0, CREATE_METHOD_TABLE(JSInjectedScriptHostConstructor) };
80 JSInjectedScriptHostConstructor::JSInjectedScriptHostConstructor(Structure* structure, JSDOMGlobalObject* globalObject)
81 : DOMConstructorObject(structure, globalObject)
85 void JSInjectedScriptHostConstructor::finishCreation(ExecState* exec, JSDOMGlobalObject* globalObject)
87 Base::finishCreation(exec->globalData());
88 ASSERT(inherits(&s_info));
89 putDirect(exec->globalData(), exec->propertyNames().prototype, JSInjectedScriptHostPrototype::self(exec, globalObject), DontDelete | ReadOnly);
92 bool JSInjectedScriptHostConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
94 return getStaticValueSlot<JSInjectedScriptHostConstructor, JSDOMWrapper>(exec, &JSInjectedScriptHostConstructorTable, static_cast<JSInjectedScriptHostConstructor*>(cell), propertyName, slot);
97 bool JSInjectedScriptHostConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
99 return getStaticValueDescriptor<JSInjectedScriptHostConstructor, JSDOMWrapper>(exec, &JSInjectedScriptHostConstructorTable, static_cast<JSInjectedScriptHostConstructor*>(object), propertyName, descriptor);
102 /* Hash table for prototype */
104 #define THUNK_GENERATOR(generator) , generator
106 #define THUNK_GENERATOR(generator)
109 #define INTRINSIC(intrinsic) , intrinsic
111 #define INTRINSIC(intrinsic)
114 static const HashTableValue JSInjectedScriptHostPrototypeTableValues[] =
116 { "clearConsoleMessages", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionClearConsoleMessages), (intptr_t)0 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
117 { "evaluate", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionEvaluate), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
118 { "copyText", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionCopyText), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
119 { "inspect", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionInspect), (intptr_t)2 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
120 { "inspectedNode", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionInspectedNode), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
121 { "internalConstructorName", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionInternalConstructorName), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
122 { "isHTMLAllCollection", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionIsHTMLAllCollection), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
123 { "type", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionType), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
124 { "functionLocation", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionFunctionLocation), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
125 { "databaseId", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionDatabaseId), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
126 { "storageId", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionStorageId), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
127 { "didCreateWorker", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionDidCreateWorker), (intptr_t)3 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
128 { "didDestroyWorker", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionDidDestroyWorker), (intptr_t)1 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
129 { "nextWorkerId", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsInjectedScriptHostPrototypeFunctionNextWorkerId), (intptr_t)0 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) },
130 { 0, 0, 0, 0 THUNK_GENERATOR(0) INTRINSIC(DFG::NoIntrinsic) }
133 #undef THUNK_GENERATOR
134 static const HashTable JSInjectedScriptHostPrototypeTable = { 34, 31, JSInjectedScriptHostPrototypeTableValues, 0 };
135 const ClassInfo JSInjectedScriptHostPrototype::s_info = { "InjectedScriptHostPrototype", &JSC::JSNonFinalObject::s_info, &JSInjectedScriptHostPrototypeTable, 0, CREATE_METHOD_TABLE(JSInjectedScriptHostPrototype) };
137 JSObject* JSInjectedScriptHostPrototype::self(ExecState* exec, JSGlobalObject* globalObject)
139 return getDOMPrototype<JSInjectedScriptHost>(exec, globalObject);
142 bool JSInjectedScriptHostPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
144 JSInjectedScriptHostPrototype* thisObject = jsCast<JSInjectedScriptHostPrototype*>(cell);
145 return getStaticFunctionSlot<JSObject>(exec, &JSInjectedScriptHostPrototypeTable, thisObject, propertyName, slot);
148 bool JSInjectedScriptHostPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
150 JSInjectedScriptHostPrototype* thisObject = jsCast<JSInjectedScriptHostPrototype*>(object);
151 return getStaticFunctionDescriptor<JSObject>(exec, &JSInjectedScriptHostPrototypeTable, thisObject, propertyName, descriptor);
154 const ClassInfo JSInjectedScriptHost::s_info = { "InjectedScriptHost", &JSDOMWrapper::s_info, &JSInjectedScriptHostTable, 0 , CREATE_METHOD_TABLE(JSInjectedScriptHost) };
156 JSInjectedScriptHost::JSInjectedScriptHost(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<InjectedScriptHost> impl)
157 : JSDOMWrapper(structure, globalObject)
158 , m_impl(impl.leakRef())
162 void JSInjectedScriptHost::finishCreation(JSGlobalData& globalData)
164 Base::finishCreation(globalData);
165 ASSERT(inherits(&s_info));
168 JSObject* JSInjectedScriptHost::createPrototype(ExecState* exec, JSGlobalObject* globalObject)
170 return JSInjectedScriptHostPrototype::create(exec->globalData(), globalObject, JSInjectedScriptHostPrototype::createStructure(globalObject->globalData(), globalObject, globalObject->objectPrototype()));
173 bool JSInjectedScriptHost::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
175 JSInjectedScriptHost* thisObject = jsCast<JSInjectedScriptHost*>(cell);
176 ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
177 return getStaticValueSlot<JSInjectedScriptHost, Base>(exec, &JSInjectedScriptHostTable, thisObject, propertyName, slot);
180 bool JSInjectedScriptHost::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
182 JSInjectedScriptHost* thisObject = jsCast<JSInjectedScriptHost*>(object);
183 ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
184 return getStaticValueDescriptor<JSInjectedScriptHost, Base>(exec, &JSInjectedScriptHostTable, thisObject, propertyName, descriptor);
187 JSValue jsInjectedScriptHostConstructor(ExecState* exec, JSValue slotBase, const Identifier&)
189 JSInjectedScriptHost* domObject = static_cast<JSInjectedScriptHost*>(asObject(slotBase));
190 return JSInjectedScriptHost::getConstructor(exec, domObject->globalObject());
193 JSValue JSInjectedScriptHost::getConstructor(ExecState* exec, JSGlobalObject* globalObject)
195 return getDOMConstructor<JSInjectedScriptHostConstructor>(exec, static_cast<JSDOMGlobalObject*>(globalObject));
198 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionClearConsoleMessages(ExecState* exec)
200 JSValue thisValue = exec->hostThisValue();
201 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
202 return throwVMTypeError(exec);
203 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
204 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
205 InjectedScriptHost* imp = static_cast<InjectedScriptHost*>(castedThis->impl());
206 imp->clearConsoleMessages();
207 return JSValue::encode(jsUndefined());
210 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionEvaluate(ExecState* exec)
212 JSValue thisValue = exec->hostThisValue();
213 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
214 return throwVMTypeError(exec);
215 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
216 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
217 return JSValue::encode(castedThis->evaluate(exec));
220 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionCopyText(ExecState* exec)
222 JSValue thisValue = exec->hostThisValue();
223 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
224 return throwVMTypeError(exec);
225 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
226 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
227 InjectedScriptHost* imp = static_cast<InjectedScriptHost*>(castedThis->impl());
228 if (exec->argumentCount() < 1)
229 return throwVMError(exec, createTypeError(exec, "Not enough arguments"));
230 const String& text(ustringToString(MAYBE_MISSING_PARAMETER(exec, 0, MissingIsUndefined).isEmpty() ? UString() : MAYBE_MISSING_PARAMETER(exec, 0, MissingIsUndefined).toString(exec)));
231 if (exec->hadException())
232 return JSValue::encode(jsUndefined());
234 return JSValue::encode(jsUndefined());
237 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionInspect(ExecState* exec)
239 JSValue thisValue = exec->hostThisValue();
240 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
241 return throwVMTypeError(exec);
242 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
243 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
244 return JSValue::encode(castedThis->inspect(exec));
247 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionInspectedNode(ExecState* exec)
249 JSValue thisValue = exec->hostThisValue();
250 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
251 return throwVMTypeError(exec);
252 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
253 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
254 return JSValue::encode(castedThis->inspectedNode(exec));
257 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionInternalConstructorName(ExecState* exec)
259 JSValue thisValue = exec->hostThisValue();
260 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
261 return throwVMTypeError(exec);
262 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
263 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
264 return JSValue::encode(castedThis->internalConstructorName(exec));
267 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIsHTMLAllCollection(ExecState* exec)
269 JSValue thisValue = exec->hostThisValue();
270 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
271 return throwVMTypeError(exec);
272 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
273 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
274 return JSValue::encode(castedThis->isHTMLAllCollection(exec));
277 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionType(ExecState* exec)
279 JSValue thisValue = exec->hostThisValue();
280 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
281 return throwVMTypeError(exec);
282 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
283 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
284 return JSValue::encode(castedThis->type(exec));
287 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionFunctionLocation(ExecState* exec)
289 JSValue thisValue = exec->hostThisValue();
290 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
291 return throwVMTypeError(exec);
292 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
293 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
294 return JSValue::encode(castedThis->functionLocation(exec));
297 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionDatabaseId(ExecState* exec)
299 JSValue thisValue = exec->hostThisValue();
300 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
301 return throwVMTypeError(exec);
302 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
303 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
304 return JSValue::encode(castedThis->databaseId(exec));
307 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionStorageId(ExecState* exec)
309 JSValue thisValue = exec->hostThisValue();
310 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
311 return throwVMTypeError(exec);
312 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
313 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
314 return JSValue::encode(castedThis->storageId(exec));
317 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionDidCreateWorker(ExecState* exec)
319 JSValue thisValue = exec->hostThisValue();
320 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
321 return throwVMTypeError(exec);
322 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
323 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
324 InjectedScriptHost* imp = static_cast<InjectedScriptHost*>(castedThis->impl());
325 if (exec->argumentCount() < 3)
326 return throwVMError(exec, createTypeError(exec, "Not enough arguments"));
327 int id(MAYBE_MISSING_PARAMETER(exec, 0, MissingIsUndefined).toInt32(exec));
328 if (exec->hadException())
329 return JSValue::encode(jsUndefined());
330 const String& url(ustringToString(MAYBE_MISSING_PARAMETER(exec, 1, MissingIsUndefined).isEmpty() ? UString() : MAYBE_MISSING_PARAMETER(exec, 1, MissingIsUndefined).toString(exec)));
331 if (exec->hadException())
332 return JSValue::encode(jsUndefined());
333 bool isFakeWorker(MAYBE_MISSING_PARAMETER(exec, 2, MissingIsUndefined).toBoolean(exec));
334 if (exec->hadException())
335 return JSValue::encode(jsUndefined());
336 imp->didCreateWorker(id, url, isFakeWorker);
337 return JSValue::encode(jsUndefined());
340 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionDidDestroyWorker(ExecState* exec)
342 JSValue thisValue = exec->hostThisValue();
343 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
344 return throwVMTypeError(exec);
345 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
346 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
347 InjectedScriptHost* imp = static_cast<InjectedScriptHost*>(castedThis->impl());
348 if (exec->argumentCount() < 1)
349 return throwVMError(exec, createTypeError(exec, "Not enough arguments"));
350 int id(MAYBE_MISSING_PARAMETER(exec, 0, MissingIsUndefined).toInt32(exec));
351 if (exec->hadException())
352 return JSValue::encode(jsUndefined());
353 imp->didDestroyWorker(id);
354 return JSValue::encode(jsUndefined());
357 EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionNextWorkerId(ExecState* exec)
359 JSValue thisValue = exec->hostThisValue();
360 if (!thisValue.inherits(&JSInjectedScriptHost::s_info))
361 return throwVMTypeError(exec);
362 JSInjectedScriptHost* castedThis = static_cast<JSInjectedScriptHost*>(asObject(thisValue));
363 ASSERT_GC_OBJECT_INHERITS(castedThis, &JSInjectedScriptHost::s_info);
364 InjectedScriptHost* imp = static_cast<InjectedScriptHost*>(castedThis->impl());
366 JSC::JSValue result = jsNumber(imp->nextWorkerId());
367 return JSValue::encode(result);
370 static inline bool isObservable(JSInjectedScriptHost* jsInjectedScriptHost)
372 if (jsInjectedScriptHost->hasCustomProperties())
377 bool JSInjectedScriptHostOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
379 JSInjectedScriptHost* jsInjectedScriptHost = static_cast<JSInjectedScriptHost*>(handle.get().asCell());
380 if (!isObservable(jsInjectedScriptHost))
382 UNUSED_PARAM(visitor);
386 void JSInjectedScriptHostOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
388 JSInjectedScriptHost* jsInjectedScriptHost = static_cast<JSInjectedScriptHost*>(handle.get().asCell());
389 DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context);
390 uncacheWrapper(world, jsInjectedScriptHost->impl(), jsInjectedScriptHost);
391 jsInjectedScriptHost->releaseImpl();
394 JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, InjectedScriptHost* impl)
396 return wrap<JSInjectedScriptHost>(exec, globalObject, impl);
399 InjectedScriptHost* toInjectedScriptHost(JSC::JSValue value)
401 return value.inherits(&JSInjectedScriptHost::s_info) ? static_cast<JSInjectedScriptHost*>(asObject(value))->impl() : 0;
406 #endif // ENABLE(INSPECTOR)