1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
10 #include "mozilla/Attributes.h"
15 struct CompartmentFilter
;
18 * Helper for Wrapper::New default options.
20 * Callers of Wrapper::New() who wish to specify a prototype for the created
21 * Wrapper, *MUST* construct a WrapperOptions with a JSContext.
23 class MOZ_STACK_CLASS WrapperOptions
: public ProxyOptions
{
25 WrapperOptions() : ProxyOptions(false), proto_() {}
27 explicit WrapperOptions(JSContext
* cx
) : ProxyOptions(false), proto_() {
31 inline JSObject
* proto() const;
32 WrapperOptions
& setProto(JSObject
* protoArg
) {
39 mozilla::Maybe
<JS::RootedObject
> proto_
;
42 // Base class for proxy handlers that want to forward all operations to an
43 // object stored in the proxy's private slot.
44 class JS_PUBLIC_API ForwardingProxyHandler
: public BaseProxyHandler
{
46 using BaseProxyHandler::BaseProxyHandler
;
48 /* Standard internal methods. */
49 virtual bool getOwnPropertyDescriptor(
50 JSContext
* cx
, JS::HandleObject proxy
, JS::HandleId id
,
51 JS::MutableHandle
<mozilla::Maybe
<JS::PropertyDescriptor
>> desc
)
53 virtual bool defineProperty(JSContext
* cx
, JS::HandleObject proxy
,
55 JS::Handle
<JS::PropertyDescriptor
> desc
,
56 JS::ObjectOpResult
& result
) const override
;
57 virtual bool ownPropertyKeys(JSContext
* cx
, JS::HandleObject proxy
,
58 JS::MutableHandleIdVector props
) const override
;
59 virtual bool delete_(JSContext
* cx
, JS::HandleObject proxy
, JS::HandleId id
,
60 JS::ObjectOpResult
& result
) const override
;
61 virtual bool enumerate(JSContext
* cx
, JS::HandleObject proxy
,
62 JS::MutableHandleIdVector props
) const override
;
63 virtual bool getPrototype(JSContext
* cx
, JS::HandleObject proxy
,
64 JS::MutableHandleObject protop
) const override
;
65 virtual bool setPrototype(JSContext
* cx
, JS::HandleObject proxy
,
66 JS::HandleObject proto
,
67 JS::ObjectOpResult
& result
) const override
;
68 virtual bool getPrototypeIfOrdinary(
69 JSContext
* cx
, JS::HandleObject proxy
, bool* isOrdinary
,
70 JS::MutableHandleObject protop
) const override
;
71 virtual bool setImmutablePrototype(JSContext
* cx
, JS::HandleObject proxy
,
72 bool* succeeded
) const override
;
73 virtual bool preventExtensions(JSContext
* cx
, JS::HandleObject proxy
,
74 JS::ObjectOpResult
& result
) const override
;
75 virtual bool isExtensible(JSContext
* cx
, JS::HandleObject proxy
,
76 bool* extensible
) const override
;
77 virtual bool has(JSContext
* cx
, JS::HandleObject proxy
, JS::HandleId id
,
78 bool* bp
) const override
;
79 virtual bool get(JSContext
* cx
, JS::HandleObject proxy
,
80 JS::HandleValue receiver
, JS::HandleId id
,
81 JS::MutableHandleValue vp
) const override
;
82 virtual bool set(JSContext
* cx
, JS::HandleObject proxy
, JS::HandleId id
,
83 JS::HandleValue v
, JS::HandleValue receiver
,
84 JS::ObjectOpResult
& result
) const override
;
85 virtual bool call(JSContext
* cx
, JS::HandleObject proxy
,
86 const JS::CallArgs
& args
) const override
;
87 virtual bool construct(JSContext
* cx
, JS::HandleObject proxy
,
88 const JS::CallArgs
& args
) const override
;
90 /* SpiderMonkey extensions. */
91 virtual bool hasOwn(JSContext
* cx
, JS::HandleObject proxy
, JS::HandleId id
,
92 bool* bp
) const override
;
93 virtual bool getOwnEnumerablePropertyKeys(
94 JSContext
* cx
, JS::HandleObject proxy
,
95 JS::MutableHandleIdVector props
) const override
;
96 virtual bool nativeCall(JSContext
* cx
, JS::IsAcceptableThis test
,
98 const JS::CallArgs
& args
) const override
;
99 virtual bool getBuiltinClass(JSContext
* cx
, JS::HandleObject proxy
,
100 ESClass
* cls
) const override
;
101 virtual bool isArray(JSContext
* cx
, JS::HandleObject proxy
,
102 JS::IsArrayAnswer
* answer
) const override
;
103 virtual const char* className(JSContext
* cx
,
104 JS::HandleObject proxy
) const override
;
105 virtual JSString
* fun_toString(JSContext
* cx
, JS::HandleObject proxy
,
106 bool isToSource
) const override
;
107 virtual RegExpShared
* regexp_toShared(JSContext
* cx
,
108 JS::HandleObject proxy
) const override
;
109 virtual bool boxedValue_unbox(JSContext
* cx
, JS::HandleObject proxy
,
110 JS::MutableHandleValue vp
) const override
;
111 virtual bool isCallable(JSObject
* obj
) const override
;
112 virtual bool isConstructor(JSObject
* obj
) const override
;
114 // Use the target object for private fields.
115 virtual bool useProxyExpandoObjectForPrivateFields() const override
{
121 * A wrapper is a proxy with a target object to which it generally forwards
122 * operations, but may restrict access to certain operations or augment those
123 * operations in various ways.
125 * A wrapper can be "unwrapped" in C++, exposing the underlying object.
126 * Callers should be careful to avoid unwrapping security wrappers in the wrong
129 * Important: If you add a method implementation here, you probably also need
130 * to add an override in CrossCompartmentWrapper. If you don't, you risk
131 * compartment mismatches. See bug 945826 comment 0.
133 class JS_PUBLIC_API Wrapper
: public ForwardingProxyHandler
{
137 explicit constexpr Wrapper(unsigned aFlags
, bool aHasPrototype
= false,
138 bool aHasSecurityPolicy
= false)
139 : ForwardingProxyHandler(&family
, aHasPrototype
, aHasSecurityPolicy
),
142 virtual bool finalizeInBackground(const JS::Value
& priv
) const override
;
145 * A hook subclasses can override to implement CheckedUnwrapDynamic
146 * behavior. The JSContext represents the "who is trying to unwrap?" Realm.
147 * The JSObject is the wrapper that the caller is trying to unwrap.
149 virtual bool dynamicCheckedUnwrapAllowed(JS::HandleObject obj
,
150 JSContext
* cx
) const {
151 MOZ_ASSERT(hasSecurityPolicy(), "Why are you asking?");
155 using BaseProxyHandler::Action
;
157 enum Flags
{ CROSS_COMPARTMENT
= 1 << 0, LAST_USED_FLAG
= CROSS_COMPARTMENT
};
159 static JSObject
* New(JSContext
* cx
, JSObject
* obj
, const Wrapper
* handler
,
160 const WrapperOptions
& options
= WrapperOptions());
162 static JSObject
* Renew(JSObject
* existing
, JSObject
* obj
,
163 const Wrapper
* handler
);
165 static inline const Wrapper
* wrapperHandler(const JSObject
* wrapper
);
167 static JSObject
* wrappedObject(JSObject
* wrapper
);
169 unsigned flags() const { return mFlags
; }
171 bool isCrossCompartmentWrapper() const {
172 return !!(mFlags
& CROSS_COMPARTMENT
);
175 static const char family
;
176 static const Wrapper singleton
;
177 static const Wrapper singletonWithPrototype
;
179 static JSObject
* const defaultProto
;
182 inline JSObject
* WrapperOptions::proto() const {
183 return proto_
? *proto_
: Wrapper::defaultProto
;
186 /* Base class for all cross compartment wrapper handlers. */
187 class JS_PUBLIC_API CrossCompartmentWrapper
: public Wrapper
{
189 explicit constexpr CrossCompartmentWrapper(unsigned aFlags
,
190 bool aHasPrototype
= false,
191 bool aHasSecurityPolicy
= false)
192 : Wrapper(CROSS_COMPARTMENT
| aFlags
, aHasPrototype
, aHasSecurityPolicy
) {
195 /* Standard internal methods. */
196 virtual bool getOwnPropertyDescriptor(
197 JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
198 JS::MutableHandle
<mozilla::Maybe
<JS::PropertyDescriptor
>> desc
)
200 virtual bool defineProperty(JSContext
* cx
, JS::HandleObject wrapper
,
202 JS::Handle
<JS::PropertyDescriptor
> desc
,
203 JS::ObjectOpResult
& result
) const override
;
204 virtual bool ownPropertyKeys(JSContext
* cx
, JS::HandleObject wrapper
,
205 JS::MutableHandleIdVector props
) const override
;
206 virtual bool delete_(JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
207 JS::ObjectOpResult
& result
) const override
;
208 virtual bool enumerate(JSContext
* cx
, JS::HandleObject proxy
,
209 JS::MutableHandleIdVector props
) const override
;
210 virtual bool getPrototype(JSContext
* cx
, JS::HandleObject proxy
,
211 JS::MutableHandleObject protop
) const override
;
212 virtual bool setPrototype(JSContext
* cx
, JS::HandleObject proxy
,
213 JS::HandleObject proto
,
214 JS::ObjectOpResult
& result
) const override
;
216 virtual bool getPrototypeIfOrdinary(
217 JSContext
* cx
, JS::HandleObject proxy
, bool* isOrdinary
,
218 JS::MutableHandleObject protop
) const override
;
219 virtual bool setImmutablePrototype(JSContext
* cx
, JS::HandleObject proxy
,
220 bool* succeeded
) const override
;
221 virtual bool preventExtensions(JSContext
* cx
, JS::HandleObject wrapper
,
222 JS::ObjectOpResult
& result
) const override
;
223 virtual bool isExtensible(JSContext
* cx
, JS::HandleObject wrapper
,
224 bool* extensible
) const override
;
225 virtual bool has(JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
226 bool* bp
) const override
;
227 virtual bool get(JSContext
* cx
, JS::HandleObject wrapper
,
228 JS::HandleValue receiver
, JS::HandleId id
,
229 JS::MutableHandleValue vp
) const override
;
230 virtual bool set(JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
231 JS::HandleValue v
, JS::HandleValue receiver
,
232 JS::ObjectOpResult
& result
) const override
;
233 virtual bool call(JSContext
* cx
, JS::HandleObject wrapper
,
234 const JS::CallArgs
& args
) const override
;
235 virtual bool construct(JSContext
* cx
, JS::HandleObject wrapper
,
236 const JS::CallArgs
& args
) const override
;
238 /* SpiderMonkey extensions. */
239 virtual bool hasOwn(JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
240 bool* bp
) const override
;
241 virtual bool getOwnEnumerablePropertyKeys(
242 JSContext
* cx
, JS::HandleObject wrapper
,
243 JS::MutableHandleIdVector props
) const override
;
244 virtual bool nativeCall(JSContext
* cx
, JS::IsAcceptableThis test
,
246 const JS::CallArgs
& args
) const override
;
247 virtual const char* className(JSContext
* cx
,
248 JS::HandleObject proxy
) const override
;
249 virtual JSString
* fun_toString(JSContext
* cx
, JS::HandleObject wrapper
,
250 bool isToSource
) const override
;
251 virtual RegExpShared
* regexp_toShared(JSContext
* cx
,
252 JS::HandleObject proxy
) const override
;
253 virtual bool boxedValue_unbox(JSContext
* cx
, JS::HandleObject proxy
,
254 JS::MutableHandleValue vp
) const override
;
256 // Allocate CrossCompartmentWrappers in the nursery.
257 virtual bool canNurseryAllocate() const override
{ return true; }
259 static const CrossCompartmentWrapper singleton
;
260 static const CrossCompartmentWrapper singletonWithPrototype
;
263 class JS_PUBLIC_API OpaqueCrossCompartmentWrapper
264 : public CrossCompartmentWrapper
{
266 explicit constexpr OpaqueCrossCompartmentWrapper()
267 : CrossCompartmentWrapper(0) {}
269 /* Standard internal methods. */
270 virtual bool getOwnPropertyDescriptor(
271 JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
272 JS::MutableHandle
<mozilla::Maybe
<JS::PropertyDescriptor
>> desc
)
274 virtual bool defineProperty(JSContext
* cx
, JS::HandleObject wrapper
,
276 JS::Handle
<JS::PropertyDescriptor
> desc
,
277 JS::ObjectOpResult
& result
) const override
;
278 virtual bool ownPropertyKeys(JSContext
* cx
, JS::HandleObject wrapper
,
279 JS::MutableHandleIdVector props
) const override
;
280 virtual bool delete_(JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
281 JS::ObjectOpResult
& result
) const override
;
282 virtual bool enumerate(JSContext
* cx
, JS::HandleObject proxy
,
283 JS::MutableHandleIdVector props
) const override
;
284 virtual bool getPrototype(JSContext
* cx
, JS::HandleObject wrapper
,
285 JS::MutableHandleObject protop
) const override
;
286 virtual bool setPrototype(JSContext
* cx
, JS::HandleObject wrapper
,
287 JS::HandleObject proto
,
288 JS::ObjectOpResult
& result
) const override
;
289 virtual bool getPrototypeIfOrdinary(
290 JSContext
* cx
, JS::HandleObject wrapper
, bool* isOrdinary
,
291 JS::MutableHandleObject protop
) const override
;
292 virtual bool setImmutablePrototype(JSContext
* cx
, JS::HandleObject wrapper
,
293 bool* succeeded
) const override
;
294 virtual bool preventExtensions(JSContext
* cx
, JS::HandleObject wrapper
,
295 JS::ObjectOpResult
& result
) const override
;
296 virtual bool isExtensible(JSContext
* cx
, JS::HandleObject wrapper
,
297 bool* extensible
) const override
;
298 virtual bool has(JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
299 bool* bp
) const override
;
300 virtual bool get(JSContext
* cx
, JS::HandleObject wrapper
,
301 JS::HandleValue receiver
, JS::HandleId id
,
302 JS::MutableHandleValue vp
) const override
;
303 virtual bool set(JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
304 JS::HandleValue v
, JS::HandleValue receiver
,
305 JS::ObjectOpResult
& result
) const override
;
306 virtual bool call(JSContext
* cx
, JS::HandleObject wrapper
,
307 const JS::CallArgs
& args
) const override
;
308 virtual bool construct(JSContext
* cx
, JS::HandleObject wrapper
,
309 const JS::CallArgs
& args
) const override
;
311 /* SpiderMonkey extensions. */
312 virtual bool hasOwn(JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
313 bool* bp
) const override
;
314 virtual bool getOwnEnumerablePropertyKeys(
315 JSContext
* cx
, JS::HandleObject wrapper
,
316 JS::MutableHandleIdVector props
) const override
;
317 virtual bool getBuiltinClass(JSContext
* cx
, JS::HandleObject wrapper
,
318 ESClass
* cls
) const override
;
319 virtual bool isArray(JSContext
* cx
, JS::HandleObject obj
,
320 JS::IsArrayAnswer
* answer
) const override
;
321 virtual const char* className(JSContext
* cx
,
322 JS::HandleObject wrapper
) const override
;
323 virtual JSString
* fun_toString(JSContext
* cx
, JS::HandleObject proxy
,
324 bool isToSource
) const override
;
326 static const OpaqueCrossCompartmentWrapper singleton
;
330 * Base class for security wrappers. A security wrapper is potentially hiding
331 * all or part of some wrapped object thus SecurityWrapper defaults to denying
332 * access to the wrappee. This is the opposite of Wrapper which tries to be
333 * completely transparent.
335 * NB: Currently, only a few ProxyHandler operations are overridden to deny
336 * access, relying on derived SecurityWrapper to block access when necessary.
338 template <class Base
>
339 class JS_PUBLIC_API SecurityWrapper
: public Base
{
341 explicit constexpr SecurityWrapper(unsigned flags
, bool hasPrototype
= false)
342 : Base(flags
, hasPrototype
, /* hasSecurityPolicy = */ true) {}
344 virtual bool enter(JSContext
* cx
, JS::HandleObject wrapper
, JS::HandleId id
,
345 Wrapper::Action act
, bool mayThrow
,
346 bool* bp
) const override
;
348 virtual bool defineProperty(JSContext
* cx
, JS::HandleObject wrapper
,
350 JS::Handle
<JS::PropertyDescriptor
> desc
,
351 JS::ObjectOpResult
& result
) const override
;
352 virtual bool isExtensible(JSContext
* cx
, JS::HandleObject wrapper
,
353 bool* extensible
) const override
;
354 virtual bool preventExtensions(JSContext
* cx
, JS::HandleObject wrapper
,
355 JS::ObjectOpResult
& result
) const override
;
356 virtual bool setPrototype(JSContext
* cx
, JS::HandleObject proxy
,
357 JS::HandleObject proto
,
358 JS::ObjectOpResult
& result
) const override
;
359 virtual bool setImmutablePrototype(JSContext
* cx
, JS::HandleObject proxy
,
360 bool* succeeded
) const override
;
362 virtual bool nativeCall(JSContext
* cx
, JS::IsAcceptableThis test
,
364 const JS::CallArgs
& args
) const override
;
365 virtual bool getBuiltinClass(JSContext
* cx
, JS::HandleObject wrapper
,
366 ESClass
* cls
) const override
;
367 virtual bool isArray(JSContext
* cx
, JS::HandleObject wrapper
,
368 JS::IsArrayAnswer
* answer
) const override
;
369 virtual RegExpShared
* regexp_toShared(JSContext
* cx
,
370 JS::HandleObject proxy
) const override
;
371 virtual bool boxedValue_unbox(JSContext
* cx
, JS::HandleObject proxy
,
372 JS::MutableHandleValue vp
) const override
;
374 // Allow isCallable and isConstructor. They used to be class-level, and so
375 // could not be guarded against.
378 * Allow our subclasses to select the superclass behavior they want without
379 * needing to specify an exact superclass.
381 typedef Base Permissive
;
382 typedef SecurityWrapper
<Base
> Restrictive
;
385 typedef SecurityWrapper
<CrossCompartmentWrapper
>
386 CrossCompartmentSecurityWrapper
;
388 extern JSObject
* TransparentObjectWrapper(JSContext
* cx
,
389 JS::HandleObject existing
,
390 JS::HandleObject obj
);
392 inline bool IsWrapper(const JSObject
* obj
) {
393 return IsProxy(obj
) && GetProxyHandler(obj
)->family() == &Wrapper::family
;
396 inline bool IsCrossCompartmentWrapper(const JSObject
* obj
) {
397 return IsWrapper(obj
) &&
398 (Wrapper::wrapperHandler(obj
)->flags() & Wrapper::CROSS_COMPARTMENT
);
401 /* static */ inline const Wrapper
* Wrapper::wrapperHandler(
402 const JSObject
* wrapper
) {
403 MOZ_ASSERT(IsWrapper(wrapper
));
404 return static_cast<const Wrapper
*>(GetProxyHandler(wrapper
));
407 // Given a JSObject, returns that object stripped of wrappers. If
408 // stopAtWindowProxy is true, then this returns the WindowProxy if it was
409 // previously wrapped. Otherwise, this returns the first object for which
410 // JSObject::isWrapper returns false.
412 // ExposeToActiveJS is called on wrapper targets to allow gray marking
413 // assertions to work while an incremental GC is in progress, but this means
414 // that this cannot be called from the GC or off the main thread.
415 JS_PUBLIC_API JSObject
* UncheckedUnwrap(JSObject
* obj
,
416 bool stopAtWindowProxy
= true,
417 unsigned* flagsp
= nullptr);
419 // Given a JSObject, returns that object stripped of wrappers, except
420 // WindowProxy wrappers. At each stage, the wrapper has the opportunity to veto
421 // the unwrap. Null is returned if there are security wrappers that can't be
424 // This does a static-only unwrap check: it basically checks whether _all_
425 // globals in the wrapper's source compartment should be able to access the
426 // wrapper target. This won't necessarily return the right thing for the HTML
427 // spec's cross-origin objects (WindowProxy and Location), but is fine to use
428 // when failure to unwrap one of those objects wouldn't be a problem. For
429 // example, if you want to test whether your target object is a specific class
430 // that's not WindowProxy or Location, you can use this.
432 // ExposeToActiveJS is called on wrapper targets to allow gray marking
433 // assertions to work while an incremental GC is in progress, but this means
434 // that this cannot be called from the GC or off the main thread.
435 JS_PUBLIC_API JSObject
* CheckedUnwrapStatic(JSObject
* obj
);
437 // Unwrap only the outermost security wrapper, with the same semantics as
438 // above. This is the checked version of Wrapper::wrappedObject.
439 JS_PUBLIC_API JSObject
* UnwrapOneCheckedStatic(JSObject
* obj
);
441 // Given a JSObject, returns that object stripped of wrappers. At each stage,
442 // the security wrapper has the opportunity to veto the unwrap. If
443 // stopAtWindowProxy is true, then this returns the WindowProxy if it was
444 // previously wrapped. Null is returned if there are security wrappers that
445 // can't be unwrapped.
447 // ExposeToActiveJS is called on wrapper targets to allow gray marking
448 // assertions to work while an incremental GC is in progress, but this means
449 // that this cannot be called from the GC or off the main thread.
451 // The JSContext argument will be used for dynamic checks (needed by WindowProxy
452 // and Location) and should represent the Realm doing the unwrapping. It is not
453 // used to throw exceptions; this function never throws.
455 // This function may be able to GC (and the static analysis definitely thinks it
456 // can), but it still takes a JSObject* argument, because some of its callers
457 // would actually have a bit of a hard time producing a Rooted. And it ends up
458 // having to root internally anyway, because it wants to use the value in a loop
459 // and you can't assign to a HandleObject. What this means is that callers who
460 // plan to use the argument object after they have called this function will
461 // need to root it to avoid hazard failures, even though this function doesn't
463 JS_PUBLIC_API JSObject
* CheckedUnwrapDynamic(JSObject
* obj
, JSContext
* cx
,
464 bool stopAtWindowProxy
= true);
466 // Unwrap only the outermost security wrapper, with the same semantics as
467 // above. This is the checked version of Wrapper::wrappedObject.
468 JS_PUBLIC_API JSObject
* UnwrapOneCheckedDynamic(JS::HandleObject obj
,
470 bool stopAtWindowProxy
= true);
472 // Given a JSObject, returns that object stripped of wrappers. This returns the
473 // WindowProxy if it was previously wrapped.
475 // ExposeToActiveJS is not called on wrapper targets so this can be called from
476 // the GC or off the main thread.
477 JS_PUBLIC_API JSObject
* UncheckedUnwrapWithoutExpose(JSObject
* obj
);
479 void ReportAccessDenied(JSContext
* cx
);
481 JS_PUBLIC_API
void NukeCrossCompartmentWrapper(JSContext
* cx
,
484 // If a cross-compartment wrapper source => target exists, nuke it.
485 JS_PUBLIC_API
void NukeCrossCompartmentWrapperIfExists(JSContext
* cx
,
486 JS::Compartment
* source
,
489 void RemapWrapper(JSContext
* cx
, JSObject
* wobj
, JSObject
* newTarget
);
490 void RemapDeadWrapper(JSContext
* cx
, JS::HandleObject wobj
,
491 JS::HandleObject newTarget
);
493 JS_PUBLIC_API
bool RemapAllWrappersForObject(JSContext
* cx
,
494 JS::HandleObject oldTarget
,
495 JS::HandleObject newTarget
);
497 // API to recompute all cross-compartment wrappers whose source and target
498 // match the given filters.
499 JS_PUBLIC_API
bool RecomputeWrappers(JSContext
* cx
,
500 const CompartmentFilter
& sourceFilter
,
501 const CompartmentFilter
& targetFilter
);
505 #endif /* js_Wrapper_h */