bool AJFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (isHostFunction()) return Base::getOwnPropertySlot(exec, propertyName, slot); if (propertyName == exec->propertyNames().prototype) { AJValue* location = getDirectLocation(propertyName); if (!location) { AJObject* prototype = new (exec) AJObject(scopeChain().globalObject()->emptyObjectStructure()); prototype->putDirect(exec->propertyNames().constructor, this, DontEnum); putDirect(exec->propertyNames().prototype, prototype, DontDelete); location = getDirectLocation(propertyName); } slot.setValueSlot(this, location, offsetForLocation(location)); } if (propertyName == exec->propertyNames().arguments) { slot.setCacheableCustom(this, argumentsGetter); return true; } if (propertyName == exec->propertyNames().length) { slot.setCacheableCustom(this, lengthGetter); return true; } if (propertyName == exec->propertyNames().caller) { slot.setCacheableCustom(this, callerGetter); return true; } return Base::getOwnPropertySlot(exec, propertyName, slot); }
bool AJFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (isHostFunction()) return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); if (propertyName == exec->propertyNames().prototype) { PropertySlot slot; getOwnPropertySlot(exec, propertyName, slot); return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); } if (propertyName == exec->propertyNames().arguments) { descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().caller) { descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete); return true; } return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
// ECMA 13.2.2 [[Construct]] ConstructType AJFunction::getConstructData(ConstructData& constructData) { if (isHostFunction()) return ConstructTypeNone; constructData.js.functionExecutable = jsExecutable(); constructData.js.scopeChain = scopeChain().node(); return ConstructTypeJS; }
void AJFunction::markChildren(MarkStack& markStack) { Base::markChildren(markStack); if (!isHostFunction()) { jsExecutable()->markAggregate(markStack); scopeChain().markAggregate(markStack); } }
bool AJFunction::deleteProperty(ExecState* exec, const Identifier& propertyName) { if (isHostFunction()) return Base::deleteProperty(exec, propertyName); if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return false; return Base::deleteProperty(exec, propertyName); }
void AJFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { if (!isHostFunction() && (mode == IncludeDontEnumProperties)) { propertyNames.add(exec->propertyNames().arguments); propertyNames.add(exec->propertyNames().callee); propertyNames.add(exec->propertyNames().caller); propertyNames.add(exec->propertyNames().length); } Base::getOwnPropertyNames(exec, propertyNames, mode); }
void AJFunction::put(ExecState* exec, const Identifier& propertyName, AJValue value, PutPropertySlot& slot) { if (isHostFunction()) { Base::put(exec, propertyName, value, slot); return; } if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return; Base::put(exec, propertyName, value, slot); }
CallType AJFunction::getCallData(CallData& callData) { if (isHostFunction()) { callData.native.function = nativeFunction(); return CallTypeHost; } callData.js.functionExecutable = jsExecutable(); callData.js.scopeChain = scopeChain().node(); return CallTypeJS; }
CallType JSFunction::getCallData(CallData& callData) { #if ENABLE(JIT) if (isHostFunction()) { callData.native.function = nativeFunction(); return CallTypeHost; } #endif callData.js.functionExecutable = jsExecutable(); callData.js.scopeChain = scope().node(); return CallTypeJS; }
void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { if (!isHostFunction() && (mode == IncludeDontEnumProperties)) { // Make sure prototype has been reified. PropertySlot slot; getOwnPropertySlotVirtual(exec, exec->propertyNames().prototype, slot); propertyNames.add(exec->propertyNames().arguments); propertyNames.add(exec->propertyNames().caller); propertyNames.add(exec->propertyNames().length); } Base::getOwnPropertyNames(exec, propertyNames, mode); }
const String JSFunction::calculatedDisplayName(ExecState* exec) { const String explicitName = displayName(exec); if (!explicitName.isEmpty()) return explicitName; const String actualName = name(exec); if (!actualName.isEmpty() || isHostFunction()) return actualName; return jsExecutable()->inferredName().string(); }
JSFunction::~JSFunction() { // JIT code for other functions may have had calls linked directly to the code for this function; these links // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once // this memory is freed and may be reused (potentially for another, different JSFunction). if (!isHostFunction()) { #if ENABLE(JIT_OPTIMIZE_CALL) ASSERT(m_executable); if (jsExecutable()->isGenerated()) jsExecutable()->generatedBytecode().unlinkCallers(); #endif scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too? } }
AJObject* AJFunction::construct(ExecState* exec, const ArgList& args) { ASSERT(!isHostFunction()); Structure* structure; AJValue prototype = get(exec, exec->propertyNames().prototype); if (prototype.isObject()) structure = asObject(prototype)->inheritorID(); else structure = exec->lexicalGlobalObject()->emptyObjectStructure(); AJObject* thisObj = new (exec) AJObject(structure); AJValue result = exec->interpreter()->execute(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot()); if (exec->hadException() || !result.isObject()) return thisObj; return asObject(result); }
bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (isHostFunction()) return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); if (propertyName == exec->propertyNames().prototype) { PropertySlot slot; getOwnPropertySlotVirtual(exec, propertyName, slot); return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); } if (propertyName == exec->propertyNames().arguments) { if (jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); if (!result) { initializeGetterSetterProperty(exec, propertyName, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); ASSERT(result); } return result; } descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().caller) { if (jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); if (!result) { initializeGetterSetterProperty(exec, propertyName, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); ASSERT(result); } return result; } descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete); return true; } return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
JSFunction::~JSFunction() { ASSERT(vptr() == JSGlobalData::jsFunctionVPtr); // JIT code for other functions may have had calls linked directly to the code for this function; these links // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once // this memory is freed and may be reused (potentially for another, different JSFunction). if (!isHostFunction()) { #if ENABLE(JIT_OPTIMIZE_CALL) ASSERT(m_executable); if (jsExecutable()->isGeneratedForCall()) jsExecutable()->generatedBytecodeForCall().unlinkCallers(); if (jsExecutable()->isGeneratedForConstruct()) jsExecutable()->generatedBytecodeForConstruct().unlinkCallers(); #endif } }
// Property access sequence is: // (1) indexed properties, // (2) regular own properties, // (3) named properties (in fact, these shouldn't be on the window, should be on the NPO). bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot) { // (1) First, indexed properties. // Hand off all indexed access to getOwnPropertySlotByIndex, which supports the indexed getter. if (Optional<unsigned> index = parseIndex(propertyName)) return getOwnPropertySlotByIndex(object, state, index.value(), slot); auto* thisObject = jsCast<JSDOMWindow*>(object); auto* frame = thisObject->wrapped().frame(); // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess. String errorMessage; if (!frame || !BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage)) return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, state, propertyName, slot, errorMessage); // FIXME: this need more explanation. // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?) slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints); // (2) Regular own properties. PropertySlot slotCopy = slot; if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot)) { // Detect when we're getting the property 'showModalDialog', this is disabled, and has its original value. bool isShowModalDialogAndShouldHide = propertyName == state->propertyNames().showModalDialog && !DOMWindow::canShowModalDialog(frame) && slot.isValue() && isHostFunction(slot.getValue(state, propertyName), jsDOMWindowInstanceFunctionShowModalDialog); // Unless we're in the showModalDialog special case, we're done. if (!isShowModalDialogAndShouldHide) return true; slot = slotCopy; } #if ENABLE(USER_MESSAGE_HANDLERS) if (propertyName == state->propertyNames().webkit && thisObject->wrapped().shouldHaveWebKitNamespaceForWorld(thisObject->world())) { slot.setCacheableCustom(thisObject, DontDelete | ReadOnly, jsDOMWindowWebKit); return true; } #endif return false; }
const SourceCode* JSFunction::sourceCode() const { if (isHostFunction()) return 0; return &jsExecutable()->source(); }
AJValue AJFunction::call(ExecState* exec, AJValue thisValue, const ArgList& args) { ASSERT(!isHostFunction()); return exec->interpreter()->execute(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot()); }
bool JSFunction::isBuiltinFunction() const { return !isHostFunction() && jsExecutable()->isBuiltinFunction(); }
bool AJFunction::isHostFunctionNonInline() const { return isHostFunction(); }
bool JSFunction::isHostOrBuiltinFunction() const { return isHostFunction() || isBuiltinFunction(); }