📄 function.cpp
字号:
// -*- c-basic-offset: 2 -*-/* * This file is part of the KDE libraries * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) * Copyright (C) 2003 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */#include "function.h"#include "internal.h"#include "function_object.h"#include "lexer.h"#include "nodes.h"#include "operations.h"#include "debugger.h"#include "context.h"#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <assert.h>#include <string.h>using namespace KJS;// ----------------------------- FunctionImp ----------------------------------const ClassInfo FunctionImp::info = {"Function", &InternalFunctionImp::info, 0, 0};namespace KJS { class Parameter { public: Parameter(const Identifier &n) : name(n), next(0L) { } ~Parameter() { delete next; } Identifier name; Parameter *next; };};FunctionImp::FunctionImp(ExecState *exec, const Identifier &n) : InternalFunctionImp( static_cast<FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp()) ), param(0L), ident(n){}FunctionImp::~FunctionImp(){ delete param;}bool FunctionImp::implementsCall() const{ return true;}Value FunctionImp::call(ExecState *exec, Object &thisObj, const List &args){ Object &globalObj = exec->dynamicInterpreter()->globalObject(); Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger(); int sid = -1; int lineno = -1; if (dbg) { if (inherits(&DeclaredFunctionImp::info)) { sid = static_cast<DeclaredFunctionImp*>(this)->body->sourceId(); lineno = static_cast<DeclaredFunctionImp*>(this)->body->firstLine(); } Object func(this); bool cont = dbg->callEvent(exec,sid,lineno,func,args); if (!cont) { dbg->imp()->abort(); return Undefined(); } } // enter a new execution context ContextImp ctx(globalObj, exec->dynamicInterpreter()->imp(), thisObj, codeType(), exec->context().imp(), this, &args); ExecState newExec(exec->dynamicInterpreter(), &ctx); newExec.setException(exec->exception()); // could be null // assign user supplied arguments to parameters processParameters(&newExec, args); // add variable declarations (initialized to undefined) processVarDecls(&newExec); Completion comp = execute(&newExec); // if an exception occured, propogate it back to the previous execution object if (newExec.hadException()) exec->setException(newExec.exception());#ifdef KJS_VERBOSE if (comp.complType() == Throw) printInfo(exec,"throwing", comp.value()); else if (comp.complType() == ReturnValue) printInfo(exec,"returning", comp.value()); else fprintf(stderr, "returning: undefined\n");#endif if (dbg) { Object func(this); int cont = dbg->returnEvent(exec,sid,lineno,func); if (!cont) { dbg->imp()->abort(); return Undefined(); } } if (comp.complType() == Throw) { exec->setException(comp.value()); return comp.value(); } else if (comp.complType() == ReturnValue) return comp.value(); else return Undefined();}void FunctionImp::addParameter(const Identifier &n){ Parameter **p = ¶m; while (*p) p = &(*p)->next; *p = new Parameter(n);}UString FunctionImp::parameterString() const{ UString s; const Parameter *p = param; while (p) { if (!s.isEmpty()) s += ", "; s += p->name.ustring(); p = p->next; } return s;}// ECMA 10.1.3qvoid FunctionImp::processParameters(ExecState *exec, const List &args){ Object variable = exec->context().imp()->variableObject();#ifdef KJS_VERBOSE fprintf(stderr, "---------------------------------------------------\n" "processing parameters for %s call\n", name().isEmpty() ? "(internal)" : name().ascii());#endif if (param) { ListIterator it = args.begin(); Parameter *p = param; while (p) { if (it != args.end()) {#ifdef KJS_VERBOSE fprintf(stderr, "setting parameter %s ", p->name.ascii()); printInfo(exec,"to", *it);#endif variable.put(exec, p->name, *it); it++; } else variable.put(exec, p->name, Undefined()); p = p->next; } }#ifdef KJS_VERBOSE else { for (int i = 0; i < args.size(); i++) printInfo(exec,"setting argument", args[i]); }#endif}void FunctionImp::processVarDecls(ExecState */*exec*/){}Value FunctionImp::get(ExecState *exec, const Identifier &propertyName) const{ // Find the arguments from the closest context. if (propertyName == argumentsPropertyName) { ContextImp *context = exec->_context; while (context) { if (context->function() == this) return static_cast<ActivationImp *> (context->activationObject())->get(exec, propertyName); context = context->callingContext(); } return Undefined(); } // Compute length of parameters. if (propertyName == lengthPropertyName) { const Parameter * p = param; int count = 0; while (p) { ++count; p = p->next; } return Number(count); } return InternalFunctionImp::get(exec, propertyName);}void FunctionImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr){ if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName) return; InternalFunctionImp::put(exec, propertyName, value, attr);}bool FunctionImp::hasProperty(ExecState *exec, const Identifier &propertyName) const{ if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName) return true; return InternalFunctionImp::hasProperty(exec, propertyName);}bool FunctionImp::deleteProperty(ExecState *exec, const Identifier &propertyName){ if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName) return false; return InternalFunctionImp::deleteProperty(exec, propertyName);}// ------------------------------ DeclaredFunctionImp --------------------------// ### is "Function" correct here?const ClassInfo DeclaredFunctionImp::info = {"Function", &FunctionImp::info, 0, 0};DeclaredFunctionImp::DeclaredFunctionImp(ExecState *exec, const Identifier &n, FunctionBodyNode *b, const ScopeChain &sc) : FunctionImp(exec,n), body(b){ Value protect(this); body->ref(); setScope(sc);}DeclaredFunctionImp::~DeclaredFunctionImp(){ if ( body->deref() ) delete body;}bool DeclaredFunctionImp::implementsConstruct() const{ return true;}// ECMA 13.2.2 [[Construct]]Object DeclaredFunctionImp::construct(ExecState *exec, const List &args){ Object proto; Value p = get(exec,prototypePropertyName); if (p.type() == ObjectType) proto = Object(static_cast<ObjectImp*>(p.imp())); else proto = exec->lexicalInterpreter()->builtinObjectPrototype(); Object obj(new ObjectImp(proto)); Value res = call(exec,obj,args); if (res.type() == ObjectType) return Object::dynamicCast(res); else return obj;}Completion DeclaredFunctionImp::execute(ExecState *exec){ Completion result = body->execute(exec); if (result.complType() == Throw || result.complType() == ReturnValue) return result; return Completion(Normal, Undefined()); // TODO: or ReturnValue ?}void DeclaredFunctionImp::processVarDecls(ExecState *exec){ body->processVarDecls(exec);}// ------------------------------ ArgumentsImp ---------------------------------const ClassInfo ArgumentsImp::info = {"Arguments", 0, 0, 0};// ECMA 10.1.8ArgumentsImp::ArgumentsImp(ExecState *exec, FunctionImp *func)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -