2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #import "JavaScriptCore.h"
29 #if JSC_OBJC_API_ENABLED
31 #import "APICallbackFunction.h"
33 #import "DelayedReleaseScope.h"
35 #import "JSCJSValueInlines.h"
37 #import "JSCellInlines.h"
38 #import "JSContextInternal.h"
39 #import "JSWrapperMap.h"
40 #import "JSValueInternal.h"
41 #import "ObjCCallbackFunction.h"
42 #import "ObjcRuntimeExtras.h"
43 #import <objc/runtime.h>
44 #import <wtf/RetainPtr.h>
46 class CallbackArgument {
48 virtual ~CallbackArgument();
49 virtual void set(NSInvocation *, NSInteger, JSContext *, JSValueRef, JSValueRef*) = 0;
51 OwnPtr<CallbackArgument> m_next;
54 CallbackArgument::~CallbackArgument()
58 class CallbackArgumentBoolean : public CallbackArgument {
59 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
61 bool value = JSValueToBoolean([context JSGlobalContextRef], argument);
62 [invocation setArgument:&value atIndex:argumentNumber];
67 class CallbackArgumentInteger : public CallbackArgument {
68 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
70 T value = (T)JSC::toInt32(JSValueToNumber([context JSGlobalContextRef], argument, exception));
71 [invocation setArgument:&value atIndex:argumentNumber];
76 class CallbackArgumentDouble : public CallbackArgument {
77 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
79 T value = (T)JSValueToNumber([context JSGlobalContextRef], argument, exception);
80 [invocation setArgument:&value atIndex:argumentNumber];
84 class CallbackArgumentJSValue : public CallbackArgument {
85 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
87 JSValue *value = [JSValue valueWithJSValueRef:argument inContext:context];
88 [invocation setArgument:&value atIndex:argumentNumber];
92 class CallbackArgumentId : public CallbackArgument {
93 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
95 id value = valueToObject(context, argument);
96 [invocation setArgument:&value atIndex:argumentNumber];
100 class CallbackArgumentOfClass : public CallbackArgument {
102 CallbackArgumentOfClass(Class cls)
110 virtual ~CallbackArgumentOfClass()
115 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
117 JSGlobalContextRef contextRef = [context JSGlobalContextRef];
119 id object = tryUnwrapObjcObject(contextRef, argument);
120 if (object && [object isKindOfClass:m_class]) {
121 [invocation setArgument:&object atIndex:argumentNumber];
125 if (JSValueIsNull(contextRef, argument) || JSValueIsUndefined(contextRef, argument)) {
127 [invocation setArgument:&object atIndex:argumentNumber];
131 *exception = toRef(JSC::createTypeError(toJS(contextRef), ASCIILiteral("Argument does not match Objective-C Class")));
137 class CallbackArgumentNSNumber : public CallbackArgument {
138 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
140 id value = valueToNumber([context JSGlobalContextRef], argument, exception);
141 [invocation setArgument:&value atIndex:argumentNumber];
145 class CallbackArgumentNSString : public CallbackArgument {
146 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
148 id value = valueToString([context JSGlobalContextRef], argument, exception);
149 [invocation setArgument:&value atIndex:argumentNumber];
153 class CallbackArgumentNSDate : public CallbackArgument {
154 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
156 id value = valueToDate([context JSGlobalContextRef], argument, exception);
157 [invocation setArgument:&value atIndex:argumentNumber];
161 class CallbackArgumentNSArray : public CallbackArgument {
162 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
164 id value = valueToArray([context JSGlobalContextRef], argument, exception);
165 [invocation setArgument:&value atIndex:argumentNumber];
169 class CallbackArgumentNSDictionary : public CallbackArgument {
170 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef* exception) override
172 id value = valueToDictionary([context JSGlobalContextRef], argument, exception);
173 [invocation setArgument:&value atIndex:argumentNumber];
177 class CallbackArgumentStruct : public CallbackArgument {
179 CallbackArgumentStruct(NSInvocation *conversionInvocation, const char* encodedType)
180 : m_conversionInvocation(conversionInvocation)
181 , m_buffer(encodedType)
186 virtual void set(NSInvocation *invocation, NSInteger argumentNumber, JSContext *context, JSValueRef argument, JSValueRef*) override
188 JSValue *value = [JSValue valueWithJSValueRef:argument inContext:context];
189 [m_conversionInvocation invokeWithTarget:value];
190 [m_conversionInvocation getReturnValue:m_buffer];
191 [invocation setArgument:m_buffer atIndex:argumentNumber];
194 RetainPtr<NSInvocation> m_conversionInvocation;
195 StructBuffer m_buffer;
198 class ArgumentTypeDelegate {
200 typedef CallbackArgument* ResultType;
203 static ResultType typeInteger()
205 return new CallbackArgumentInteger<T>;
209 static ResultType typeDouble()
211 return new CallbackArgumentDouble<T>;
214 static ResultType typeBool()
216 return new CallbackArgumentBoolean;
219 static ResultType typeVoid()
221 RELEASE_ASSERT_NOT_REACHED();
225 static ResultType typeId()
227 return new CallbackArgumentId;
230 static ResultType typeOfClass(const char* begin, const char* end)
232 StringRange copy(begin, end);
233 Class cls = objc_getClass(copy);
237 if (cls == [JSValue class])
238 return new CallbackArgumentJSValue;
239 if (cls == [NSString class])
240 return new CallbackArgumentNSString;
241 if (cls == [NSNumber class])
242 return new CallbackArgumentNSNumber;
243 if (cls == [NSDate class])
244 return new CallbackArgumentNSDate;
245 if (cls == [NSArray class])
246 return new CallbackArgumentNSArray;
247 if (cls == [NSDictionary class])
248 return new CallbackArgumentNSDictionary;
250 return new CallbackArgumentOfClass(cls);
253 static ResultType typeBlock(const char*, const char*)
258 static ResultType typeStruct(const char* begin, const char* end)
260 StringRange copy(begin, end);
261 if (NSInvocation *invocation = valueToTypeInvocationFor(copy))
262 return new CallbackArgumentStruct(invocation, copy);
267 class CallbackResult {
269 virtual ~CallbackResult()
273 virtual JSValueRef get(NSInvocation *, JSContext *, JSValueRef*) = 0;
276 class CallbackResultVoid : public CallbackResult {
277 virtual JSValueRef get(NSInvocation *, JSContext *context, JSValueRef*) override
279 return JSValueMakeUndefined([context JSGlobalContextRef]);
283 class CallbackResultId : public CallbackResult {
284 virtual JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
287 [invocation getReturnValue:&value];
288 return objectToValue(context, value);
293 class CallbackResultNumeric : public CallbackResult {
294 virtual JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
297 [invocation getReturnValue:&value];
298 return JSValueMakeNumber([context JSGlobalContextRef], value);
302 class CallbackResultBoolean : public CallbackResult {
303 virtual JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
306 [invocation getReturnValue:&value];
307 return JSValueMakeBoolean([context JSGlobalContextRef], value);
311 class CallbackResultStruct : public CallbackResult {
313 CallbackResultStruct(NSInvocation *conversionInvocation, const char* encodedType)
314 : m_conversionInvocation(conversionInvocation)
315 , m_buffer(encodedType)
320 virtual JSValueRef get(NSInvocation *invocation, JSContext *context, JSValueRef*) override
322 [invocation getReturnValue:m_buffer];
324 [m_conversionInvocation setArgument:m_buffer atIndex:2];
325 [m_conversionInvocation setArgument:&context atIndex:3];
326 [m_conversionInvocation invokeWithTarget:[JSValue class]];
329 [m_conversionInvocation getReturnValue:&value];
330 return valueInternalValue(value);
333 RetainPtr<NSInvocation> m_conversionInvocation;
334 StructBuffer m_buffer;
337 class ResultTypeDelegate {
339 typedef CallbackResult* ResultType;
342 static ResultType typeInteger()
344 return new CallbackResultNumeric<T>;
348 static ResultType typeDouble()
350 return new CallbackResultNumeric<T>;
353 static ResultType typeBool()
355 return new CallbackResultBoolean;
358 static ResultType typeVoid()
360 return new CallbackResultVoid;
363 static ResultType typeId()
365 return new CallbackResultId();
368 static ResultType typeOfClass(const char*, const char*)
370 return new CallbackResultId();
373 static ResultType typeBlock(const char*, const char*)
375 return new CallbackResultId();
378 static ResultType typeStruct(const char* begin, const char* end)
380 StringRange copy(begin, end);
381 if (NSInvocation *invocation = typeToValueInvocationFor(copy))
382 return new CallbackResultStruct(invocation, copy);
389 CallbackInstanceMethod,
396 class ObjCCallbackFunctionImpl {
398 ObjCCallbackFunctionImpl(NSInvocation *invocation, CallbackType type, Class instanceClass, PassOwnPtr<CallbackArgument> arguments, PassOwnPtr<CallbackResult> result)
400 , m_instanceClass([instanceClass retain])
401 , m_invocation(invocation)
402 , m_arguments(arguments)
405 ASSERT((type != CallbackInstanceMethod && type != CallbackInitMethod) || instanceClass);
408 void destroy(Heap& heap)
410 // We need to explicitly release the target since we didn't call
411 // -retainArguments on m_invocation (and we don't want to do so).
412 if (m_type == CallbackBlock || m_type == CallbackClassMethod)
413 heap.releaseSoon(adoptNS([m_invocation.get() target]));
414 [m_instanceClass release];
417 JSValueRef call(JSContext *context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
421 return m_type == CallbackBlock ? [m_invocation target] : nil;
424 id wrappedConstructor()
428 return [m_invocation target];
429 case CallbackInitMethod:
430 return m_instanceClass;
436 bool isConstructible()
438 return !!wrappedBlock() || m_type == CallbackInitMethod;
445 Class m_instanceClass;
446 RetainPtr<NSInvocation> m_invocation;
447 OwnPtr<CallbackArgument> m_arguments;
448 OwnPtr<CallbackResult> m_result;
451 static JSValueRef objCCallbackFunctionCallAsFunction(JSContextRef callerContext, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
453 // Retake the API lock - we need this for a few reasons:
454 // (1) We don't want to support the C-API's confusing drops-locks-once policy - should only drop locks if we can do so recursively.
455 // (2) We're calling some JSC internals that require us to be on the 'inside' - e.g. createTypeError.
456 // (3) We need to be locked (per context would be fine) against conflicting usage of the ObjCCallbackFunction's NSInvocation.
457 JSC::JSLockHolder locker(toJS(callerContext));
459 ObjCCallbackFunction* callback = static_cast<ObjCCallbackFunction*>(toJS(function));
460 ObjCCallbackFunctionImpl* impl = callback->impl();
461 JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(callback->globalObject()->globalExec())];
463 CallbackData callbackData;
466 [context beginCallbackWithData:&callbackData calleeValue:function thisValue:thisObject argumentCount:argumentCount arguments:arguments];
467 result = impl->call(context, thisObject, argumentCount, arguments, exception);
468 if (context.exception)
469 *exception = valueInternalValue(context.exception);
470 [context endCallbackWithData:&callbackData];
475 static JSObjectRef objCCallbackFunctionCallAsConstructor(JSContextRef callerContext, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
477 JSC::JSLockHolder locker(toJS(callerContext));
479 ObjCCallbackFunction* callback = static_cast<ObjCCallbackFunction*>(toJS(constructor));
480 ObjCCallbackFunctionImpl* impl = callback->impl();
481 JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(toJS(callerContext)->lexicalGlobalObject()->globalExec())];
483 CallbackData callbackData;
486 [context beginCallbackWithData:&callbackData calleeValue:constructor thisValue:nil argumentCount:argumentCount arguments:arguments];
487 result = impl->call(context, NULL, argumentCount, arguments, exception);
488 if (context.exception)
489 *exception = valueInternalValue(context.exception);
490 [context endCallbackWithData:&callbackData];
493 JSGlobalContextRef contextRef = [context JSGlobalContextRef];
497 if (!JSValueIsObject(contextRef, result)) {
498 *exception = toRef(JSC::createTypeError(toJS(contextRef), ASCIILiteral("Objective-C blocks called as constructors must return an object.")));
501 return (JSObjectRef)result;
504 const JSC::ClassInfo ObjCCallbackFunction::s_info = { "CallbackFunction", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ObjCCallbackFunction) };
506 ObjCCallbackFunction::ObjCCallbackFunction(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback functionCallback, JSObjectCallAsConstructorCallback constructCallback, PassOwnPtr<ObjCCallbackFunctionImpl> impl)
507 : Base(vm, globalObject->objcCallbackFunctionStructure())
508 , m_functionCallback(functionCallback)
509 , m_constructCallback(constructCallback)
514 ObjCCallbackFunction* ObjCCallbackFunction::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, const String& name, PassOwnPtr<ObjCCallbackFunctionImpl> impl)
516 ObjCCallbackFunction* function = new (NotNull, allocateCell<ObjCCallbackFunction>(vm.heap)) ObjCCallbackFunction(vm, globalObject, objCCallbackFunctionCallAsFunction, objCCallbackFunctionCallAsConstructor, impl);
517 function->finishCreation(vm, name);
521 void ObjCCallbackFunction::destroy(JSCell* cell)
523 ObjCCallbackFunction& function = *jsCast<ObjCCallbackFunction*>(cell);
524 function.impl()->destroy(*Heap::heap(cell));
525 function.~ObjCCallbackFunction();
529 CallType ObjCCallbackFunction::getCallData(JSCell*, CallData& callData)
531 callData.native.function = APICallbackFunction::call<ObjCCallbackFunction>;
535 ConstructType ObjCCallbackFunction::getConstructData(JSCell* cell, ConstructData& constructData)
537 ObjCCallbackFunction* callback = jsCast<ObjCCallbackFunction*>(cell);
538 if (!callback->impl()->isConstructible())
539 return Base::getConstructData(cell, constructData);
540 constructData.native.function = APICallbackFunction::construct<ObjCCallbackFunction>;
541 return ConstructTypeHost;
544 String ObjCCallbackFunctionImpl::name()
546 if (m_type == CallbackInitMethod)
547 return class_getName(m_instanceClass);
548 // FIXME: Maybe we could support having the selector as the name of the non-init
549 // functions to make it a bit more user-friendly from the JS side?
553 JSValueRef ObjCCallbackFunctionImpl::call(JSContext *context, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
555 JSGlobalContextRef contextRef = [context JSGlobalContextRef];
558 size_t firstArgument;
560 case CallbackInitMethod: {
561 RELEASE_ASSERT(!thisObject);
562 target = [m_instanceClass alloc];
563 if (!target || ![target isKindOfClass:m_instanceClass]) {
564 *exception = toRef(JSC::createTypeError(toJS(contextRef), ASCIILiteral("self type check failed for Objective-C instance method")));
565 return JSValueMakeUndefined(contextRef);
567 [m_invocation setTarget:target];
571 case CallbackInstanceMethod: {
572 target = tryUnwrapObjcObject(contextRef, thisObject);
573 if (!target || ![target isKindOfClass:m_instanceClass]) {
574 *exception = toRef(JSC::createTypeError(toJS(contextRef), ASCIILiteral("self type check failed for Objective-C instance method")));
575 return JSValueMakeUndefined(contextRef);
577 [m_invocation setTarget:target];
581 case CallbackClassMethod:
588 size_t argumentNumber = 0;
589 for (CallbackArgument* argument = m_arguments.get(); argument; argument = argument->m_next.get()) {
590 JSValueRef value = argumentNumber < argumentCount ? arguments[argumentNumber] : JSValueMakeUndefined(contextRef);
591 argument->set(m_invocation.get(), argumentNumber + firstArgument, context, value, exception);
593 return JSValueMakeUndefined(contextRef);
597 [m_invocation invoke];
599 JSValueRef result = m_result->get(m_invocation.get(), context, exception);
601 // Balance our call to -alloc with a call to -autorelease. We have to do this after calling -init
602 // because init family methods are allowed to release the allocated object and return something
603 // else in its place.
604 if (m_type == CallbackInitMethod) {
605 id objcResult = tryUnwrapObjcObject(contextRef, result);
607 [objcResult autorelease];
615 static bool blockSignatureContainsClass()
617 static bool containsClass = ^{
618 id block = ^(NSString *string){ return string; };
619 return _Block_has_signature(block) && strstr(_Block_signature(block), "NSString");
621 return containsClass;
624 inline bool skipNumber(const char*& position)
626 if (!isASCIIDigit(*position))
628 while (isASCIIDigit(*++position)) { }
632 static JSObjectRef objCCallbackFunctionForInvocation(JSContext *context, NSInvocation *invocation, CallbackType type, Class instanceClass, const char* signatureWithObjcClasses)
634 if (!signatureWithObjcClasses)
637 const char* position = signatureWithObjcClasses;
639 OwnPtr<CallbackResult> result = adoptPtr(parseObjCType<ResultTypeDelegate>(position));
640 if (!result || !skipNumber(position))
644 case CallbackInitMethod:
645 case CallbackInstanceMethod:
646 case CallbackClassMethod:
647 // Methods are passed two implicit arguments - (id)self, and the selector.
648 if ('@' != *position++ || !skipNumber(position) || ':' != *position++ || !skipNumber(position))
652 // Blocks are passed one implicit argument - the block, of type "@?".
653 if (('@' != *position++) || ('?' != *position++) || !skipNumber(position))
655 // Only allow arguments of type 'id' if the block signature contains the NS type information.
656 if ((!blockSignatureContainsClass() && strchr(position, '@')))
661 OwnPtr<CallbackArgument> arguments = 0;
662 OwnPtr<CallbackArgument>* nextArgument = &arguments;
663 unsigned argumentCount = 0;
665 OwnPtr<CallbackArgument> argument = adoptPtr(parseObjCType<ArgumentTypeDelegate>(position));
666 if (!argument || !skipNumber(position))
669 *nextArgument = argument.release();
670 nextArgument = &(*nextArgument)->m_next;
674 JSC::ExecState* exec = toJS([context JSGlobalContextRef]);
675 JSC::JSLockHolder locker(exec);
676 OwnPtr<JSC::ObjCCallbackFunctionImpl> impl = adoptPtr(new JSC::ObjCCallbackFunctionImpl(invocation, type, instanceClass, arguments.release(), result.release()));
677 return toRef(JSC::ObjCCallbackFunction::create(exec->vm(), exec->lexicalGlobalObject(), impl->name(), impl.release()));
680 JSObjectRef objCCallbackFunctionForInit(JSContext *context, Class cls, Protocol *protocol, SEL sel, const char* types)
682 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:types]];
683 [invocation setSelector:sel];
684 return objCCallbackFunctionForInvocation(context, invocation, CallbackInitMethod, cls, _protocol_getMethodTypeEncoding(protocol, sel, YES, YES));
687 JSObjectRef objCCallbackFunctionForMethod(JSContext *context, Class cls, Protocol *protocol, BOOL isInstanceMethod, SEL sel, const char* types)
689 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:types]];
690 [invocation setSelector:sel];
691 // We need to retain the target Class because m_invocation doesn't retain it
692 // by default (and we don't want it to).
693 if (!isInstanceMethod)
694 [invocation setTarget:[cls retain]];
695 return objCCallbackFunctionForInvocation(context, invocation, isInstanceMethod ? CallbackInstanceMethod : CallbackClassMethod, isInstanceMethod ? cls : nil, _protocol_getMethodTypeEncoding(protocol, sel, YES, isInstanceMethod));
698 JSObjectRef objCCallbackFunctionForBlock(JSContext *context, id target)
700 if (!_Block_has_signature(target))
702 const char* signature = _Block_signature(target);
703 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:signature]];
705 // We don't want to use -retainArguments because that leaks memory. Arguments
706 // would be retained indefinitely between invocations of the callback.
707 // Additionally, we copy the target because we want the block to stick around
708 // until the ObjCCallbackFunctionImpl is destroyed.
709 [invocation setTarget:[target copy]];
711 return objCCallbackFunctionForInvocation(context, invocation, CallbackBlock, nil, signature);
714 id tryUnwrapConstructor(JSObjectRef object)
716 if (!toJS(object)->inherits(JSC::ObjCCallbackFunction::info()))
718 JSC::ObjCCallbackFunctionImpl* impl = static_cast<JSC::ObjCCallbackFunction*>(toJS(object))->impl();
719 if (!impl->isConstructible())
721 return impl->wrappedConstructor();