Upload
alipay
View
17
Download
3
Tags:
Embed Size (px)
DESCRIPTION
Citation preview
Ñ new Ñ with Ñ function Ñ object Ñ eval
概要�
jsdefs.js� jsparse.js�
jsexec.js�
js.js�
h8ps://github.com/mozilla/narcissus/ h8p://lxr.mozilla.org/mozilla/source/js/narcissus �
Ñ Script Ñ Statements Ñ Statement Ñ Expression Ñ function �
parse �
jsdefs.js�l tokens = ["END", "\n", ";", ...]� ==> { "END": 0, "\n": 1, ... }�
l var END = 0, NEWLINE = 1, SEMICOLON = 2, COMMA = 3, ASSIGN = 4,�HOOK = 5, COLON = 6, CONDITIONAL = 7, OR = 8, AND = 9, BITWISE_OR = 10,�BITWISE_XOR = 11, BITWISE_AND = 12, EQ = 13, NE = 14, STRICT_EQ = 15,�STRICT_NE = 16, LT = 17, LE = 18, GE = 19, GT = 20, LSH = 21, RSH = 22,�URSH = 23, PLUS = 24, MINUS = 25, MUL = 26, ...�
l opTypeNames = { '\n': "NEWLINE", ';': "SEMICOLON", ... }�l keywords = { 'break': 55, 'case', ... }�l assignOps = ['|', '^', '&', '<<', ...]� ==> { "|": 32, "^": 33, ... }�
标识符索引�
三张表格�
全局变量/常量�
jsparse.js�l opPrecedence = {� 'SEMICOLON': 0� 'COMMA': 1,� 'ASSIGN': 2, 'HOOK': 3, 'COLON': 2,� ...�
优先级表�
l opArity = {� 'COMMA': -2,� 'ASSIGN': 2,� 'HOOK': 3,� 'OR': 2,� ...�
操作数表�
jsparse.js -‐‑ 代码结构(1) �var a, i = 100,� v = i + 100;��function t() {� var r = "abc"� function m() {� ...� }� ...� return r;�}��alert(t());�alert(i);�
语句块 Statements�
Script �
function Script(t, x) { var n = Statements(t, x); n.type = SCRIPT; ... } �
function parse(s, f, l) { var t = new Tokenizer(s, f, l); var x = new CompilerContext(false); var n = Script(t, x);
function Statements (t, x) { var n = new Node(t, BLOCK); while (!t.done && t.peek() != RIGHT_CURLY) n.push(Statement(t, x)); ... } �
①�
③�
②�
函数 Function �
jsparse.js -‐‑ 代码结构(2) �var a, i = 100,� v = i + 100;��function t() {��� ...����}��alert(t());�alert(i);�
语句块 Statements�
语句Statement �
function Statements (t, x) { var n = new Node(t, BLOCK); while (!t.done && t.peek() != RIGHT_CURLY) n.push(Statement(t, x)); ... } �
function Statement(t, x) { var i, label, n, n2, ss, 8 = t.get(); switch (8) { case FUNCTION: ... case LEFT_CURLY: ... case IF: n = new Node(t); n.condition = ParenExpression(t, x); n.thenPart = Statement(t, x); n.elsePart = ... default: if (8 == IDENTIFIER) ... ....
①�
②�
jsparse.js -‐‑ 代码结构(3) �var a, i = 100,� v = i + 100;��function t() {��� ...����}��alert(t());�alert(i);�
语句 Statement �
表达式 Expression �
function Statement(t, x) { ... n.condition = ParenExpression(t, x); // switch n.discriminant = n2.caseLabel = // for/for..in n.object = n.setup = // try..catch n2.guard = // other ... n.expression = Expression(t, x); } �
function ParenExpression(t, x) { t.mustMatch(LEFT_PAREN); var n = Expression(t, x); t.mu(RIGHT_PAREN); return n; } �
if (condition) ....�
return x�
①�
②�
jsparse.js – 示例(1) �
var a, i = 100 , v = i + 100;�
①� ③�
Var 语句�
语句语法分隔符�
②�
type:SCRIPT [0]
type:IDENTIFIER value: 'a'
Variables(t, x) �
Expression(t, x, COMMA) �
type:NUMBER value: 100
type:NUMBER value: 100
type:IDENTIFIER value: 'i'
type:VAR value: 'var' [0] [1] [2]
type:IDENTIFIER value: 'i' initializer:
type:IDENTIFIER value: 'v' initializer:
type:+ value: '+' [0] [1]
Statements(t, x)�Script(t, x) �
Statement (t, x)�Expression(t, x, COMMA) �
var a, i = 100 , v = i + 100;�
a, i = 100 , v = i + 100;�
jsparse.js – 示例(2) �
②� ③� ④�
i = 100�操作数1�
操作数2�操作符�
- 读操作数(Operand)�- 读操作符(Operator)� - 检取已有操作数� - 继续读操作数�- 结束读操作符�- 结束读操作数�
①�
用“;”结束 的一般语句�
语句结束符“;”�⑤�“,”运算符�
type:SCRIPT [0]
type:IDENTIFIER value: 'a'
Expression(t, x, COMMA) �
type:NUMBER value: 100
type:NUMBER value: 100
type:IDENTIFIER value: 'i'
type:COMMA value: ',' [0] [1] [2]
type:+ value: '+' [0] [1]
Statements(t, x)�Script(t, x) �
Statement (t, x)�
type:SEMICOLON value: 'a' expression:
type:ASSIGN value: '=' [0] [1]
type:ASSIGN value: '=' [0] [1]
type:IDENTIFIER value: 'i'
type:IDENTIFIER value: ‘v'
a, i = 100 , v = i + 100;�
function Expression(t, x, stop) … while (operators.length) reduce(); return operands.pop(); } �
var a, i = 100,� v = i + 100;��function t(x,y) {� var r = "abc"� function m() {� ...� }� ...� return r;�}��alert(t());�alert(i);�
jsparse.js -‐‑ 代码结构(4) �
函数 Function �
function Script(t, x) { var n = Statements(t, x); n.type = SCRIPT; n.funDecls = x.funDecls; n.varDecls = x.varDecls; return n; } �
声明 Declared�
function parse(s, f, l) { var t = new Tokenizer(s, f, l); var x = new CompilerContext(false); var n = Script(t, x);
function Variables(t, x) { x.varDecls.push(n2); … function FunctionDefinition(t, x, …) var x2 = new CompilerContext(true); f.body = Script(t, x2); … x.funDecls.push(f); …�
编译/语法分析期可决定的上下文�
②�
③�
①�
jsparse.js – 示例(3) �var a, i = 100,� v = i + 100;��function t(x,y) {� var r = "abc"� function m() {� ...� }� ...� return r;�}��alert(t());�alert(i);�
②�
①�
type:SCRIPT - x.funDecls[0] - x.varDecls:[]
type:FUNCTION name:”t” params:[‘x’, ‘y’] body: functionForm:
type:SCRIPT - x2.funDecls[0] - x2.varDecls:[]
type:FUNCTION name:”m” params:[] body: functionForm:
type:SCRIPT - x2.funDecls[0] - x2.varDecls:[]
type:IDENTIFIER value: 'a'
type:IDENTIFIER value: 'i' initializer:
type:IDENTIFIER value: 'v' initializer:
jsparse.js – functionForm�function t() {� ...�}��{� function t() {� ...� }�}��x = function t() {�}�
var DECLARED_FORM = 0, EXPRESSED_FORM = 1, STATEMENT_FORM = 2;
Ñ Script Ñ Statements Ñ Statement Ñ Expression Ñ function �
exec�
语句-‐‑语法树�
type:VAR value: 'var' [0] [1] [2]
type:FUNCTION name:”m” params:[] body: functionForm:
type:IF/FOR/TRY... value: condition: ...
type:... value:... expression:
type:SCRIPT funDecls[0] varDecls:[] [0] [1] [2] [3] ...
type:SCRIPT type:SCRIPT
...
type:NUMBER value: 100
type:IDENTIFIER value: 'i'
...
type:+ value: '+' [0] [1]
执行-‐‑上下文环境�function evaluate(s, f, l) { … var x = ExecutionContext.current; var x2 = new ExecutionContext(GLOBAL_CODE); ExecutionContext.current = x2; execute(parse(s, f, l), x2); …�
function ExecutionContext(type) { this.type = type; } var XCp = ExecutionContext.prototype; ExecutionContext.current = XCp.caller = XCp.callee = null; XCp.scope = {object: global, parent: null}; XCp.thisObject = global; XCp.result = undefined; XCp.target = null; XCp.ecmaStrictMode = false;
var GLOBAL_CODE = 0, EVAL_CODE = 1, FUNCTION_CODE = 2;
var global = { // Value properties. NaN: NaN, Infinity: …, // Function properties. eval: function eval(s) { … Function : … Array : … String: …
②�
①�
jsexec.js – execute() �function execute(n, x) {� switch (n.type) {� case FUNCTION:� case SCRIPT:� case BLOCK:� case IF:� case ASSIGN:� case LT:� case DELETE:� case CALL:� case COMMA:� for (i = 0, j = n.length; i < j; i++)� v = getValue(execute(n[i], x));� break;� ...� ...� return v;�}�
function getValue(v) {� if (v instanceof Reference) {� ...� return v.base[v.propertyName]}� }� return v;�}�
a, i = 100, v = i + 100;�
jsexec.js – IDENTIFIER�
case IDENTIFIER:� for (s = x.scope; s; s = s.parent) {� if (n.value in s.object)� break;� }� v = new Reference(s && s.object, n.value, n);� break;�
jsexec.js – new �case NEW:�case NEW_WITH_ARGS:� r = execute(n[0], x);� f = getValue(r);� if (n.type == NEW) {� a = {};� a.length = 0;� } else {� a = execute(n[1], x);� }� if (isPrimitive(f) || typeof f.__construct__ != "function") {� throw new TypeError(r + " is not a constructor",� n[0].filename, n[0].lineno);� }� v = f.__construct__(a, x);� break;�
funtion Function() { }��// FOp: FunctionObject.prototype�FOp.__construct__ = function(a,x) {� var o = {}, p = this.prototype;� o.__proto__ = p;� var v = this.__call__(o, a, x);� if (isObject(v)) return v;� return o; �}�
jsexec.js – with �
case WITH:� r = execute(n.object, x);� t = toObject(getValue(r), r, n.object);� x.scope = {object: t, parent: x.scope};� try {� execute(n.body, x);� } finally {� x.scope = x.scope.parent;� }� break;�
jsexec.js – Object/Func.�
var global = {� ...� Object: Object,� Function: function Function(dummy) {� var p = "", b = "", n = arguments.length;� ...�� var f = FunctionDefinition(..., STATEMENT_FORM);� var s = {object: global, parent: null};� return new FunctionObject(f, s);� },�
function FunctionObject(node, scope) {� this.node = node;� this.scope = scope;� this.length = node.params;� var proto = {};� this.prototype = proto;� proto.constructor = this;�}�
jsexec.js – Function. � switch (n.type) {� case FUNCTION:� if (n.functionForm != DECLARED_FORM) {� if (!n.name || n.functionForm == STATEMENT_FORM) {� v = new FunctionObject(n, x.scope);� if (n.functionForm == STATEMENT_FORM)� x.scope.object[n.name] = v;� } else {� x.scope = {object: {}, parent: x.scope};� try {� v = new FunctionObject(n, x.scope);� x.scope.object[n.name] = v;� } finally {� x.scope = x.scope.parent;� }� }� }� break;�
jsexec.js – eval �var global = {� eval: function eval(s) {� if (typeof s != "string") return s;� var x = ExecutionContext.current;� var x2 = new ExecutionContext(EVAL_CODE);� x2.thisObject = x.thisObject;� x2.caller = x.caller;� x2.callee = x.callee;� x2.scope = x.scope;� ExecutionContext.current = x2;� try {� execute(parse(s), x2);� ...�
{ END. �