当前位置: 首页 > news >正文

[领域]javascript hacking guide 第5部分

mapJSObject的一个重要属性,存放一个对象的所有的属性的入口。要想了解map,就需要打开jsobj.h文件,看里面的定义。

struct JSObject {

JSObjectMap *map;

jsval *slots;

};

很自然的,我们还要找到JSObjectMap的定义,它也在jsobj.h文件中

struct JSObjectMap {

jsrefcount nrefs; /* count of all referencing objects */

JSObjectOps *ops; /* high level object operation vtable */

uint32 nslots; /* length of obj->slots vector */

uint32 freeslot; /* index of next free obj->slots element */

};

在这个定义中,最重要的信息隐含在注释中,第一个是对ops的注释,我们会看到ops其实是一个virtual table。这表示,对象的所有的属性名,都存放在这个vtable中;第2个信息是对nslots的注释,它提及obj->slots其实是一个vector

这如同在告诉我们,我们在定义一个对象的属性时,属性的名称和类型等信息,会通过ops增加到属性表中,属性的值会对应放到slots这个vector中。例如:

var obj = new Object();

obj.a = 5;

那么“a”这个属性的类型是整型的,slots中增加了个新的值5。仔细看去,opsJSObjectOps这个结构体中,我们可以在jsapi.h中找到这个结构体的定义:

struct JSObjectOps {

/* Mandatory non-null function pointer members. */

JSNewObjectMapOp newObjectMap;

JSObjectMapOp destroyObjectMap;

JSLookupPropOp lookupProperty;

JSDefinePropOp defineProperty;

JSPropertyIdOp getProperty;

JSPropertyIdOp setProperty;

JSAttributesOp getAttributes;

JSAttributesOp setAttributes;

JSPropertyIdOp deleteProperty;

JSConvertOp defaultValue;

JSNewEnumerateOp enumerate;

JSCheckAccessIdOp checkAccess;

/* Optionally non-null members start here. */

JSObjectOp thisObject;

JSPropertyRefOp dropProperty;

JSNative call;

JSNative construct;

JSXDRObjectOp xdrObject;

JSHasInstanceOp hasInstance;

JSSetObjectSlotOp setProto;

JSSetObjectSlotOp setParent;

JSMarkOp mark;

JSFinalizeOp clear;

JSGetRequiredSlotOp getRequiredSlot;

JSSetRequiredSlotOp setRequiredSlot;

};

我们可以简单的浏览一下其中的函数指针名称,创建objectmap,定义属性,删除属性,给属性设置值或者获取属性值。。。。闭上眼睛想一想,这其中的函数指针是如此之多,所以一个对象的属性的类型判断(比如是整型还是String还是其他的)或者是属性名或者属性值的存放,都是通过预先定义好的指针函数来完成。

我们甚至可以用一个新的示意图来表示这一切:

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 213.75pt; HEIGHT: 131.25pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png"></imagedata></shape>

我们可以这样去想,有一个table,里面存放对象的属性列表。根据ruby hacking guide的说法,我们可以想像,有一张大的表,存放所有的对象的属性,也可能每个对象有自己的属性表。但,这属于具体实现的范畴,我们只要明白每个对象有属于自己的属性表,对表格中的行或者列进行操作时,是由JSObjectOps这个结构体中的指针函数来完成的就可以了。

/*

* Share proto's map only if it has the same JSObjectOps, and only if

* proto's class has the same private and reserved slots as obj's map

* and class have. We assume that if prototype and object are of the

* same class, they always have the same number of computed reserved

* slots (returned via clasp->reserveSlots); otherwise, prototype and

* object classes must have the same (null or not) reserveSlots hook.

*/

if (proto &&

(map = proto->map)->ops == ops &&

((protoclasp = OBJ_GET_CLASS(cx, proto)) == clasp ||

(!((protoclasp->flags ^ clasp->flags) &

(JSCLASS_HAS_PRIVATE |

(JSCLASS_RESERVED_SLOTS_MASK << JSCLASS_RESERVED_SLOTS_SHIFT))) &&

protoclasp->reserveSlots == clasp->reserveSlots)))

{

/*

* Default parent to the parent of the prototype, which was set from

* the parent of the prototype's constructor.

*/

if (!parent)

parent = OBJ_GET_PARENT(cx, proto);

/* Share the given prototype's map. */

obj->map = js_HoldObjectMap(cx, map);

/* Ensure that obj starts with the minimum slots for clasp. */

nslots = JS_INITIAL_NSLOTS;

} else {

/* Leave parent alone. Allocate a new map for obj. */

map = ops->newObjectMap(cx, 1, ops, clasp, obj);

if (!map)

goto bad;

obj->map = map;

/* Let ops->newObjectMap set nslots so as to reserve slots. */

nslots = map->nslots;

}

Ok,我们在上回书说到有若干的判断条件,就是为了创建一个map,并设置为obj->map的属性――不管是用parent的原型来创建,还是单独创建新的mapif 。。。else 部分),最终都是为了这个目的。

/* Allocate a slots vector, with a -1'st element telling its length. */

newslots = AllocSlots(cx, NULL, nslots);

if (!newslots) {

js_DropObjectMap(cx, obj->map, obj);

obj->map = NULL;

goto bad;

}

/* Set the proto, parent, and class properties. */

newslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);

newslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent);

newslots[JSSLOT_CLASS] = PRIVATE_TO_JSVAL(clasp);

/* Clear above JSSLOT_CLASS so the GC doesn't load uninitialized memory. */

for (i = JSSLOT_CLASS + 1; i < nslots; i++)

newslots[i] = JSVAL_VOID;

/* Store newslots after initializing all of 'em, just in case. */

obj->slots = newslots;

再看newObject中剩余的代码,真是容易多了,既然创建了map来存放属性名了,那么我们就要对应属性名来存放存放初始的属性值了。我们可以看到,每个创建的GC对象,都会被预先设置3个内置的属性,protoparentclass。然后,对剩余的slot,会设置undefinedJSVal_VOID会被解释成Undefined)。

到现在,我们的Global内置对象就已经初步创建完成了。

相关文章:

  • python3.7打包exe后有显示no utf-8_pyinstaller程序打包问题及解决方案
  • 编写安全的Symbian C++游戏代码
  • vs使用mysql操作步骤_技术分享 - 使用VS2013创建并操作SQLite数据库
  • java 内部类_Java内部类(详细整理)
  • GIS 论坛
  • java 内存输出流_java 字节流入门(内存数组流-文件流)
  • Acegi安全系统详解
  • java开发常用jar包_java开发常用jar包
  • java身高体重源代码_java代码规约
  • java 将千分位转为数字_java中千分位转回数值的问题
  • CAS logout问题释疑
  • java配置参数_【java虚拟机】常用的jvm配置参数
  • 在mapControl控件上添加feature要素
  • image失败 安装scikit_安装SciKitImage错误127
  • [领域]javascript hacking guide part 6
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • 【笔记】你不知道的JS读书笔记——Promise
  • 〔开发系列〕一次关于小程序开发的深度总结
  • create-react-app项目添加less配置
  • crontab执行失败的多种原因
  • egg(89)--egg之redis的发布和订阅
  • Java-详解HashMap
  • Python学习之路16-使用API
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • 对象引论
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 记一次和乔布斯合作最难忘的经历
  • 开源SQL-on-Hadoop系统一览
  • 模型微调
  • 区块链分支循环
  • 算法---两个栈实现一个队列
  • 通过几道题目学习二叉搜索树
  • 用Python写一份独特的元宵节祝福
  • 最简单的无缝轮播
  • Java数据解析之JSON
  • # centos7下FFmpeg环境部署记录
  • #QT(一种朴素的计算器实现方法)
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (1)(1.13) SiK无线电高级配置(六)
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (二)fiber的基本认识
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (一)Java算法:二分查找
  • (转)关于pipe()的详细解析
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .Net Winform开发笔记(一)
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .net2005怎么读string形的xml,不是xml文件。
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • [2021 蓝帽杯] One Pointer PHP
  • [28期] lamp兄弟连28期学员手册,请大家务必看一下