@workglow/javascript 0.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/task/JavaScriptTask.d.ts +153 -0
- package/dist/task/JavaScriptTask.d.ts.map +1 -0
- package/dist/task/acorn.d.ts +14 -0
- package/dist/task/acorn.d.ts.map +1 -0
- package/dist/task/interpreter.d.ts +17 -0
- package/dist/task/interpreter.d.ts.map +1 -0
- package/dist/task.d.ts +7 -0
- package/dist/task.d.ts.map +1 -0
- package/dist/task.js +4593 -0
- package/dist/task.js.map +12 -0
- package/package.json +44 -0
package/dist/task.js
ADDED
|
@@ -0,0 +1,4593 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined")
|
|
5
|
+
return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// src/task/JavaScriptTask.ts
|
|
10
|
+
import {
|
|
11
|
+
CreateWorkflow,
|
|
12
|
+
Entitlements,
|
|
13
|
+
Task,
|
|
14
|
+
TaskConfigSchema,
|
|
15
|
+
TaskInvalidInputError,
|
|
16
|
+
Workflow
|
|
17
|
+
} from "@workglow/task-graph";
|
|
18
|
+
|
|
19
|
+
// src/task/acorn.js
|
|
20
|
+
var options;
|
|
21
|
+
var input = "";
|
|
22
|
+
var inputLen;
|
|
23
|
+
var sourceFile;
|
|
24
|
+
var parse = function(inpt, opts) {
|
|
25
|
+
input = String(inpt);
|
|
26
|
+
inputLen = input.length;
|
|
27
|
+
setOptions(opts);
|
|
28
|
+
initTokenState();
|
|
29
|
+
return parseTopLevel(options.program);
|
|
30
|
+
};
|
|
31
|
+
var defaultOptions = {
|
|
32
|
+
strictSemicolons: false,
|
|
33
|
+
allowTrailingCommas: true,
|
|
34
|
+
forbidReserved: false,
|
|
35
|
+
allowReturnOutsideFunction: false,
|
|
36
|
+
locations: false,
|
|
37
|
+
onComment: null,
|
|
38
|
+
ranges: false,
|
|
39
|
+
program: null,
|
|
40
|
+
sourceFile: null,
|
|
41
|
+
directSourceFile: null
|
|
42
|
+
};
|
|
43
|
+
function setOptions(opts) {
|
|
44
|
+
options = opts || {};
|
|
45
|
+
for (var opt in defaultOptions) {
|
|
46
|
+
if (!Object.prototype.hasOwnProperty.call(options, opt)) {
|
|
47
|
+
options[opt] = defaultOptions[opt];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
sourceFile = options.sourceFile;
|
|
51
|
+
}
|
|
52
|
+
var getLineInfo = function(input2, offset) {
|
|
53
|
+
for (var line = 1, cur = 0;; ) {
|
|
54
|
+
lineBreak.lastIndex = cur;
|
|
55
|
+
var match = lineBreak.exec(input2);
|
|
56
|
+
if (match && match.index < offset) {
|
|
57
|
+
++line;
|
|
58
|
+
cur = match.index + match[0].length;
|
|
59
|
+
} else {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { line, column: offset - cur };
|
|
64
|
+
};
|
|
65
|
+
var tokPos = 0;
|
|
66
|
+
var tokStart = 0;
|
|
67
|
+
var tokEnd = 0;
|
|
68
|
+
var tokStartLoc;
|
|
69
|
+
var tokEndLoc;
|
|
70
|
+
var tokType;
|
|
71
|
+
var tokVal;
|
|
72
|
+
var tokRegexpAllowed;
|
|
73
|
+
var tokCurLine;
|
|
74
|
+
var tokLineStart;
|
|
75
|
+
var lastStart = 0;
|
|
76
|
+
var lastEnd = 0;
|
|
77
|
+
var lastEndLoc;
|
|
78
|
+
var inFunction;
|
|
79
|
+
var labels;
|
|
80
|
+
var strict;
|
|
81
|
+
function raise(pos, message) {
|
|
82
|
+
var loc = getLineInfo(input, pos);
|
|
83
|
+
message += " (" + loc.line + ":" + loc.column + ")";
|
|
84
|
+
var err = new SyntaxError(message);
|
|
85
|
+
err.pos = pos;
|
|
86
|
+
err.loc = loc;
|
|
87
|
+
err.raisedAt = tokPos;
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
var empty = [];
|
|
91
|
+
var _num = { type: "num" };
|
|
92
|
+
var _regexp = { type: "regexp" };
|
|
93
|
+
var _string = { type: "string" };
|
|
94
|
+
var _name = { type: "name" };
|
|
95
|
+
var _eof = { type: "eof" };
|
|
96
|
+
var _break = { keyword: "break" };
|
|
97
|
+
var _case = { keyword: "case", beforeExpr: true };
|
|
98
|
+
var _catch = { keyword: "catch" };
|
|
99
|
+
var _continue = { keyword: "continue" };
|
|
100
|
+
var _debugger = { keyword: "debugger" };
|
|
101
|
+
var _default = { keyword: "default" };
|
|
102
|
+
var _do = { keyword: "do", isLoop: true };
|
|
103
|
+
var _else = { keyword: "else", beforeExpr: true };
|
|
104
|
+
var _finally = { keyword: "finally" };
|
|
105
|
+
var _for = { keyword: "for", isLoop: true };
|
|
106
|
+
var _function = { keyword: "function" };
|
|
107
|
+
var _if = { keyword: "if" };
|
|
108
|
+
var _return = { keyword: "return", beforeExpr: true };
|
|
109
|
+
var _switch = { keyword: "switch" };
|
|
110
|
+
var _throw = { keyword: "throw", beforeExpr: true };
|
|
111
|
+
var _try = { keyword: "try" };
|
|
112
|
+
var _var = { keyword: "var" };
|
|
113
|
+
var _while = { keyword: "while", isLoop: true };
|
|
114
|
+
var _with = { keyword: "with" };
|
|
115
|
+
var _new = { keyword: "new", beforeExpr: true };
|
|
116
|
+
var _this = { keyword: "this" };
|
|
117
|
+
var _null = { keyword: "null", atomValue: null };
|
|
118
|
+
var _true = { keyword: "true", atomValue: true };
|
|
119
|
+
var _false = { keyword: "false", atomValue: false };
|
|
120
|
+
var _in = { keyword: "in", binop: 7, beforeExpr: true };
|
|
121
|
+
var keywordTypes = {
|
|
122
|
+
break: _break,
|
|
123
|
+
case: _case,
|
|
124
|
+
catch: _catch,
|
|
125
|
+
continue: _continue,
|
|
126
|
+
debugger: _debugger,
|
|
127
|
+
default: _default,
|
|
128
|
+
do: _do,
|
|
129
|
+
else: _else,
|
|
130
|
+
finally: _finally,
|
|
131
|
+
for: _for,
|
|
132
|
+
function: _function,
|
|
133
|
+
if: _if,
|
|
134
|
+
return: _return,
|
|
135
|
+
switch: _switch,
|
|
136
|
+
throw: _throw,
|
|
137
|
+
try: _try,
|
|
138
|
+
var: _var,
|
|
139
|
+
while: _while,
|
|
140
|
+
with: _with,
|
|
141
|
+
null: _null,
|
|
142
|
+
true: _true,
|
|
143
|
+
false: _false,
|
|
144
|
+
new: _new,
|
|
145
|
+
in: _in,
|
|
146
|
+
instanceof: { keyword: "instanceof", binop: 7, beforeExpr: true },
|
|
147
|
+
this: _this,
|
|
148
|
+
typeof: { keyword: "typeof", prefix: true, beforeExpr: true },
|
|
149
|
+
void: { keyword: "void", prefix: true, beforeExpr: true },
|
|
150
|
+
delete: { keyword: "delete", prefix: true, beforeExpr: true }
|
|
151
|
+
};
|
|
152
|
+
var _bracketL = { type: "[", beforeExpr: true };
|
|
153
|
+
var _bracketR = { type: "]" };
|
|
154
|
+
var _braceL = { type: "{", beforeExpr: true };
|
|
155
|
+
var _braceR = { type: "}" };
|
|
156
|
+
var _parenL = { type: "(", beforeExpr: true };
|
|
157
|
+
var _parenR = { type: ")" };
|
|
158
|
+
var _comma = { type: ",", beforeExpr: true };
|
|
159
|
+
var _semi = { type: ";", beforeExpr: true };
|
|
160
|
+
var _colon = { type: ":", beforeExpr: true };
|
|
161
|
+
var _dot = { type: "." };
|
|
162
|
+
var _question = { type: "?", beforeExpr: true };
|
|
163
|
+
var _slash = { binop: 10, beforeExpr: true };
|
|
164
|
+
var _eq = { isAssign: true, beforeExpr: true };
|
|
165
|
+
var _assign = { isAssign: true, beforeExpr: true };
|
|
166
|
+
var _incDec = { postfix: true, prefix: true, isUpdate: true };
|
|
167
|
+
var _prefix = { prefix: true, beforeExpr: true };
|
|
168
|
+
var _logicalOR = { binop: 1, beforeExpr: true };
|
|
169
|
+
var _logicalAND = { binop: 2, beforeExpr: true };
|
|
170
|
+
var _bitwiseOR = { binop: 3, beforeExpr: true };
|
|
171
|
+
var _bitwiseXOR = { binop: 4, beforeExpr: true };
|
|
172
|
+
var _bitwiseAND = { binop: 5, beforeExpr: true };
|
|
173
|
+
var _equality = { binop: 6, beforeExpr: true };
|
|
174
|
+
var _relational = { binop: 7, beforeExpr: true };
|
|
175
|
+
var _bitShift = { binop: 8, beforeExpr: true };
|
|
176
|
+
var _plusMin = { binop: 9, prefix: true, beforeExpr: true };
|
|
177
|
+
var _multiplyModulo = { binop: 10, beforeExpr: true };
|
|
178
|
+
function makePredicate(words) {
|
|
179
|
+
var wordList = words.split(" ");
|
|
180
|
+
var set = Object.create(null);
|
|
181
|
+
for (var i = 0;i < wordList.length; i++) {
|
|
182
|
+
set[wordList[i]] = true;
|
|
183
|
+
}
|
|
184
|
+
return function(str) {
|
|
185
|
+
return set[str] || false;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
var isReservedWord5 = makePredicate("class enum extends super const export import");
|
|
189
|
+
var isStrictReservedWord = makePredicate("implements interface var package private protected public static yield");
|
|
190
|
+
var isStrictBadIdWord = makePredicate("eval arguments");
|
|
191
|
+
var isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this");
|
|
192
|
+
var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
|
|
193
|
+
var nonASCIIidentifierStartChars = "ªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԧԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠࢢ-ࢬऄ-हऽॐक़-ॡॱ-ॷॹ-ॿঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-ళవ-హఽౘౙౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൠൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛰᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤜᥐ-ᥭᥰ-ᥴᦀ-ᦫᧁ-ᧇᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⸯ々-〇〡-〩〱-〵〸-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿌ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚗꚠ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞎꞐ-ꞓꞠ-Ɦꟸ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꪀ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꯀ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ";
|
|
194
|
+
var nonASCIIidentifierChars = "̀-ͯ҃-֑҇-ׇֽֿׁׂׅׄؐ-ؚؠ-ىٲ-ۓۧ-ۨۻ-ۼܰ-݊ࠀ-ࠔࠛ-ࠣࠥ-ࠧࠩ-࠭ࡀ-ࡗࣤ-ࣾऀ-ःऺ-़ा-ॏ॑-ॗॢ-ॣ०-९ঁ-ঃ়া-ৄেৈৗয়-ৠਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑ੦-ੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢ-ૣ૦-૯ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୟ-ୠ୦-୯ஂா-ூெ-ைொ-்ௗ௦-௯ఁ-ఃె-ైొ-్ౕౖౢ-ౣ౦-౯ಂಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢ-ೣ೦-೯ംഃെ-ൈൗൢ-ൣ൦-൯ංඃ්ා-ුූෘ-ෟෲෳิ-ฺเ-ๅ๐-๙ິ-ູ່-ໍ໐-໙༘༙༠-༩༹༵༷ཁ-ཇཱ-྄྆-྇ྍ-ྗྙ-ྼ࿆က-ဩ၀-၉ၧ-ၭၱ-ၴႂ-ႍႏ-ႝ፝-፟ᜎ-ᜐᜠ-ᜰᝀ-ᝐᝲᝳក-ឲ៝០-៩᠋-᠍᠐-᠙ᤠ-ᤫᤰ-᤻ᥑ-ᥭᦰ-ᧀᧈ-ᧉ᧐-᧙ᨀ-ᨕᨠ-ᩓ᩠-᩿᩼-᪉᪐-᪙ᭆ-ᭋ᭐-᭙᭫-᭳᮰-᮹᯦-᯳ᰀ-ᰢ᱀-᱉ᱛ-ᱽ᳐-᳒ᴀ-ᶾḁ-ἕ‿⁀⁔⃐-⃥⃜⃡-⃰ⶁ-ⶖⷠ-ⷿ〡-〨゙゚Ꙁ-ꙭꙴ-꙽ꚟ꛰-꛱ꟸ-ꠀ꠆ꠋꠣ-ꠧꢀ-ꢁꢴ-꣄꣐-꣙ꣳ-ꣷ꤀-꤉ꤦ-꤭ꤰ-ꥅꦀ-ꦃ꦳-꧀ꨀ-ꨧꩀ-ꩁꩌ-ꩍ꩐-꩙ꩻꫠ-ꫩꫲ-ꫳꯀ-ꯡ꯬꯭꯰-꯹ﬠ-ﬨ︀-️︠-︦︳︴﹍-﹏0-9_";
|
|
195
|
+
var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
|
|
196
|
+
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
|
|
197
|
+
var newline = /[\n\r\u2028\u2029]/;
|
|
198
|
+
var lineBreak = /\r\n|[\n\r\u2028\u2029]/g;
|
|
199
|
+
var isIdentifierStart = function(code) {
|
|
200
|
+
if (code < 65)
|
|
201
|
+
return code === 36;
|
|
202
|
+
if (code < 91)
|
|
203
|
+
return true;
|
|
204
|
+
if (code < 97)
|
|
205
|
+
return code === 95;
|
|
206
|
+
if (code < 123)
|
|
207
|
+
return true;
|
|
208
|
+
return code >= 170 && nonASCIIidentifierStart.test(String.fromCharCode(code));
|
|
209
|
+
};
|
|
210
|
+
var isIdentifierChar = function(code) {
|
|
211
|
+
if (code < 48)
|
|
212
|
+
return code === 36;
|
|
213
|
+
if (code < 58)
|
|
214
|
+
return true;
|
|
215
|
+
if (code < 65)
|
|
216
|
+
return false;
|
|
217
|
+
if (code < 91)
|
|
218
|
+
return true;
|
|
219
|
+
if (code < 97)
|
|
220
|
+
return code === 95;
|
|
221
|
+
if (code < 123)
|
|
222
|
+
return true;
|
|
223
|
+
return code >= 170 && nonASCIIidentifier.test(String.fromCharCode(code));
|
|
224
|
+
};
|
|
225
|
+
function line_loc_t() {
|
|
226
|
+
this.line = tokCurLine;
|
|
227
|
+
this.column = tokPos - tokLineStart;
|
|
228
|
+
}
|
|
229
|
+
function initTokenState() {
|
|
230
|
+
tokCurLine = 1;
|
|
231
|
+
tokPos = tokLineStart = 0;
|
|
232
|
+
tokRegexpAllowed = true;
|
|
233
|
+
skipSpace();
|
|
234
|
+
}
|
|
235
|
+
function finishToken(type, val) {
|
|
236
|
+
tokEnd = tokPos;
|
|
237
|
+
if (options.locations) {
|
|
238
|
+
tokEndLoc = new line_loc_t;
|
|
239
|
+
}
|
|
240
|
+
tokType = type;
|
|
241
|
+
skipSpace();
|
|
242
|
+
tokVal = val;
|
|
243
|
+
tokRegexpAllowed = type.beforeExpr;
|
|
244
|
+
}
|
|
245
|
+
function skipBlockComment() {
|
|
246
|
+
var startLoc = options.onComment && options.locations && new line_loc_t;
|
|
247
|
+
var start = tokPos;
|
|
248
|
+
var end = input.indexOf("*/", tokPos += 2);
|
|
249
|
+
if (end === -1) {
|
|
250
|
+
raise(tokPos - 2, "Unterminated comment");
|
|
251
|
+
}
|
|
252
|
+
tokPos = end + 2;
|
|
253
|
+
if (options.locations) {
|
|
254
|
+
lineBreak.lastIndex = start;
|
|
255
|
+
var match;
|
|
256
|
+
while ((match = lineBreak.exec(input)) && match.index < tokPos) {
|
|
257
|
+
++tokCurLine;
|
|
258
|
+
tokLineStart = match.index + match[0].length;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (options.onComment) {
|
|
262
|
+
options.onComment(true, input.slice(start + 2, end), start, tokPos, startLoc, options.locations && new line_loc_t);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function skipLineComment() {
|
|
266
|
+
var start = tokPos;
|
|
267
|
+
var startLoc = options.onComment && options.locations && new line_loc_t;
|
|
268
|
+
var ch = input.charCodeAt(tokPos += 2);
|
|
269
|
+
while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
|
|
270
|
+
++tokPos;
|
|
271
|
+
ch = input.charCodeAt(tokPos);
|
|
272
|
+
}
|
|
273
|
+
if (options.onComment) {
|
|
274
|
+
options.onComment(false, input.slice(start + 2, tokPos), start, tokPos, startLoc, options.locations && new line_loc_t);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function skipSpace() {
|
|
278
|
+
while (tokPos < inputLen) {
|
|
279
|
+
var ch = input.charCodeAt(tokPos);
|
|
280
|
+
if (ch === 32) {
|
|
281
|
+
++tokPos;
|
|
282
|
+
} else if (ch === 13) {
|
|
283
|
+
++tokPos;
|
|
284
|
+
var next = input.charCodeAt(tokPos);
|
|
285
|
+
if (next === 10) {
|
|
286
|
+
++tokPos;
|
|
287
|
+
}
|
|
288
|
+
if (options.locations) {
|
|
289
|
+
++tokCurLine;
|
|
290
|
+
tokLineStart = tokPos;
|
|
291
|
+
}
|
|
292
|
+
} else if (ch === 10 || ch === 8232 || ch === 8233) {
|
|
293
|
+
++tokPos;
|
|
294
|
+
if (options.locations) {
|
|
295
|
+
++tokCurLine;
|
|
296
|
+
tokLineStart = tokPos;
|
|
297
|
+
}
|
|
298
|
+
} else if (ch > 8 && ch < 14) {
|
|
299
|
+
++tokPos;
|
|
300
|
+
} else if (ch === 47) {
|
|
301
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
302
|
+
if (next === 42) {
|
|
303
|
+
skipBlockComment();
|
|
304
|
+
} else if (next === 47) {
|
|
305
|
+
skipLineComment();
|
|
306
|
+
} else
|
|
307
|
+
break;
|
|
308
|
+
} else if (ch === 160) {
|
|
309
|
+
++tokPos;
|
|
310
|
+
} else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
|
|
311
|
+
++tokPos;
|
|
312
|
+
} else {
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
function readToken_dot() {
|
|
318
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
319
|
+
if (next >= 48 && next <= 57) {
|
|
320
|
+
readNumber(true);
|
|
321
|
+
} else {
|
|
322
|
+
++tokPos;
|
|
323
|
+
finishToken(_dot);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function readToken_slash() {
|
|
327
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
328
|
+
if (tokRegexpAllowed) {
|
|
329
|
+
++tokPos;
|
|
330
|
+
readRegexp();
|
|
331
|
+
} else if (next === 61) {
|
|
332
|
+
finishOp(_assign, 2);
|
|
333
|
+
} else {
|
|
334
|
+
finishOp(_slash, 1);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function readToken_mult_modulo() {
|
|
338
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
339
|
+
if (next === 61) {
|
|
340
|
+
finishOp(_assign, 2);
|
|
341
|
+
} else {
|
|
342
|
+
finishOp(_multiplyModulo, 1);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function readToken_pipe_amp(code) {
|
|
346
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
347
|
+
if (next === code) {
|
|
348
|
+
finishOp(code === 124 ? _logicalOR : _logicalAND, 2);
|
|
349
|
+
} else if (next === 61) {
|
|
350
|
+
finishOp(_assign, 2);
|
|
351
|
+
} else {
|
|
352
|
+
finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function readToken_caret() {
|
|
356
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
357
|
+
if (next === 61) {
|
|
358
|
+
finishOp(_assign, 2);
|
|
359
|
+
} else {
|
|
360
|
+
finishOp(_bitwiseXOR, 1);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function readToken_plus_min(code) {
|
|
364
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
365
|
+
if (next === code) {
|
|
366
|
+
if (next === 45 && input.charCodeAt(tokPos + 2) === 62 && newline.test(input.slice(lastEnd, tokPos))) {
|
|
367
|
+
tokPos += 3;
|
|
368
|
+
skipLineComment();
|
|
369
|
+
skipSpace();
|
|
370
|
+
readToken();
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
finishOp(_incDec, 2);
|
|
374
|
+
} else if (next === 61) {
|
|
375
|
+
finishOp(_assign, 2);
|
|
376
|
+
} else {
|
|
377
|
+
finishOp(_plusMin, 1);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
function readToken_lt_gt(code) {
|
|
381
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
382
|
+
var size = 1;
|
|
383
|
+
if (next === code) {
|
|
384
|
+
size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2;
|
|
385
|
+
if (input.charCodeAt(tokPos + size) === 61) {
|
|
386
|
+
finishOp(_assign, size + 1);
|
|
387
|
+
} else {
|
|
388
|
+
finishOp(_bitShift, size);
|
|
389
|
+
}
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (next === 33 && code === 60 && input.charCodeAt(tokPos + 2) === 45 && input.charCodeAt(tokPos + 3) === 45) {
|
|
393
|
+
tokPos += 4;
|
|
394
|
+
skipLineComment();
|
|
395
|
+
skipSpace();
|
|
396
|
+
readToken();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (next === 61) {
|
|
400
|
+
size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;
|
|
401
|
+
}
|
|
402
|
+
finishOp(_relational, size);
|
|
403
|
+
}
|
|
404
|
+
function readToken_eq_excl(code) {
|
|
405
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
406
|
+
if (next === 61) {
|
|
407
|
+
finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);
|
|
408
|
+
} else {
|
|
409
|
+
finishOp(code === 61 ? _eq : _prefix, 1);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function getTokenFromCode(code) {
|
|
413
|
+
switch (code) {
|
|
414
|
+
case 46:
|
|
415
|
+
return readToken_dot();
|
|
416
|
+
case 40:
|
|
417
|
+
++tokPos;
|
|
418
|
+
return finishToken(_parenL);
|
|
419
|
+
case 41:
|
|
420
|
+
++tokPos;
|
|
421
|
+
return finishToken(_parenR);
|
|
422
|
+
case 59:
|
|
423
|
+
++tokPos;
|
|
424
|
+
return finishToken(_semi);
|
|
425
|
+
case 44:
|
|
426
|
+
++tokPos;
|
|
427
|
+
return finishToken(_comma);
|
|
428
|
+
case 91:
|
|
429
|
+
++tokPos;
|
|
430
|
+
return finishToken(_bracketL);
|
|
431
|
+
case 93:
|
|
432
|
+
++tokPos;
|
|
433
|
+
return finishToken(_bracketR);
|
|
434
|
+
case 123:
|
|
435
|
+
++tokPos;
|
|
436
|
+
return finishToken(_braceL);
|
|
437
|
+
case 125:
|
|
438
|
+
++tokPos;
|
|
439
|
+
return finishToken(_braceR);
|
|
440
|
+
case 58:
|
|
441
|
+
++tokPos;
|
|
442
|
+
return finishToken(_colon);
|
|
443
|
+
case 63:
|
|
444
|
+
++tokPos;
|
|
445
|
+
return finishToken(_question);
|
|
446
|
+
case 48:
|
|
447
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
448
|
+
if (next === 120 || next === 88)
|
|
449
|
+
return readHexNumber();
|
|
450
|
+
case 49:
|
|
451
|
+
case 50:
|
|
452
|
+
case 51:
|
|
453
|
+
case 52:
|
|
454
|
+
case 53:
|
|
455
|
+
case 54:
|
|
456
|
+
case 55:
|
|
457
|
+
case 56:
|
|
458
|
+
case 57:
|
|
459
|
+
return readNumber(false);
|
|
460
|
+
case 34:
|
|
461
|
+
case 39:
|
|
462
|
+
return readString(code);
|
|
463
|
+
case 47:
|
|
464
|
+
return readToken_slash();
|
|
465
|
+
case 37:
|
|
466
|
+
case 42:
|
|
467
|
+
return readToken_mult_modulo();
|
|
468
|
+
case 124:
|
|
469
|
+
case 38:
|
|
470
|
+
return readToken_pipe_amp(code);
|
|
471
|
+
case 94:
|
|
472
|
+
return readToken_caret();
|
|
473
|
+
case 43:
|
|
474
|
+
case 45:
|
|
475
|
+
return readToken_plus_min(code);
|
|
476
|
+
case 60:
|
|
477
|
+
case 62:
|
|
478
|
+
return readToken_lt_gt(code);
|
|
479
|
+
case 61:
|
|
480
|
+
case 33:
|
|
481
|
+
return readToken_eq_excl(code);
|
|
482
|
+
case 126:
|
|
483
|
+
return finishOp(_prefix, 1);
|
|
484
|
+
}
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
function readToken(forceRegexp) {
|
|
488
|
+
if (!forceRegexp) {
|
|
489
|
+
tokStart = tokPos;
|
|
490
|
+
} else {
|
|
491
|
+
tokPos = tokStart + 1;
|
|
492
|
+
}
|
|
493
|
+
if (options.locations) {
|
|
494
|
+
tokStartLoc = new line_loc_t;
|
|
495
|
+
}
|
|
496
|
+
if (forceRegexp)
|
|
497
|
+
return readRegexp();
|
|
498
|
+
if (tokPos >= inputLen)
|
|
499
|
+
return finishToken(_eof);
|
|
500
|
+
var code = input.charCodeAt(tokPos);
|
|
501
|
+
if (isIdentifierStart(code) || code === 92) {
|
|
502
|
+
return readWord();
|
|
503
|
+
}
|
|
504
|
+
var tok = getTokenFromCode(code);
|
|
505
|
+
if (tok === false) {
|
|
506
|
+
var ch = String.fromCharCode(code);
|
|
507
|
+
if (ch === "\\" || nonASCIIidentifierStart.test(ch)) {
|
|
508
|
+
return readWord();
|
|
509
|
+
}
|
|
510
|
+
raise(tokPos, "Unexpected character '" + ch + "'");
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function finishOp(type, size) {
|
|
514
|
+
var str = input.slice(tokPos, tokPos + size);
|
|
515
|
+
tokPos += size;
|
|
516
|
+
finishToken(type, str);
|
|
517
|
+
}
|
|
518
|
+
function readRegexp() {
|
|
519
|
+
var escaped;
|
|
520
|
+
var inClass;
|
|
521
|
+
var start = tokPos;
|
|
522
|
+
for (;; ) {
|
|
523
|
+
if (tokPos >= inputLen)
|
|
524
|
+
raise(start, "Unterminated regexp");
|
|
525
|
+
var ch = input.charAt(tokPos);
|
|
526
|
+
if (newline.test(ch))
|
|
527
|
+
raise(start, "Unterminated regexp");
|
|
528
|
+
if (!escaped) {
|
|
529
|
+
if (ch === "[") {
|
|
530
|
+
inClass = true;
|
|
531
|
+
} else if (ch === "]" && inClass) {
|
|
532
|
+
inClass = false;
|
|
533
|
+
} else if (ch === "/" && !inClass) {
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
escaped = ch === "\\";
|
|
537
|
+
} else
|
|
538
|
+
escaped = false;
|
|
539
|
+
++tokPos;
|
|
540
|
+
}
|
|
541
|
+
var content = input.slice(start, tokPos);
|
|
542
|
+
++tokPos;
|
|
543
|
+
var mods = readWord1();
|
|
544
|
+
if (mods && !/^[gmi]*$/.test(mods)) {
|
|
545
|
+
raise(start, "Invalid regexp flag");
|
|
546
|
+
}
|
|
547
|
+
try {
|
|
548
|
+
var value = new RegExp(content, mods);
|
|
549
|
+
} catch (e) {
|
|
550
|
+
if (e instanceof SyntaxError)
|
|
551
|
+
raise(start, e.message);
|
|
552
|
+
throw e;
|
|
553
|
+
}
|
|
554
|
+
finishToken(_regexp, value);
|
|
555
|
+
}
|
|
556
|
+
function readInt(radix, len) {
|
|
557
|
+
var start = tokPos;
|
|
558
|
+
var total = 0;
|
|
559
|
+
var e = len === undefined ? Infinity : len;
|
|
560
|
+
for (var i = 0;i < e; ++i) {
|
|
561
|
+
var code = input.charCodeAt(tokPos), val;
|
|
562
|
+
if (code >= 97) {
|
|
563
|
+
val = code - 97 + 10;
|
|
564
|
+
} else if (code >= 65) {
|
|
565
|
+
val = code - 65 + 10;
|
|
566
|
+
} else if (code >= 48 && code <= 57) {
|
|
567
|
+
val = code - 48;
|
|
568
|
+
} else {
|
|
569
|
+
val = Infinity;
|
|
570
|
+
}
|
|
571
|
+
if (val >= radix)
|
|
572
|
+
break;
|
|
573
|
+
++tokPos;
|
|
574
|
+
total = total * radix + val;
|
|
575
|
+
}
|
|
576
|
+
if (tokPos === start || len !== undefined && tokPos - start !== len) {
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
return total;
|
|
580
|
+
}
|
|
581
|
+
function readHexNumber() {
|
|
582
|
+
tokPos += 2;
|
|
583
|
+
var val = readInt(16);
|
|
584
|
+
if (val === null) {
|
|
585
|
+
raise(tokStart + 2, "Expected hexadecimal number");
|
|
586
|
+
}
|
|
587
|
+
if (isIdentifierStart(input.charCodeAt(tokPos))) {
|
|
588
|
+
raise(tokPos, "Identifier directly after number");
|
|
589
|
+
}
|
|
590
|
+
finishToken(_num, val);
|
|
591
|
+
}
|
|
592
|
+
function readNumber(startsWithDot) {
|
|
593
|
+
var start = tokPos;
|
|
594
|
+
var isFloat = false;
|
|
595
|
+
var octal = input.charCodeAt(tokPos) === 48;
|
|
596
|
+
if (!startsWithDot && readInt(10) === null) {
|
|
597
|
+
raise(start, "Invalid number");
|
|
598
|
+
}
|
|
599
|
+
if (input.charCodeAt(tokPos) === 46) {
|
|
600
|
+
++tokPos;
|
|
601
|
+
readInt(10);
|
|
602
|
+
isFloat = true;
|
|
603
|
+
}
|
|
604
|
+
var next = input.charCodeAt(tokPos);
|
|
605
|
+
if (next === 69 || next === 101) {
|
|
606
|
+
next = input.charCodeAt(++tokPos);
|
|
607
|
+
if (next === 43 || next === 45) {
|
|
608
|
+
++tokPos;
|
|
609
|
+
}
|
|
610
|
+
if (readInt(10) === null) {
|
|
611
|
+
raise(start, "Invalid number");
|
|
612
|
+
}
|
|
613
|
+
isFloat = true;
|
|
614
|
+
}
|
|
615
|
+
if (isIdentifierStart(input.charCodeAt(tokPos))) {
|
|
616
|
+
raise(tokPos, "Identifier directly after number");
|
|
617
|
+
}
|
|
618
|
+
var str = input.slice(start, tokPos);
|
|
619
|
+
var val;
|
|
620
|
+
if (isFloat) {
|
|
621
|
+
val = parseFloat(str);
|
|
622
|
+
} else if (!octal || str.length === 1) {
|
|
623
|
+
val = parseInt(str, 10);
|
|
624
|
+
} else if (/[89]/.test(str) || strict) {
|
|
625
|
+
raise(start, "Invalid number");
|
|
626
|
+
} else {
|
|
627
|
+
val = parseInt(str, 8);
|
|
628
|
+
}
|
|
629
|
+
finishToken(_num, val);
|
|
630
|
+
}
|
|
631
|
+
function readString(quote) {
|
|
632
|
+
tokPos++;
|
|
633
|
+
var out = "";
|
|
634
|
+
for (;; ) {
|
|
635
|
+
if (tokPos >= inputLen)
|
|
636
|
+
raise(tokStart, "Unterminated string constant");
|
|
637
|
+
var ch = input.charCodeAt(tokPos);
|
|
638
|
+
if (ch === quote) {
|
|
639
|
+
++tokPos;
|
|
640
|
+
finishToken(_string, out);
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
if (ch === 92) {
|
|
644
|
+
ch = input.charCodeAt(++tokPos);
|
|
645
|
+
var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));
|
|
646
|
+
if (octal) {
|
|
647
|
+
octal = octal[0];
|
|
648
|
+
}
|
|
649
|
+
while (octal && parseInt(octal, 8) > 255) {
|
|
650
|
+
octal = octal.slice(0, -1);
|
|
651
|
+
}
|
|
652
|
+
if (octal === "0") {
|
|
653
|
+
octal = null;
|
|
654
|
+
}
|
|
655
|
+
++tokPos;
|
|
656
|
+
if (octal) {
|
|
657
|
+
if (strict)
|
|
658
|
+
raise(tokPos - 2, "Octal literal in strict mode");
|
|
659
|
+
out += String.fromCharCode(parseInt(octal, 8));
|
|
660
|
+
tokPos += octal.length - 1;
|
|
661
|
+
} else {
|
|
662
|
+
switch (ch) {
|
|
663
|
+
case 110:
|
|
664
|
+
out += `
|
|
665
|
+
`;
|
|
666
|
+
break;
|
|
667
|
+
case 114:
|
|
668
|
+
out += "\r";
|
|
669
|
+
break;
|
|
670
|
+
case 120:
|
|
671
|
+
out += String.fromCharCode(readHexChar(2));
|
|
672
|
+
break;
|
|
673
|
+
case 117:
|
|
674
|
+
out += String.fromCharCode(readHexChar(4));
|
|
675
|
+
break;
|
|
676
|
+
case 85:
|
|
677
|
+
out += String.fromCharCode(readHexChar(8));
|
|
678
|
+
break;
|
|
679
|
+
case 116:
|
|
680
|
+
out += "\t";
|
|
681
|
+
break;
|
|
682
|
+
case 98:
|
|
683
|
+
out += "\b";
|
|
684
|
+
break;
|
|
685
|
+
case 118:
|
|
686
|
+
out += "\v";
|
|
687
|
+
break;
|
|
688
|
+
case 102:
|
|
689
|
+
out += "\f";
|
|
690
|
+
break;
|
|
691
|
+
case 48:
|
|
692
|
+
out += "\x00";
|
|
693
|
+
break;
|
|
694
|
+
case 13:
|
|
695
|
+
if (input.charCodeAt(tokPos) === 10) {
|
|
696
|
+
++tokPos;
|
|
697
|
+
}
|
|
698
|
+
case 10:
|
|
699
|
+
if (options.locations) {
|
|
700
|
+
tokLineStart = tokPos;
|
|
701
|
+
++tokCurLine;
|
|
702
|
+
}
|
|
703
|
+
break;
|
|
704
|
+
default:
|
|
705
|
+
out += String.fromCharCode(ch);
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
} else {
|
|
710
|
+
if (ch === 13 || ch === 10 || ch === 8232 || ch === 8233) {
|
|
711
|
+
raise(tokStart, "Unterminated string constant");
|
|
712
|
+
}
|
|
713
|
+
out += String.fromCharCode(ch);
|
|
714
|
+
++tokPos;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
function readHexChar(len) {
|
|
719
|
+
var n = readInt(16, len);
|
|
720
|
+
if (n === null)
|
|
721
|
+
raise(tokStart, "Bad character escape sequence");
|
|
722
|
+
return n;
|
|
723
|
+
}
|
|
724
|
+
var containsEsc;
|
|
725
|
+
function readWord1() {
|
|
726
|
+
containsEsc = false;
|
|
727
|
+
var word;
|
|
728
|
+
var first = true;
|
|
729
|
+
var start = tokPos;
|
|
730
|
+
for (;; ) {
|
|
731
|
+
var ch = input.charCodeAt(tokPos);
|
|
732
|
+
if (isIdentifierChar(ch)) {
|
|
733
|
+
if (containsEsc) {
|
|
734
|
+
word += input.charAt(tokPos);
|
|
735
|
+
}
|
|
736
|
+
++tokPos;
|
|
737
|
+
} else if (ch === 92) {
|
|
738
|
+
if (!containsEsc) {
|
|
739
|
+
word = input.slice(start, tokPos);
|
|
740
|
+
}
|
|
741
|
+
containsEsc = true;
|
|
742
|
+
if (input.charCodeAt(++tokPos) !== 117) {
|
|
743
|
+
raise(tokPos, "Expecting Unicode escape sequence \\uXXXX");
|
|
744
|
+
}
|
|
745
|
+
++tokPos;
|
|
746
|
+
var esc = readHexChar(4);
|
|
747
|
+
var escStr = String.fromCharCode(esc);
|
|
748
|
+
if (!escStr)
|
|
749
|
+
raise(tokPos - 1, "Invalid Unicode escape");
|
|
750
|
+
if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc))) {
|
|
751
|
+
raise(tokPos - 4, "Invalid Unicode escape");
|
|
752
|
+
}
|
|
753
|
+
word += escStr;
|
|
754
|
+
} else {
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
first = false;
|
|
758
|
+
}
|
|
759
|
+
return containsEsc ? word : input.slice(start, tokPos);
|
|
760
|
+
}
|
|
761
|
+
function readWord() {
|
|
762
|
+
var word = readWord1();
|
|
763
|
+
var type = _name;
|
|
764
|
+
if (!containsEsc && isKeyword(word)) {
|
|
765
|
+
type = keywordTypes[word];
|
|
766
|
+
}
|
|
767
|
+
finishToken(type, word);
|
|
768
|
+
}
|
|
769
|
+
function next() {
|
|
770
|
+
lastStart = tokStart;
|
|
771
|
+
lastEnd = tokEnd;
|
|
772
|
+
lastEndLoc = tokEndLoc;
|
|
773
|
+
readToken();
|
|
774
|
+
}
|
|
775
|
+
function setStrict(strct) {
|
|
776
|
+
strict = strct;
|
|
777
|
+
tokPos = tokStart;
|
|
778
|
+
if (options.locations) {
|
|
779
|
+
while (tokPos < tokLineStart) {
|
|
780
|
+
tokLineStart = input.lastIndexOf(`
|
|
781
|
+
`, tokLineStart - 2) + 1;
|
|
782
|
+
--tokCurLine;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
skipSpace();
|
|
786
|
+
readToken();
|
|
787
|
+
}
|
|
788
|
+
function node_t() {
|
|
789
|
+
this.type = null;
|
|
790
|
+
this.start = tokStart;
|
|
791
|
+
this.end = null;
|
|
792
|
+
}
|
|
793
|
+
function node_loc_t() {
|
|
794
|
+
this.start = tokStartLoc;
|
|
795
|
+
this.end = null;
|
|
796
|
+
if (sourceFile) {
|
|
797
|
+
this.source = sourceFile;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
function startNode() {
|
|
801
|
+
var node = new node_t;
|
|
802
|
+
if (options.locations) {
|
|
803
|
+
node.loc = new node_loc_t;
|
|
804
|
+
}
|
|
805
|
+
if (options.directSourceFile) {
|
|
806
|
+
node.sourceFile = options.directSourceFile;
|
|
807
|
+
}
|
|
808
|
+
if (options.ranges) {
|
|
809
|
+
node.range = [tokStart, 0];
|
|
810
|
+
}
|
|
811
|
+
return node;
|
|
812
|
+
}
|
|
813
|
+
function startNodeFrom(other) {
|
|
814
|
+
var node = new node_t;
|
|
815
|
+
node.start = other.start;
|
|
816
|
+
if (options.locations) {
|
|
817
|
+
node.loc = new node_loc_t;
|
|
818
|
+
node.loc.start = other.loc.start;
|
|
819
|
+
}
|
|
820
|
+
if (options.ranges) {
|
|
821
|
+
node.range = [other.range[0], 0];
|
|
822
|
+
}
|
|
823
|
+
return node;
|
|
824
|
+
}
|
|
825
|
+
function finishNode(node, type) {
|
|
826
|
+
node.type = type;
|
|
827
|
+
node.end = lastEnd;
|
|
828
|
+
if (options.locations) {
|
|
829
|
+
node.loc.end = lastEndLoc;
|
|
830
|
+
}
|
|
831
|
+
if (options.ranges) {
|
|
832
|
+
node.range[1] = lastEnd;
|
|
833
|
+
}
|
|
834
|
+
return node;
|
|
835
|
+
}
|
|
836
|
+
function isUseStrict(stmt) {
|
|
837
|
+
return stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && stmt.expression.value === "use strict";
|
|
838
|
+
}
|
|
839
|
+
function eat(type) {
|
|
840
|
+
if (tokType === type) {
|
|
841
|
+
next();
|
|
842
|
+
return true;
|
|
843
|
+
}
|
|
844
|
+
return false;
|
|
845
|
+
}
|
|
846
|
+
function canInsertSemicolon() {
|
|
847
|
+
return !options.strictSemicolons && (tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart)));
|
|
848
|
+
}
|
|
849
|
+
function semicolon() {
|
|
850
|
+
if (!eat(_semi) && !canInsertSemicolon()) {
|
|
851
|
+
unexpected();
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
function expect(type) {
|
|
855
|
+
if (tokType === type) {
|
|
856
|
+
next();
|
|
857
|
+
} else {
|
|
858
|
+
unexpected();
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
function unexpected() {
|
|
862
|
+
raise(tokStart, "Unexpected token");
|
|
863
|
+
}
|
|
864
|
+
function checkLVal(expr) {
|
|
865
|
+
if (expr.type !== "Identifier" && expr.type !== "MemberExpression") {
|
|
866
|
+
raise(expr.start, "Assigning to rvalue");
|
|
867
|
+
}
|
|
868
|
+
if (strict && expr.type === "Identifier" && isStrictBadIdWord(expr.name)) {
|
|
869
|
+
raise(expr.start, "Assigning to " + expr.name + " in strict mode");
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
function parseTopLevel(program) {
|
|
873
|
+
lastStart = lastEnd = tokPos;
|
|
874
|
+
if (options.locations) {
|
|
875
|
+
lastEndLoc = new line_loc_t;
|
|
876
|
+
}
|
|
877
|
+
inFunction = strict = false;
|
|
878
|
+
labels = [];
|
|
879
|
+
readToken();
|
|
880
|
+
var node = program || startNode();
|
|
881
|
+
var first = true;
|
|
882
|
+
if (!program) {
|
|
883
|
+
node.body = [];
|
|
884
|
+
}
|
|
885
|
+
while (tokType !== _eof) {
|
|
886
|
+
var stmt = parseStatement();
|
|
887
|
+
node.body.push(stmt);
|
|
888
|
+
if (first && isUseStrict(stmt)) {
|
|
889
|
+
setStrict(true);
|
|
890
|
+
}
|
|
891
|
+
first = false;
|
|
892
|
+
}
|
|
893
|
+
return finishNode(node, "Program");
|
|
894
|
+
}
|
|
895
|
+
var loopLabel = { kind: "loop" };
|
|
896
|
+
var switchLabel = { kind: "switch" };
|
|
897
|
+
function parseStatement() {
|
|
898
|
+
if (tokType === _slash || tokType === _assign && tokVal === "/=") {
|
|
899
|
+
readToken(true);
|
|
900
|
+
}
|
|
901
|
+
var starttype = tokType;
|
|
902
|
+
var node = startNode();
|
|
903
|
+
switch (starttype) {
|
|
904
|
+
case _break:
|
|
905
|
+
case _continue:
|
|
906
|
+
next();
|
|
907
|
+
var isBreak = starttype === _break;
|
|
908
|
+
if (eat(_semi) || canInsertSemicolon()) {
|
|
909
|
+
node.label = null;
|
|
910
|
+
} else if (tokType !== _name) {
|
|
911
|
+
unexpected();
|
|
912
|
+
} else {
|
|
913
|
+
node.label = parseIdent();
|
|
914
|
+
semicolon();
|
|
915
|
+
}
|
|
916
|
+
for (var i = 0;i < labels.length; ++i) {
|
|
917
|
+
var lab = labels[i];
|
|
918
|
+
if (node.label === null || lab.name === node.label.name) {
|
|
919
|
+
if (lab.kind !== null && (isBreak || lab.kind === "loop"))
|
|
920
|
+
break;
|
|
921
|
+
if (node.label && isBreak)
|
|
922
|
+
break;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
if (i === labels.length) {
|
|
926
|
+
raise(node.start, "Unsyntactic " + starttype.keyword);
|
|
927
|
+
}
|
|
928
|
+
return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
|
|
929
|
+
case _debugger:
|
|
930
|
+
next();
|
|
931
|
+
semicolon();
|
|
932
|
+
return finishNode(node, "DebuggerStatement");
|
|
933
|
+
case _do:
|
|
934
|
+
next();
|
|
935
|
+
labels.push(loopLabel);
|
|
936
|
+
node.body = parseStatement();
|
|
937
|
+
labels.pop();
|
|
938
|
+
expect(_while);
|
|
939
|
+
node.test = parseParenExpression();
|
|
940
|
+
semicolon();
|
|
941
|
+
return finishNode(node, "DoWhileStatement");
|
|
942
|
+
case _for:
|
|
943
|
+
next();
|
|
944
|
+
labels.push(loopLabel);
|
|
945
|
+
expect(_parenL);
|
|
946
|
+
if (tokType === _semi)
|
|
947
|
+
return parseFor(node, null);
|
|
948
|
+
if (tokType === _var) {
|
|
949
|
+
var init = startNode();
|
|
950
|
+
next();
|
|
951
|
+
parseVar(init, true);
|
|
952
|
+
finishNode(init, "VariableDeclaration");
|
|
953
|
+
if (init.declarations.length === 1 && eat(_in))
|
|
954
|
+
return parseForIn(node, init);
|
|
955
|
+
return parseFor(node, init);
|
|
956
|
+
}
|
|
957
|
+
var init = parseExpression(false, true);
|
|
958
|
+
if (eat(_in)) {
|
|
959
|
+
checkLVal(init);
|
|
960
|
+
return parseForIn(node, init);
|
|
961
|
+
}
|
|
962
|
+
return parseFor(node, init);
|
|
963
|
+
case _function:
|
|
964
|
+
next();
|
|
965
|
+
return parseFunction(node, true);
|
|
966
|
+
case _if:
|
|
967
|
+
next();
|
|
968
|
+
node.test = parseParenExpression();
|
|
969
|
+
node.consequent = parseStatement();
|
|
970
|
+
node.alternate = eat(_else) ? parseStatement() : null;
|
|
971
|
+
return finishNode(node, "IfStatement");
|
|
972
|
+
case _return:
|
|
973
|
+
if (!inFunction && !options.allowReturnOutsideFunction) {
|
|
974
|
+
raise(tokStart, "'return' outside of function");
|
|
975
|
+
}
|
|
976
|
+
next();
|
|
977
|
+
if (eat(_semi) || canInsertSemicolon()) {
|
|
978
|
+
node.argument = null;
|
|
979
|
+
} else {
|
|
980
|
+
node.argument = parseExpression();
|
|
981
|
+
semicolon();
|
|
982
|
+
}
|
|
983
|
+
return finishNode(node, "ReturnStatement");
|
|
984
|
+
case _switch:
|
|
985
|
+
next();
|
|
986
|
+
node.discriminant = parseParenExpression();
|
|
987
|
+
node.cases = [];
|
|
988
|
+
expect(_braceL);
|
|
989
|
+
labels.push(switchLabel);
|
|
990
|
+
for (var cur, sawDefault;tokType !== _braceR; ) {
|
|
991
|
+
if (tokType === _case || tokType === _default) {
|
|
992
|
+
var isCase = tokType === _case;
|
|
993
|
+
if (cur) {
|
|
994
|
+
finishNode(cur, "SwitchCase");
|
|
995
|
+
}
|
|
996
|
+
node.cases.push(cur = startNode());
|
|
997
|
+
cur.consequent = [];
|
|
998
|
+
next();
|
|
999
|
+
if (isCase) {
|
|
1000
|
+
cur.test = parseExpression();
|
|
1001
|
+
} else {
|
|
1002
|
+
if (sawDefault) {
|
|
1003
|
+
raise(lastStart, "Multiple default clauses");
|
|
1004
|
+
}
|
|
1005
|
+
sawDefault = true;
|
|
1006
|
+
cur.test = null;
|
|
1007
|
+
}
|
|
1008
|
+
expect(_colon);
|
|
1009
|
+
} else {
|
|
1010
|
+
if (!cur)
|
|
1011
|
+
unexpected();
|
|
1012
|
+
cur.consequent.push(parseStatement());
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
if (cur)
|
|
1016
|
+
finishNode(cur, "SwitchCase");
|
|
1017
|
+
next();
|
|
1018
|
+
labels.pop();
|
|
1019
|
+
return finishNode(node, "SwitchStatement");
|
|
1020
|
+
case _throw:
|
|
1021
|
+
next();
|
|
1022
|
+
if (newline.test(input.slice(lastEnd, tokStart)))
|
|
1023
|
+
raise(lastEnd, "Illegal newline after throw");
|
|
1024
|
+
node.argument = parseExpression();
|
|
1025
|
+
semicolon();
|
|
1026
|
+
return finishNode(node, "ThrowStatement");
|
|
1027
|
+
case _try:
|
|
1028
|
+
next();
|
|
1029
|
+
node.block = parseBlock();
|
|
1030
|
+
node.handler = null;
|
|
1031
|
+
if (tokType === _catch) {
|
|
1032
|
+
var clause = startNode();
|
|
1033
|
+
next();
|
|
1034
|
+
expect(_parenL);
|
|
1035
|
+
clause.param = parseIdent();
|
|
1036
|
+
if (strict && isStrictBadIdWord(clause.param.name))
|
|
1037
|
+
raise(clause.param.start, "Binding " + clause.param.name + " in strict mode");
|
|
1038
|
+
expect(_parenR);
|
|
1039
|
+
clause.body = parseBlock();
|
|
1040
|
+
node.handler = finishNode(clause, "CatchClause");
|
|
1041
|
+
}
|
|
1042
|
+
node.finalizer = eat(_finally) ? parseBlock() : null;
|
|
1043
|
+
if (!node.handler && !node.finalizer)
|
|
1044
|
+
raise(node.start, "Missing catch or finally clause");
|
|
1045
|
+
return finishNode(node, "TryStatement");
|
|
1046
|
+
case _var:
|
|
1047
|
+
next();
|
|
1048
|
+
parseVar(node);
|
|
1049
|
+
semicolon();
|
|
1050
|
+
return finishNode(node, "VariableDeclaration");
|
|
1051
|
+
case _while:
|
|
1052
|
+
next();
|
|
1053
|
+
node.test = parseParenExpression();
|
|
1054
|
+
labels.push(loopLabel);
|
|
1055
|
+
node.body = parseStatement();
|
|
1056
|
+
labels.pop();
|
|
1057
|
+
return finishNode(node, "WhileStatement");
|
|
1058
|
+
case _with:
|
|
1059
|
+
if (strict)
|
|
1060
|
+
raise(tokStart, "'with' in strict mode");
|
|
1061
|
+
next();
|
|
1062
|
+
node.object = parseParenExpression();
|
|
1063
|
+
node.body = parseStatement();
|
|
1064
|
+
return finishNode(node, "WithStatement");
|
|
1065
|
+
case _braceL:
|
|
1066
|
+
return parseBlock();
|
|
1067
|
+
case _semi:
|
|
1068
|
+
next();
|
|
1069
|
+
return finishNode(node, "EmptyStatement");
|
|
1070
|
+
default:
|
|
1071
|
+
var maybeName = tokVal;
|
|
1072
|
+
var expr = parseExpression();
|
|
1073
|
+
if (starttype === _name && expr.type === "Identifier" && eat(_colon)) {
|
|
1074
|
+
for (var i = 0;i < labels.length; ++i) {
|
|
1075
|
+
if (labels[i].name === maybeName) {
|
|
1076
|
+
raise(expr.start, "Label '" + maybeName + "' is already declared");
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null;
|
|
1080
|
+
labels.push({ name: maybeName, kind });
|
|
1081
|
+
node.body = parseStatement();
|
|
1082
|
+
labels.pop();
|
|
1083
|
+
node.label = expr;
|
|
1084
|
+
return finishNode(node, "LabeledStatement");
|
|
1085
|
+
} else {
|
|
1086
|
+
node.expression = expr;
|
|
1087
|
+
semicolon();
|
|
1088
|
+
return finishNode(node, "ExpressionStatement");
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
function parseParenExpression() {
|
|
1093
|
+
expect(_parenL);
|
|
1094
|
+
var val = parseExpression();
|
|
1095
|
+
expect(_parenR);
|
|
1096
|
+
return val;
|
|
1097
|
+
}
|
|
1098
|
+
function parseBlock(allowStrict) {
|
|
1099
|
+
var node = startNode();
|
|
1100
|
+
var first = true;
|
|
1101
|
+
var strict2 = false;
|
|
1102
|
+
var oldStrict;
|
|
1103
|
+
node.body = [];
|
|
1104
|
+
expect(_braceL);
|
|
1105
|
+
while (!eat(_braceR)) {
|
|
1106
|
+
var stmt = parseStatement();
|
|
1107
|
+
node.body.push(stmt);
|
|
1108
|
+
if (first && allowStrict && isUseStrict(stmt)) {
|
|
1109
|
+
oldStrict = strict2;
|
|
1110
|
+
setStrict(strict2 = true);
|
|
1111
|
+
}
|
|
1112
|
+
first = false;
|
|
1113
|
+
}
|
|
1114
|
+
if (strict2 && !oldStrict)
|
|
1115
|
+
setStrict(false);
|
|
1116
|
+
return finishNode(node, "BlockStatement");
|
|
1117
|
+
}
|
|
1118
|
+
function parseFor(node, init) {
|
|
1119
|
+
node.init = init;
|
|
1120
|
+
expect(_semi);
|
|
1121
|
+
node.test = tokType === _semi ? null : parseExpression();
|
|
1122
|
+
expect(_semi);
|
|
1123
|
+
node.update = tokType === _parenR ? null : parseExpression();
|
|
1124
|
+
expect(_parenR);
|
|
1125
|
+
node.body = parseStatement();
|
|
1126
|
+
labels.pop();
|
|
1127
|
+
return finishNode(node, "ForStatement");
|
|
1128
|
+
}
|
|
1129
|
+
function parseForIn(node, init) {
|
|
1130
|
+
node.left = init;
|
|
1131
|
+
node.right = parseExpression();
|
|
1132
|
+
expect(_parenR);
|
|
1133
|
+
node.body = parseStatement();
|
|
1134
|
+
labels.pop();
|
|
1135
|
+
return finishNode(node, "ForInStatement");
|
|
1136
|
+
}
|
|
1137
|
+
function parseVar(node, noIn) {
|
|
1138
|
+
node.declarations = [];
|
|
1139
|
+
node.kind = "var";
|
|
1140
|
+
for (;; ) {
|
|
1141
|
+
var decl = startNode();
|
|
1142
|
+
decl.id = parseIdent();
|
|
1143
|
+
if (strict && isStrictBadIdWord(decl.id.name))
|
|
1144
|
+
raise(decl.id.start, "Binding " + decl.id.name + " in strict mode");
|
|
1145
|
+
decl.init = eat(_eq) ? parseExpression(true, noIn) : null;
|
|
1146
|
+
node.declarations.push(finishNode(decl, "VariableDeclarator"));
|
|
1147
|
+
if (!eat(_comma))
|
|
1148
|
+
break;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
function parseExpression(noComma, noIn) {
|
|
1152
|
+
var expr = parseMaybeAssign(noIn);
|
|
1153
|
+
if (!noComma && tokType === _comma) {
|
|
1154
|
+
var node = startNodeFrom(expr);
|
|
1155
|
+
node.expressions = [expr];
|
|
1156
|
+
while (eat(_comma))
|
|
1157
|
+
node.expressions.push(parseMaybeAssign(noIn));
|
|
1158
|
+
return finishNode(node, "SequenceExpression");
|
|
1159
|
+
}
|
|
1160
|
+
return expr;
|
|
1161
|
+
}
|
|
1162
|
+
function parseMaybeAssign(noIn) {
|
|
1163
|
+
var left = parseMaybeConditional(noIn);
|
|
1164
|
+
if (tokType.isAssign) {
|
|
1165
|
+
var node = startNodeFrom(left);
|
|
1166
|
+
node.operator = tokVal;
|
|
1167
|
+
node.left = left;
|
|
1168
|
+
next();
|
|
1169
|
+
node.right = parseMaybeAssign(noIn);
|
|
1170
|
+
checkLVal(left);
|
|
1171
|
+
return finishNode(node, "AssignmentExpression");
|
|
1172
|
+
}
|
|
1173
|
+
return left;
|
|
1174
|
+
}
|
|
1175
|
+
function parseMaybeConditional(noIn) {
|
|
1176
|
+
var expr = parseExprOps(noIn);
|
|
1177
|
+
if (eat(_question)) {
|
|
1178
|
+
var node = startNodeFrom(expr);
|
|
1179
|
+
node.test = expr;
|
|
1180
|
+
node.consequent = parseExpression(true);
|
|
1181
|
+
expect(_colon);
|
|
1182
|
+
node.alternate = parseExpression(true, noIn);
|
|
1183
|
+
return finishNode(node, "ConditionalExpression");
|
|
1184
|
+
}
|
|
1185
|
+
return expr;
|
|
1186
|
+
}
|
|
1187
|
+
function parseExprOps(noIn) {
|
|
1188
|
+
return parseExprOp(parseMaybeUnary(), -1, noIn);
|
|
1189
|
+
}
|
|
1190
|
+
function parseExprOp(left, minPrec, noIn) {
|
|
1191
|
+
var prec = tokType.binop;
|
|
1192
|
+
if (prec !== null && (!noIn || tokType !== _in)) {
|
|
1193
|
+
if (prec > minPrec) {
|
|
1194
|
+
var node = startNodeFrom(left);
|
|
1195
|
+
node.left = left;
|
|
1196
|
+
node.operator = tokVal;
|
|
1197
|
+
var op = tokType;
|
|
1198
|
+
next();
|
|
1199
|
+
node.right = parseExprOp(parseMaybeUnary(), prec, noIn);
|
|
1200
|
+
var exprNode = finishNode(node, op === _logicalOR || op === _logicalAND ? "LogicalExpression" : "BinaryExpression");
|
|
1201
|
+
return parseExprOp(exprNode, minPrec, noIn);
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
return left;
|
|
1205
|
+
}
|
|
1206
|
+
function parseMaybeUnary() {
|
|
1207
|
+
if (tokType.prefix) {
|
|
1208
|
+
var node = startNode();
|
|
1209
|
+
var update = tokType.isUpdate;
|
|
1210
|
+
node.operator = tokVal;
|
|
1211
|
+
node.prefix = true;
|
|
1212
|
+
tokRegexpAllowed = true;
|
|
1213
|
+
next();
|
|
1214
|
+
node.argument = parseMaybeUnary();
|
|
1215
|
+
if (update)
|
|
1216
|
+
checkLVal(node.argument);
|
|
1217
|
+
else if (strict && node.operator === "delete" && node.argument.type === "Identifier")
|
|
1218
|
+
raise(node.start, "Deleting local variable in strict mode");
|
|
1219
|
+
return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
|
|
1220
|
+
}
|
|
1221
|
+
var expr = parseExprSubscripts();
|
|
1222
|
+
while (tokType.postfix && !canInsertSemicolon()) {
|
|
1223
|
+
var node = startNodeFrom(expr);
|
|
1224
|
+
node.operator = tokVal;
|
|
1225
|
+
node.prefix = false;
|
|
1226
|
+
node.argument = expr;
|
|
1227
|
+
checkLVal(expr);
|
|
1228
|
+
next();
|
|
1229
|
+
expr = finishNode(node, "UpdateExpression");
|
|
1230
|
+
}
|
|
1231
|
+
return expr;
|
|
1232
|
+
}
|
|
1233
|
+
function parseExprSubscripts() {
|
|
1234
|
+
return parseSubscripts(parseExprAtom());
|
|
1235
|
+
}
|
|
1236
|
+
function parseSubscripts(base, noCalls) {
|
|
1237
|
+
var node;
|
|
1238
|
+
if (eat(_dot)) {
|
|
1239
|
+
node = startNodeFrom(base);
|
|
1240
|
+
node.object = base;
|
|
1241
|
+
node.property = parseIdent(true);
|
|
1242
|
+
node.computed = false;
|
|
1243
|
+
return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
|
|
1244
|
+
}
|
|
1245
|
+
if (eat(_bracketL)) {
|
|
1246
|
+
node = startNodeFrom(base);
|
|
1247
|
+
node.object = base;
|
|
1248
|
+
node.property = parseExpression();
|
|
1249
|
+
node.computed = true;
|
|
1250
|
+
expect(_bracketR);
|
|
1251
|
+
return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
|
|
1252
|
+
}
|
|
1253
|
+
if (!noCalls && eat(_parenL)) {
|
|
1254
|
+
node = startNodeFrom(base);
|
|
1255
|
+
node.callee = base;
|
|
1256
|
+
node.arguments = parseExprList(_parenR, false);
|
|
1257
|
+
return parseSubscripts(finishNode(node, "CallExpression"), noCalls);
|
|
1258
|
+
}
|
|
1259
|
+
return base;
|
|
1260
|
+
}
|
|
1261
|
+
function parseExprAtom() {
|
|
1262
|
+
var node;
|
|
1263
|
+
switch (tokType) {
|
|
1264
|
+
case _this:
|
|
1265
|
+
node = startNode();
|
|
1266
|
+
next();
|
|
1267
|
+
return finishNode(node, "ThisExpression");
|
|
1268
|
+
case _name:
|
|
1269
|
+
return parseIdent();
|
|
1270
|
+
case _num:
|
|
1271
|
+
case _string:
|
|
1272
|
+
case _regexp:
|
|
1273
|
+
node = startNode();
|
|
1274
|
+
node.value = tokVal;
|
|
1275
|
+
node.raw = input.slice(tokStart, tokEnd);
|
|
1276
|
+
next();
|
|
1277
|
+
return finishNode(node, "Literal");
|
|
1278
|
+
case _null:
|
|
1279
|
+
case _true:
|
|
1280
|
+
case _false:
|
|
1281
|
+
node = startNode();
|
|
1282
|
+
node.value = tokType.atomValue;
|
|
1283
|
+
node.raw = tokType.keyword;
|
|
1284
|
+
next();
|
|
1285
|
+
return finishNode(node, "Literal");
|
|
1286
|
+
case _parenL:
|
|
1287
|
+
var tokStartLoc1 = tokStartLoc;
|
|
1288
|
+
var tokStart1 = tokStart;
|
|
1289
|
+
next();
|
|
1290
|
+
var val = parseExpression();
|
|
1291
|
+
val.start = tokStart1;
|
|
1292
|
+
val.end = tokEnd;
|
|
1293
|
+
if (options.locations) {
|
|
1294
|
+
val.loc.start = tokStartLoc1;
|
|
1295
|
+
val.loc.end = tokEndLoc;
|
|
1296
|
+
}
|
|
1297
|
+
if (options.ranges) {
|
|
1298
|
+
val.range = [tokStart1, tokEnd];
|
|
1299
|
+
}
|
|
1300
|
+
expect(_parenR);
|
|
1301
|
+
return val;
|
|
1302
|
+
case _bracketL:
|
|
1303
|
+
node = startNode();
|
|
1304
|
+
next();
|
|
1305
|
+
node.elements = parseExprList(_bracketR, true, true);
|
|
1306
|
+
return finishNode(node, "ArrayExpression");
|
|
1307
|
+
case _braceL:
|
|
1308
|
+
return parseObj();
|
|
1309
|
+
case _function:
|
|
1310
|
+
node = startNode();
|
|
1311
|
+
next();
|
|
1312
|
+
return parseFunction(node, false);
|
|
1313
|
+
case _new:
|
|
1314
|
+
return parseNew();
|
|
1315
|
+
}
|
|
1316
|
+
unexpected();
|
|
1317
|
+
}
|
|
1318
|
+
function parseNew() {
|
|
1319
|
+
var node = startNode();
|
|
1320
|
+
next();
|
|
1321
|
+
node.callee = parseSubscripts(parseExprAtom(), true);
|
|
1322
|
+
node.arguments = eat(_parenL) ? parseExprList(_parenR, false) : empty;
|
|
1323
|
+
return finishNode(node, "NewExpression");
|
|
1324
|
+
}
|
|
1325
|
+
function parseObj() {
|
|
1326
|
+
var node = startNode();
|
|
1327
|
+
var first = true;
|
|
1328
|
+
var sawGetSet = false;
|
|
1329
|
+
node.properties = [];
|
|
1330
|
+
next();
|
|
1331
|
+
while (!eat(_braceR)) {
|
|
1332
|
+
if (!first) {
|
|
1333
|
+
expect(_comma);
|
|
1334
|
+
if (options.allowTrailingCommas && eat(_braceR)) {
|
|
1335
|
+
break;
|
|
1336
|
+
}
|
|
1337
|
+
} else {
|
|
1338
|
+
first = false;
|
|
1339
|
+
}
|
|
1340
|
+
var prop = { key: parsePropertyName() };
|
|
1341
|
+
var isGetSet = false;
|
|
1342
|
+
var kind;
|
|
1343
|
+
if (eat(_colon)) {
|
|
1344
|
+
prop.value = parseExpression(true);
|
|
1345
|
+
kind = prop.kind = "init";
|
|
1346
|
+
} else if (prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set")) {
|
|
1347
|
+
isGetSet = sawGetSet = true;
|
|
1348
|
+
kind = prop.kind = prop.key.name;
|
|
1349
|
+
prop.key = parsePropertyName();
|
|
1350
|
+
if (tokType !== _parenL)
|
|
1351
|
+
unexpected();
|
|
1352
|
+
prop.value = parseFunction(startNode(), false);
|
|
1353
|
+
} else {
|
|
1354
|
+
unexpected();
|
|
1355
|
+
}
|
|
1356
|
+
if (prop.key.type === "Identifier" && (strict || sawGetSet)) {
|
|
1357
|
+
for (var i = 0;i < node.properties.length; ++i) {
|
|
1358
|
+
var other = node.properties[i];
|
|
1359
|
+
if (other.key.name === prop.key.name) {
|
|
1360
|
+
var conflict = kind === other.kind || isGetSet && other.kind === "init" || kind === "init" && (other.kind === "get" || other.kind === "set");
|
|
1361
|
+
if (conflict && !strict && kind === "init" && other.kind === "init") {
|
|
1362
|
+
conflict = false;
|
|
1363
|
+
}
|
|
1364
|
+
if (conflict) {
|
|
1365
|
+
raise(prop.key.start, "Redefinition of property");
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
node.properties.push(prop);
|
|
1371
|
+
}
|
|
1372
|
+
return finishNode(node, "ObjectExpression");
|
|
1373
|
+
}
|
|
1374
|
+
function parsePropertyName() {
|
|
1375
|
+
if (tokType === _num || tokType === _string) {
|
|
1376
|
+
return parseExprAtom();
|
|
1377
|
+
}
|
|
1378
|
+
return parseIdent(true);
|
|
1379
|
+
}
|
|
1380
|
+
function parseFunction(node, isStatement) {
|
|
1381
|
+
if (tokType === _name) {
|
|
1382
|
+
node.id = parseIdent();
|
|
1383
|
+
} else if (isStatement) {
|
|
1384
|
+
unexpected();
|
|
1385
|
+
} else {
|
|
1386
|
+
node.id = null;
|
|
1387
|
+
}
|
|
1388
|
+
node.params = [];
|
|
1389
|
+
var first = true;
|
|
1390
|
+
expect(_parenL);
|
|
1391
|
+
while (!eat(_parenR)) {
|
|
1392
|
+
if (!first) {
|
|
1393
|
+
expect(_comma);
|
|
1394
|
+
} else {
|
|
1395
|
+
first = false;
|
|
1396
|
+
}
|
|
1397
|
+
node.params.push(parseIdent());
|
|
1398
|
+
}
|
|
1399
|
+
var oldInFunc = inFunction;
|
|
1400
|
+
var oldLabels = labels;
|
|
1401
|
+
inFunction = true;
|
|
1402
|
+
labels = [];
|
|
1403
|
+
node.body = parseBlock(true);
|
|
1404
|
+
inFunction = oldInFunc;
|
|
1405
|
+
labels = oldLabels;
|
|
1406
|
+
if (strict || node.body.body.length && isUseStrict(node.body.body[0])) {
|
|
1407
|
+
for (var i = node.id ? -1 : 0;i < node.params.length; ++i) {
|
|
1408
|
+
var id = i < 0 ? node.id : node.params[i];
|
|
1409
|
+
if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name)) {
|
|
1410
|
+
raise(id.start, "Defining '" + id.name + "' in strict mode");
|
|
1411
|
+
}
|
|
1412
|
+
if (i >= 0) {
|
|
1413
|
+
for (var j = 0;j < i; ++j) {
|
|
1414
|
+
if (id.name === node.params[j].name) {
|
|
1415
|
+
raise(id.start, "Argument name clash in strict mode");
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
|
|
1422
|
+
}
|
|
1423
|
+
function parseExprList(close, allowTrailingComma, allowEmpty) {
|
|
1424
|
+
var elts = [];
|
|
1425
|
+
var first = true;
|
|
1426
|
+
while (!eat(close)) {
|
|
1427
|
+
if (!first) {
|
|
1428
|
+
expect(_comma);
|
|
1429
|
+
if (allowTrailingComma && options.allowTrailingCommas && eat(close)) {
|
|
1430
|
+
break;
|
|
1431
|
+
}
|
|
1432
|
+
} else {
|
|
1433
|
+
first = false;
|
|
1434
|
+
}
|
|
1435
|
+
elts.push(allowEmpty && tokType === _comma ? null : parseExpression(true));
|
|
1436
|
+
}
|
|
1437
|
+
return elts;
|
|
1438
|
+
}
|
|
1439
|
+
function parseIdent(liberal) {
|
|
1440
|
+
var node = startNode();
|
|
1441
|
+
if (liberal && options.forbidReserved === "everywhere") {
|
|
1442
|
+
liberal = false;
|
|
1443
|
+
}
|
|
1444
|
+
if (tokType === _name) {
|
|
1445
|
+
if (!liberal && (options.forbidReserved && isReservedWord5(tokVal) || strict && isStrictReservedWord(tokVal)) && input.slice(tokStart, tokEnd).indexOf("\\") === -1) {
|
|
1446
|
+
raise(tokStart, "The keyword '" + tokVal + "' is reserved");
|
|
1447
|
+
}
|
|
1448
|
+
node.name = tokVal;
|
|
1449
|
+
} else if (liberal && tokType.keyword) {
|
|
1450
|
+
node.name = tokType.keyword;
|
|
1451
|
+
} else {
|
|
1452
|
+
unexpected();
|
|
1453
|
+
}
|
|
1454
|
+
tokRegexpAllowed = false;
|
|
1455
|
+
next();
|
|
1456
|
+
return finishNode(node, "Identifier");
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
// src/task/interpreter.js
|
|
1460
|
+
var Interpreter = function(code, opt_initFunc) {
|
|
1461
|
+
if (typeof code === "string") {
|
|
1462
|
+
code = this.parse_(code, "code");
|
|
1463
|
+
}
|
|
1464
|
+
var nodeConstructor = code.constructor;
|
|
1465
|
+
this.newNode = function() {
|
|
1466
|
+
return new nodeConstructor({ options: {} });
|
|
1467
|
+
};
|
|
1468
|
+
var ast = this.newNode();
|
|
1469
|
+
for (var prop in code) {
|
|
1470
|
+
ast[prop] = prop === "body" ? code[prop].slice() : code[prop];
|
|
1471
|
+
}
|
|
1472
|
+
this.ast = ast;
|
|
1473
|
+
this.tasks = [];
|
|
1474
|
+
this.initFunc_ = opt_initFunc;
|
|
1475
|
+
this.paused_ = false;
|
|
1476
|
+
this.polyfills_ = [];
|
|
1477
|
+
this.functionCounter_ = 0;
|
|
1478
|
+
this.stepFunctions_ = Object.create(null);
|
|
1479
|
+
var stepMatch = /^step([A-Z]\w*)$/;
|
|
1480
|
+
var m;
|
|
1481
|
+
for (var methodName in this) {
|
|
1482
|
+
if (typeof this[methodName] === "function" && (m = methodName.match(stepMatch))) {
|
|
1483
|
+
this.stepFunctions_[m[1]] = this[methodName].bind(this);
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
this.globalScope = this.createScope(this.ast, null);
|
|
1487
|
+
this.globalObject = this.globalScope.object;
|
|
1488
|
+
this.ast = this.parse_(this.polyfills_.join(`
|
|
1489
|
+
`), "polyfills");
|
|
1490
|
+
this.polyfills_ = undefined;
|
|
1491
|
+
Interpreter.stripLocations_(this.ast, undefined, undefined);
|
|
1492
|
+
var state = new Interpreter.State(this.ast, this.globalScope);
|
|
1493
|
+
state.done = false;
|
|
1494
|
+
this.stateStack = [state];
|
|
1495
|
+
this.run();
|
|
1496
|
+
this.value = undefined;
|
|
1497
|
+
this.ast = ast;
|
|
1498
|
+
state = new Interpreter.State(this.ast, this.globalScope);
|
|
1499
|
+
state.done = false;
|
|
1500
|
+
this.stateStack.length = 0;
|
|
1501
|
+
this.stateStack[0] = state;
|
|
1502
|
+
};
|
|
1503
|
+
Interpreter.Completion = {
|
|
1504
|
+
NORMAL: 0,
|
|
1505
|
+
BREAK: 1,
|
|
1506
|
+
CONTINUE: 2,
|
|
1507
|
+
RETURN: 3,
|
|
1508
|
+
THROW: 4
|
|
1509
|
+
};
|
|
1510
|
+
Interpreter.Status = {
|
|
1511
|
+
DONE: 0,
|
|
1512
|
+
STEP: 1,
|
|
1513
|
+
TASK: 2,
|
|
1514
|
+
ASYNC: 3
|
|
1515
|
+
};
|
|
1516
|
+
Interpreter.PARSE_OPTIONS = {
|
|
1517
|
+
locations: true,
|
|
1518
|
+
ecmaVersion: 5
|
|
1519
|
+
};
|
|
1520
|
+
Interpreter.READONLY_DESCRIPTOR = {
|
|
1521
|
+
configurable: true,
|
|
1522
|
+
enumerable: true,
|
|
1523
|
+
writable: false
|
|
1524
|
+
};
|
|
1525
|
+
Interpreter.NONENUMERABLE_DESCRIPTOR = {
|
|
1526
|
+
configurable: true,
|
|
1527
|
+
enumerable: false,
|
|
1528
|
+
writable: true
|
|
1529
|
+
};
|
|
1530
|
+
Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR = {
|
|
1531
|
+
configurable: true,
|
|
1532
|
+
enumerable: false,
|
|
1533
|
+
writable: false
|
|
1534
|
+
};
|
|
1535
|
+
Interpreter.NONCONFIGURABLE_READONLY_NONENUMERABLE_DESCRIPTOR = {
|
|
1536
|
+
configurable: false,
|
|
1537
|
+
enumerable: false,
|
|
1538
|
+
writable: false
|
|
1539
|
+
};
|
|
1540
|
+
Interpreter.VARIABLE_DESCRIPTOR = {
|
|
1541
|
+
configurable: false,
|
|
1542
|
+
enumerable: true,
|
|
1543
|
+
writable: true
|
|
1544
|
+
};
|
|
1545
|
+
Interpreter.STEP_ERROR = { STEP_ERROR: true };
|
|
1546
|
+
Interpreter.SCOPE_REFERENCE = { SCOPE_REFERENCE: true };
|
|
1547
|
+
Interpreter.VALUE_IN_DESCRIPTOR = {
|
|
1548
|
+
VALUE_IN_DESCRIPTOR: true
|
|
1549
|
+
};
|
|
1550
|
+
Interpreter.REGEXP_TIMEOUT = { REGEXP_TIMEOUT: true };
|
|
1551
|
+
Interpreter.toStringCycles_ = [];
|
|
1552
|
+
Interpreter.vm = null;
|
|
1553
|
+
Interpreter.currentInterpreter_ = null;
|
|
1554
|
+
Interpreter.nativeGlobal = typeof globalThis === "undefined" ? null : globalThis;
|
|
1555
|
+
Interpreter.WORKER_CODE = [
|
|
1556
|
+
"onmessage = function(e) {",
|
|
1557
|
+
"var result;",
|
|
1558
|
+
"var data = e.data;",
|
|
1559
|
+
"switch (data[0]) {",
|
|
1560
|
+
"case 'split':",
|
|
1561
|
+
"result = data[1].split(data[2], data[3]);",
|
|
1562
|
+
"break;",
|
|
1563
|
+
"case 'match':",
|
|
1564
|
+
"result = data[1].match(data[2]);",
|
|
1565
|
+
"break;",
|
|
1566
|
+
"case 'search':",
|
|
1567
|
+
"result = data[1].search(data[2]);",
|
|
1568
|
+
"break;",
|
|
1569
|
+
"case 'replace':",
|
|
1570
|
+
"result = data[1].replace(data[2], data[3]);",
|
|
1571
|
+
"break;",
|
|
1572
|
+
"case 'exec':",
|
|
1573
|
+
"var regexp = data[1];",
|
|
1574
|
+
"regexp.lastIndex = data[2];",
|
|
1575
|
+
"result = [regexp.exec(data[3]), data[1].lastIndex];",
|
|
1576
|
+
"break;",
|
|
1577
|
+
"default:",
|
|
1578
|
+
"throw Error('Unknown RegExp operation: ' + data[0]);",
|
|
1579
|
+
"}",
|
|
1580
|
+
"postMessage(result);",
|
|
1581
|
+
"close();",
|
|
1582
|
+
"};"
|
|
1583
|
+
];
|
|
1584
|
+
Interpreter.legalArrayLength = function(x) {
|
|
1585
|
+
var n = x >>> 0;
|
|
1586
|
+
return n === Number(x) ? n : NaN;
|
|
1587
|
+
};
|
|
1588
|
+
Interpreter.legalArrayIndex = function(x) {
|
|
1589
|
+
var n = x >>> 0;
|
|
1590
|
+
return String(n) === String(x) && n !== 4294967295 ? n : NaN;
|
|
1591
|
+
};
|
|
1592
|
+
Interpreter.stripLocations_ = function(node, start, end) {
|
|
1593
|
+
if (start) {
|
|
1594
|
+
node.start = start;
|
|
1595
|
+
} else {
|
|
1596
|
+
delete node.start;
|
|
1597
|
+
}
|
|
1598
|
+
if (end) {
|
|
1599
|
+
node.end = end;
|
|
1600
|
+
} else {
|
|
1601
|
+
delete node.end;
|
|
1602
|
+
}
|
|
1603
|
+
for (var name in node) {
|
|
1604
|
+
if (name !== "loc" && node.hasOwnProperty(name)) {
|
|
1605
|
+
var prop = node[name];
|
|
1606
|
+
if (prop && typeof prop === "object") {
|
|
1607
|
+
Interpreter.stripLocations_(prop, start, end);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
};
|
|
1612
|
+
Interpreter.prototype["REGEXP_MODE"] = 2;
|
|
1613
|
+
Interpreter.prototype["REGEXP_THREAD_TIMEOUT"] = 1000;
|
|
1614
|
+
Interpreter.prototype["POLYFILL_TIMEOUT"] = 1000;
|
|
1615
|
+
Interpreter.prototype.getterStep_ = false;
|
|
1616
|
+
Interpreter.prototype.setterStep_ = false;
|
|
1617
|
+
Interpreter.prototype.appendCodeNumber_ = 0;
|
|
1618
|
+
Interpreter.prototype.taskCodeNumber_ = 0;
|
|
1619
|
+
Interpreter.prototype.parse_ = function(code, sourceFile2) {
|
|
1620
|
+
var options2 = {};
|
|
1621
|
+
for (var name in Interpreter.PARSE_OPTIONS) {
|
|
1622
|
+
options2[name] = Interpreter.PARSE_OPTIONS[name];
|
|
1623
|
+
}
|
|
1624
|
+
options2.sourceFile = sourceFile2;
|
|
1625
|
+
return parse(code, options2);
|
|
1626
|
+
};
|
|
1627
|
+
Interpreter.prototype.appendCode = function(code) {
|
|
1628
|
+
var state = this.stateStack[0];
|
|
1629
|
+
if (!state || state.node.type !== "Program") {
|
|
1630
|
+
throw Error("Expecting original AST to start with a Program node");
|
|
1631
|
+
}
|
|
1632
|
+
if (typeof code === "string") {
|
|
1633
|
+
code = this.parse_(code, "appendCode" + this.appendCodeNumber_++);
|
|
1634
|
+
}
|
|
1635
|
+
if (!code || code.type !== "Program") {
|
|
1636
|
+
throw Error("Expecting new AST to start with a Program node");
|
|
1637
|
+
}
|
|
1638
|
+
this.populateScope_(code, state.scope);
|
|
1639
|
+
Array.prototype.push.apply(state.node.body, code.body);
|
|
1640
|
+
state.node.body.variableCache_ = null;
|
|
1641
|
+
state.done = false;
|
|
1642
|
+
};
|
|
1643
|
+
Interpreter.prototype.step = function() {
|
|
1644
|
+
var stack = this.stateStack;
|
|
1645
|
+
var endTime;
|
|
1646
|
+
do {
|
|
1647
|
+
var state = stack[stack.length - 1];
|
|
1648
|
+
if (this.paused_) {
|
|
1649
|
+
return true;
|
|
1650
|
+
} else if (!state || state.node.type === "Program" && state.done) {
|
|
1651
|
+
if (!this.tasks.length) {
|
|
1652
|
+
return false;
|
|
1653
|
+
}
|
|
1654
|
+
state = this.nextTask_();
|
|
1655
|
+
if (!state) {
|
|
1656
|
+
return true;
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
var node = state.node;
|
|
1660
|
+
var oldInterpreterValue = Interpreter.currentInterpreter_;
|
|
1661
|
+
Interpreter.currentInterpreter_ = this;
|
|
1662
|
+
try {
|
|
1663
|
+
var nextState = this.stepFunctions_[node.type](stack, state, node);
|
|
1664
|
+
} catch (e) {
|
|
1665
|
+
if (e !== Interpreter.STEP_ERROR) {
|
|
1666
|
+
if (this.value !== e) {
|
|
1667
|
+
this.value = undefined;
|
|
1668
|
+
}
|
|
1669
|
+
throw e;
|
|
1670
|
+
}
|
|
1671
|
+
} finally {
|
|
1672
|
+
Interpreter.currentInterpreter_ = oldInterpreterValue;
|
|
1673
|
+
}
|
|
1674
|
+
if (nextState) {
|
|
1675
|
+
stack.push(nextState);
|
|
1676
|
+
}
|
|
1677
|
+
if (this.getterStep_) {
|
|
1678
|
+
this.value = undefined;
|
|
1679
|
+
throw Error("Getter not supported in this context");
|
|
1680
|
+
}
|
|
1681
|
+
if (this.setterStep_) {
|
|
1682
|
+
this.value = undefined;
|
|
1683
|
+
throw Error("Setter not supported in this context");
|
|
1684
|
+
}
|
|
1685
|
+
if (!endTime && !node.end) {
|
|
1686
|
+
endTime = Date.now() + this["POLYFILL_TIMEOUT"];
|
|
1687
|
+
}
|
|
1688
|
+
} while (!node.end && endTime > Date.now());
|
|
1689
|
+
return true;
|
|
1690
|
+
};
|
|
1691
|
+
Interpreter.prototype.run = function() {
|
|
1692
|
+
while (!this.paused_ && this.step()) {}
|
|
1693
|
+
return this.paused_;
|
|
1694
|
+
};
|
|
1695
|
+
Interpreter.prototype.getStatus = function() {
|
|
1696
|
+
if (this.paused_) {
|
|
1697
|
+
return Interpreter.Status["ASYNC"];
|
|
1698
|
+
}
|
|
1699
|
+
var stack = this.stateStack;
|
|
1700
|
+
var state = stack[stack.length - 1];
|
|
1701
|
+
if (state && (state.node.type !== "Program" || !state.done)) {
|
|
1702
|
+
return Interpreter.Status["STEP"];
|
|
1703
|
+
}
|
|
1704
|
+
var task = this.tasks[0];
|
|
1705
|
+
if (task) {
|
|
1706
|
+
if (task.time > Date.now()) {
|
|
1707
|
+
return Interpreter.Status["TASK"];
|
|
1708
|
+
}
|
|
1709
|
+
return Interpreter.Status["STEP"];
|
|
1710
|
+
}
|
|
1711
|
+
return Interpreter.Status["DONE"];
|
|
1712
|
+
};
|
|
1713
|
+
Interpreter.prototype.initGlobal = function(globalObject) {
|
|
1714
|
+
this.setProperty(globalObject, "NaN", NaN, Interpreter.NONCONFIGURABLE_READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
1715
|
+
this.setProperty(globalObject, "Infinity", Infinity, Interpreter.NONCONFIGURABLE_READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
1716
|
+
this.setProperty(globalObject, "undefined", undefined, Interpreter.NONCONFIGURABLE_READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
1717
|
+
this.setProperty(globalObject, "window", globalObject, Interpreter.READONLY_DESCRIPTOR);
|
|
1718
|
+
this.setProperty(globalObject, "this", globalObject, Interpreter.NONCONFIGURABLE_READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
1719
|
+
this.setProperty(globalObject, "self", globalObject);
|
|
1720
|
+
this.OBJECT_PROTO = new Interpreter.Object(null);
|
|
1721
|
+
this.FUNCTION_PROTO = new Interpreter.Object(this.OBJECT_PROTO);
|
|
1722
|
+
this.initFunction(globalObject);
|
|
1723
|
+
this.initObject(globalObject);
|
|
1724
|
+
globalObject.proto = this.OBJECT_PROTO;
|
|
1725
|
+
this.setProperty(globalObject, "constructor", this.OBJECT, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1726
|
+
this.initArray(globalObject);
|
|
1727
|
+
this.initString(globalObject);
|
|
1728
|
+
this.initBoolean(globalObject);
|
|
1729
|
+
this.initNumber(globalObject);
|
|
1730
|
+
this.initDate(globalObject);
|
|
1731
|
+
this.initRegExp(globalObject);
|
|
1732
|
+
this.initError(globalObject);
|
|
1733
|
+
this.initMath(globalObject);
|
|
1734
|
+
this.initJSON(globalObject);
|
|
1735
|
+
var thisInterpreter = this;
|
|
1736
|
+
var wrapper;
|
|
1737
|
+
var func = this.createNativeFunction(function(_x) {
|
|
1738
|
+
throw EvalError("Can't happen");
|
|
1739
|
+
}, false);
|
|
1740
|
+
func.eval = true;
|
|
1741
|
+
this.setProperty(globalObject, "eval", func, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1742
|
+
this.setProperty(globalObject, "parseInt", this.createNativeFunction(parseInt, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1743
|
+
this.setProperty(globalObject, "parseFloat", this.createNativeFunction(parseFloat, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1744
|
+
this.setProperty(globalObject, "isNaN", this.createNativeFunction(isNaN, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1745
|
+
this.setProperty(globalObject, "isFinite", this.createNativeFunction(isFinite, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1746
|
+
var strFunctions = [
|
|
1747
|
+
[escape, "escape"],
|
|
1748
|
+
[unescape, "unescape"],
|
|
1749
|
+
[decodeURI, "decodeURI"],
|
|
1750
|
+
[decodeURIComponent, "decodeURIComponent"],
|
|
1751
|
+
[encodeURI, "encodeURI"],
|
|
1752
|
+
[encodeURIComponent, "encodeURIComponent"]
|
|
1753
|
+
];
|
|
1754
|
+
for (var i = 0;i < strFunctions.length; i++) {
|
|
1755
|
+
wrapper = function(nativeFunc) {
|
|
1756
|
+
return function(str) {
|
|
1757
|
+
try {
|
|
1758
|
+
return nativeFunc(str);
|
|
1759
|
+
} catch (e) {
|
|
1760
|
+
thisInterpreter.throwException(thisInterpreter.URI_ERROR, e.message);
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
}(strFunctions[i][0]);
|
|
1764
|
+
this.setProperty(globalObject, strFunctions[i][1], this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1765
|
+
}
|
|
1766
|
+
wrapper = function setTimeout2(var_args) {
|
|
1767
|
+
return thisInterpreter.createTask_(false, arguments);
|
|
1768
|
+
};
|
|
1769
|
+
this.setProperty(globalObject, "setTimeout", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1770
|
+
wrapper = function setInterval(var_args) {
|
|
1771
|
+
return thisInterpreter.createTask_(true, arguments);
|
|
1772
|
+
};
|
|
1773
|
+
this.setProperty(globalObject, "setInterval", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1774
|
+
wrapper = function clearTimeout2(pid) {
|
|
1775
|
+
thisInterpreter.deleteTask_(pid);
|
|
1776
|
+
};
|
|
1777
|
+
this.setProperty(globalObject, "clearTimeout", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1778
|
+
wrapper = function clearInterval(pid) {
|
|
1779
|
+
thisInterpreter.deleteTask_(pid);
|
|
1780
|
+
};
|
|
1781
|
+
this.setProperty(globalObject, "clearInterval", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1782
|
+
this["OBJECT"] = this.OBJECT;
|
|
1783
|
+
this["OBJECT_PROTO"] = this.OBJECT_PROTO;
|
|
1784
|
+
this["FUNCTION"] = this.FUNCTION;
|
|
1785
|
+
this["FUNCTION_PROTO"] = this.FUNCTION_PROTO;
|
|
1786
|
+
this["ARRAY"] = this.ARRAY;
|
|
1787
|
+
this["ARRAY_PROTO"] = this.ARRAY_PROTO;
|
|
1788
|
+
this["REGEXP"] = this.REGEXP;
|
|
1789
|
+
this["REGEXP_PROTO"] = this.REGEXP_PROTO;
|
|
1790
|
+
this["DATE"] = this.DATE;
|
|
1791
|
+
this["DATE_PROTO"] = this.DATE_PROTO;
|
|
1792
|
+
if (this.initFunc_) {
|
|
1793
|
+
this.initFunc_(this, globalObject);
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
Interpreter.prototype.functionCodeNumber_ = 0;
|
|
1797
|
+
Interpreter.prototype.initFunction = function(globalObject) {
|
|
1798
|
+
var thisInterpreter = this;
|
|
1799
|
+
var wrapper;
|
|
1800
|
+
var identifierRegexp = /^[A-Za-z_$][\w$]*$/;
|
|
1801
|
+
wrapper = function Function2(var_args) {
|
|
1802
|
+
if (arguments.length) {
|
|
1803
|
+
var code = String(arguments[arguments.length - 1]);
|
|
1804
|
+
} else {
|
|
1805
|
+
var code = "";
|
|
1806
|
+
}
|
|
1807
|
+
var argsStr = Array.prototype.slice.call(arguments, 0, -1).join(",").trim();
|
|
1808
|
+
if (argsStr) {
|
|
1809
|
+
var args = argsStr.split(/\s*,\s*/);
|
|
1810
|
+
for (var i = 0;i < args.length; i++) {
|
|
1811
|
+
var name = args[i];
|
|
1812
|
+
if (!identifierRegexp.test(name)) {
|
|
1813
|
+
thisInterpreter.throwException(thisInterpreter.SYNTAX_ERROR, "Invalid function argument: " + name);
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
argsStr = args.join(", ");
|
|
1817
|
+
}
|
|
1818
|
+
try {
|
|
1819
|
+
var ast = thisInterpreter.parse_("(function(" + argsStr + ") {" + code + "})", "function" + thisInterpreter.functionCodeNumber_++);
|
|
1820
|
+
} catch (e) {
|
|
1821
|
+
thisInterpreter.throwException(thisInterpreter.SYNTAX_ERROR, "Invalid code: " + e.message);
|
|
1822
|
+
}
|
|
1823
|
+
if (ast.body.length !== 1) {
|
|
1824
|
+
thisInterpreter.throwException(thisInterpreter.SYNTAX_ERROR, "Invalid code in function body");
|
|
1825
|
+
}
|
|
1826
|
+
var node = ast.body[0].expression;
|
|
1827
|
+
return thisInterpreter.createFunction(node, thisInterpreter.globalScope, "anonymous");
|
|
1828
|
+
};
|
|
1829
|
+
this.FUNCTION = this.createNativeFunction(wrapper, true);
|
|
1830
|
+
this.setProperty(globalObject, "Function", this.FUNCTION, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1831
|
+
this.setProperty(this.FUNCTION, "prototype", this.FUNCTION_PROTO, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1832
|
+
this.setProperty(this.FUNCTION_PROTO, "constructor", this.FUNCTION, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1833
|
+
this.FUNCTION_PROTO.nativeFunc = function() {};
|
|
1834
|
+
this.FUNCTION_PROTO.nativeFunc.id = this.functionCounter_++;
|
|
1835
|
+
this.FUNCTION_PROTO.illegalConstructor = true;
|
|
1836
|
+
this.setProperty(this.FUNCTION_PROTO, "length", 0, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
1837
|
+
this.FUNCTION_PROTO.class = "Function";
|
|
1838
|
+
wrapper = function apply(thisArg, args) {
|
|
1839
|
+
var state = thisInterpreter.stateStack[thisInterpreter.stateStack.length - 1];
|
|
1840
|
+
state.func_ = this;
|
|
1841
|
+
state.funcThis_ = thisArg;
|
|
1842
|
+
state.arguments_ = [];
|
|
1843
|
+
if (args !== null && args !== undefined) {
|
|
1844
|
+
if (args instanceof Interpreter.Object) {
|
|
1845
|
+
state.arguments_ = thisInterpreter.arrayPseudoToNative(args);
|
|
1846
|
+
} else {
|
|
1847
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, "CreateListFromArrayLike called on non-object");
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
state.doneExec_ = false;
|
|
1851
|
+
};
|
|
1852
|
+
this.setNativeFunctionPrototype(this.FUNCTION, "apply", wrapper);
|
|
1853
|
+
wrapper = function call(thisArg) {
|
|
1854
|
+
var state = thisInterpreter.stateStack[thisInterpreter.stateStack.length - 1];
|
|
1855
|
+
state.func_ = this;
|
|
1856
|
+
state.funcThis_ = thisArg;
|
|
1857
|
+
state.arguments_ = [];
|
|
1858
|
+
for (var i = 1;i < arguments.length; i++) {
|
|
1859
|
+
state.arguments_.push(arguments[i]);
|
|
1860
|
+
}
|
|
1861
|
+
state.doneExec_ = false;
|
|
1862
|
+
};
|
|
1863
|
+
this.setNativeFunctionPrototype(this.FUNCTION, "call", wrapper);
|
|
1864
|
+
this.polyfills_.push("Object.defineProperty(Function.prototype, 'bind',", "{configurable: true, writable: true, value:", "function bind(oThis) {", "if (typeof this !== 'function') {", "throw TypeError('What is trying to be bound is not callable');", "}", "var aArgs = Array.prototype.slice.call(arguments, 1),", "fToBind = this,", "fNOP = function() {},", "fBound = function() {", "return fToBind.apply(this instanceof fNOP", "? this", ": oThis,", "aArgs.concat(Array.prototype.slice.call(arguments)));", "};", "if (this.prototype) {", "fNOP.prototype = this.prototype;", "}", "fBound.prototype = new fNOP();", "return fBound;", "}", "});", "");
|
|
1865
|
+
wrapper = function toString() {
|
|
1866
|
+
return String(this);
|
|
1867
|
+
};
|
|
1868
|
+
this.setNativeFunctionPrototype(this.FUNCTION, "toString", wrapper);
|
|
1869
|
+
this.setProperty(this.FUNCTION, "toString", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1870
|
+
wrapper = function valueOf() {
|
|
1871
|
+
return this.valueOf();
|
|
1872
|
+
};
|
|
1873
|
+
this.setNativeFunctionPrototype(this.FUNCTION, "valueOf", wrapper);
|
|
1874
|
+
this.setProperty(this.FUNCTION, "valueOf", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1875
|
+
};
|
|
1876
|
+
Interpreter.prototype.initObject = function(globalObject) {
|
|
1877
|
+
var thisInterpreter = this;
|
|
1878
|
+
var wrapper;
|
|
1879
|
+
wrapper = function Object2(value) {
|
|
1880
|
+
if (value === undefined || value === null) {
|
|
1881
|
+
if (thisInterpreter.calledWithNew()) {
|
|
1882
|
+
return this;
|
|
1883
|
+
} else {
|
|
1884
|
+
return thisInterpreter.createObjectProto(thisInterpreter.OBJECT_PROTO);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
if (!(value instanceof Interpreter.Object)) {
|
|
1888
|
+
var box = thisInterpreter.createObjectProto(thisInterpreter.getPrototype(value));
|
|
1889
|
+
box.data = value;
|
|
1890
|
+
return box;
|
|
1891
|
+
}
|
|
1892
|
+
return value;
|
|
1893
|
+
};
|
|
1894
|
+
this.OBJECT = this.createNativeFunction(wrapper, true);
|
|
1895
|
+
this.setProperty(this.OBJECT, "prototype", this.OBJECT_PROTO, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1896
|
+
this.setProperty(this.OBJECT_PROTO, "constructor", this.OBJECT, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1897
|
+
this.setProperty(globalObject, "Object", this.OBJECT, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1898
|
+
var throwIfNullUndefined = function(value) {
|
|
1899
|
+
if (value === undefined || value === null) {
|
|
1900
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, "Cannot convert '" + value + "' to object");
|
|
1901
|
+
}
|
|
1902
|
+
};
|
|
1903
|
+
wrapper = function getOwnPropertyNames(obj) {
|
|
1904
|
+
throwIfNullUndefined(obj);
|
|
1905
|
+
var props = obj instanceof Interpreter.Object ? obj.properties : obj;
|
|
1906
|
+
return thisInterpreter.arrayNativeToPseudo(Object.getOwnPropertyNames(props));
|
|
1907
|
+
};
|
|
1908
|
+
this.setProperty(this.OBJECT, "getOwnPropertyNames", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1909
|
+
wrapper = function keys(obj) {
|
|
1910
|
+
throwIfNullUndefined(obj);
|
|
1911
|
+
if (obj instanceof Interpreter.Object) {
|
|
1912
|
+
obj = obj.properties;
|
|
1913
|
+
}
|
|
1914
|
+
return thisInterpreter.arrayNativeToPseudo(Object.keys(obj));
|
|
1915
|
+
};
|
|
1916
|
+
this.setProperty(this.OBJECT, "keys", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1917
|
+
wrapper = function create_(proto) {
|
|
1918
|
+
if (proto === null) {
|
|
1919
|
+
return thisInterpreter.createObjectProto(null);
|
|
1920
|
+
}
|
|
1921
|
+
if (!(proto instanceof Interpreter.Object)) {
|
|
1922
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, "Object prototype may only be an Object or null, not " + proto);
|
|
1923
|
+
}
|
|
1924
|
+
return thisInterpreter.createObjectProto(proto);
|
|
1925
|
+
};
|
|
1926
|
+
this.setProperty(this.OBJECT, "create", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1927
|
+
this.polyfills_.push("(function() {", "var create_ = Object.create;", "Object.create = function create(proto, props) {", "var obj = create_(proto);", "props && Object.defineProperties(obj, props);", "return obj;", "};", "})();", "");
|
|
1928
|
+
wrapper = function defineProperty(obj, prop, descriptor) {
|
|
1929
|
+
prop = String(prop);
|
|
1930
|
+
if (!(obj instanceof Interpreter.Object)) {
|
|
1931
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, "Object.defineProperty called on non-object: " + obj);
|
|
1932
|
+
}
|
|
1933
|
+
if (!(descriptor instanceof Interpreter.Object)) {
|
|
1934
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, "Property description must be an object");
|
|
1935
|
+
}
|
|
1936
|
+
if (obj.preventExtensions && !(prop in obj.properties)) {
|
|
1937
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, "Can't define property '" + prop + "', object is not extensible");
|
|
1938
|
+
}
|
|
1939
|
+
thisInterpreter.setProperty(obj, prop, Interpreter.VALUE_IN_DESCRIPTOR, descriptor.properties);
|
|
1940
|
+
return obj;
|
|
1941
|
+
};
|
|
1942
|
+
this.setProperty(this.OBJECT, "defineProperty", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1943
|
+
this.polyfills_.push("(function() {", "var defineProperty_ = Object.defineProperty;", "Object.defineProperty = function defineProperty(obj, prop, d1) {", "var d2 = {};", "if ('configurable' in d1) d2.configurable = d1.configurable;", "if ('enumerable' in d1) d2.enumerable = d1.enumerable;", "if ('writable' in d1) d2.writable = d1.writable;", "if ('value' in d1) d2.value = d1.value;", "if ('get' in d1) d2.get = d1.get;", "if ('set' in d1) d2.set = d1.set;", "return defineProperty_(obj, prop, d2);", "};", "})();", "Object.defineProperty(Object, 'defineProperties',", "{configurable: true, writable: true, value:", "function defineProperties(obj, props) {", "var keys = Object.keys(props);", "for (var i = 0; i < keys.length; i++) {", "Object.defineProperty(obj, keys[i], props[keys[i]]);", "}", "return obj;", "}", "});", "");
|
|
1944
|
+
wrapper = function getOwnPropertyDescriptor(obj, prop) {
|
|
1945
|
+
if (!(obj instanceof Interpreter.Object)) {
|
|
1946
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, "Object.getOwnPropertyDescriptor called on non-object: " + obj);
|
|
1947
|
+
}
|
|
1948
|
+
prop = String(prop);
|
|
1949
|
+
if (!(prop in obj.properties)) {
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
var descriptor = Object.getOwnPropertyDescriptor(obj.properties, prop);
|
|
1953
|
+
var getter = obj.getter[prop];
|
|
1954
|
+
var setter = obj.setter[prop];
|
|
1955
|
+
var pseudoDescriptor = thisInterpreter.createObjectProto(thisInterpreter.OBJECT_PROTO);
|
|
1956
|
+
if (getter || setter) {
|
|
1957
|
+
thisInterpreter.setProperty(pseudoDescriptor, "get", getter);
|
|
1958
|
+
thisInterpreter.setProperty(pseudoDescriptor, "set", setter);
|
|
1959
|
+
} else {
|
|
1960
|
+
thisInterpreter.setProperty(pseudoDescriptor, "value", descriptor["value"]);
|
|
1961
|
+
thisInterpreter.setProperty(pseudoDescriptor, "writable", descriptor["writable"]);
|
|
1962
|
+
}
|
|
1963
|
+
thisInterpreter.setProperty(pseudoDescriptor, "configurable", descriptor["configurable"]);
|
|
1964
|
+
thisInterpreter.setProperty(pseudoDescriptor, "enumerable", descriptor["enumerable"]);
|
|
1965
|
+
return pseudoDescriptor;
|
|
1966
|
+
};
|
|
1967
|
+
this.setProperty(this.OBJECT, "getOwnPropertyDescriptor", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1968
|
+
wrapper = function getPrototypeOf(obj) {
|
|
1969
|
+
throwIfNullUndefined(obj);
|
|
1970
|
+
return thisInterpreter.getPrototype(obj);
|
|
1971
|
+
};
|
|
1972
|
+
this.setProperty(this.OBJECT, "getPrototypeOf", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1973
|
+
wrapper = function isExtensible(obj) {
|
|
1974
|
+
return Boolean(obj) && !obj.preventExtensions;
|
|
1975
|
+
};
|
|
1976
|
+
this.setProperty(this.OBJECT, "isExtensible", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1977
|
+
wrapper = function preventExtensions(obj) {
|
|
1978
|
+
if (obj instanceof Interpreter.Object) {
|
|
1979
|
+
obj.preventExtensions = true;
|
|
1980
|
+
}
|
|
1981
|
+
return obj;
|
|
1982
|
+
};
|
|
1983
|
+
this.setProperty(this.OBJECT, "preventExtensions", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
1984
|
+
this.setNativeFunctionPrototype(this.OBJECT, "toString", Interpreter.Object.prototype.toString);
|
|
1985
|
+
this.setNativeFunctionPrototype(this.OBJECT, "toLocaleString", Interpreter.Object.prototype.toString);
|
|
1986
|
+
this.setNativeFunctionPrototype(this.OBJECT, "valueOf", Interpreter.Object.prototype.valueOf);
|
|
1987
|
+
wrapper = function hasOwnProperty(prop) {
|
|
1988
|
+
throwIfNullUndefined(this);
|
|
1989
|
+
if (this instanceof Interpreter.Object) {
|
|
1990
|
+
return String(prop) in this.properties;
|
|
1991
|
+
}
|
|
1992
|
+
return this.hasOwnProperty(prop);
|
|
1993
|
+
};
|
|
1994
|
+
this.setNativeFunctionPrototype(this.OBJECT, "hasOwnProperty", wrapper);
|
|
1995
|
+
wrapper = function propertyIsEnumerable(prop) {
|
|
1996
|
+
throwIfNullUndefined(this);
|
|
1997
|
+
if (this instanceof Interpreter.Object) {
|
|
1998
|
+
return Object.prototype.propertyIsEnumerable.call(this.properties, prop);
|
|
1999
|
+
}
|
|
2000
|
+
return this.propertyIsEnumerable(prop);
|
|
2001
|
+
};
|
|
2002
|
+
this.setNativeFunctionPrototype(this.OBJECT, "propertyIsEnumerable", wrapper);
|
|
2003
|
+
wrapper = function isPrototypeOf(obj) {
|
|
2004
|
+
while (true) {
|
|
2005
|
+
obj = thisInterpreter.getPrototype(obj);
|
|
2006
|
+
if (!obj) {
|
|
2007
|
+
return false;
|
|
2008
|
+
}
|
|
2009
|
+
if (obj === this) {
|
|
2010
|
+
return true;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
};
|
|
2014
|
+
this.setNativeFunctionPrototype(this.OBJECT, "isPrototypeOf", wrapper);
|
|
2015
|
+
};
|
|
2016
|
+
Interpreter.prototype.initArray = function(globalObject) {
|
|
2017
|
+
var thisInterpreter = this;
|
|
2018
|
+
var wrapper;
|
|
2019
|
+
wrapper = function Array2(var_args) {
|
|
2020
|
+
if (thisInterpreter.calledWithNew()) {
|
|
2021
|
+
var newArray = this;
|
|
2022
|
+
} else {
|
|
2023
|
+
var newArray = thisInterpreter.createArray();
|
|
2024
|
+
}
|
|
2025
|
+
var first = arguments[0];
|
|
2026
|
+
if (arguments.length === 1 && typeof first === "number") {
|
|
2027
|
+
if (isNaN(Interpreter.legalArrayLength(first))) {
|
|
2028
|
+
thisInterpreter.throwException(thisInterpreter.RANGE_ERROR, "Invalid array length: " + first);
|
|
2029
|
+
}
|
|
2030
|
+
newArray.properties.length = first;
|
|
2031
|
+
} else {
|
|
2032
|
+
for (var i = 0;i < arguments.length; i++) {
|
|
2033
|
+
newArray.properties[i] = arguments[i];
|
|
2034
|
+
}
|
|
2035
|
+
newArray.properties.length = i;
|
|
2036
|
+
}
|
|
2037
|
+
return newArray;
|
|
2038
|
+
};
|
|
2039
|
+
this.ARRAY = this.createNativeFunction(wrapper, true);
|
|
2040
|
+
this.ARRAY_PROTO = this.ARRAY.properties["prototype"];
|
|
2041
|
+
this.setProperty(globalObject, "Array", this.ARRAY, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2042
|
+
wrapper = function isArray(obj) {
|
|
2043
|
+
return obj && obj.class === "Array";
|
|
2044
|
+
};
|
|
2045
|
+
this.setProperty(this.ARRAY, "isArray", this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2046
|
+
this.setProperty(this.ARRAY_PROTO, "length", 0, {
|
|
2047
|
+
configurable: false,
|
|
2048
|
+
enumerable: false,
|
|
2049
|
+
writable: true
|
|
2050
|
+
});
|
|
2051
|
+
this.ARRAY_PROTO.class = "Array";
|
|
2052
|
+
this.polyfills_.push("(function() {", "function createArrayMethod_(f) {", "Object.defineProperty(Array.prototype, f.name,", "{configurable: true, writable: true, value: f});", "}", "createArrayMethod_(", "function pop() {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "if (!len || len < 0) {", "o.length = 0;", "return undefined;", "}", "len--;", "var x = o[len];", "delete o[len];", "o.length = len;", "return x;", "}", ");", "createArrayMethod_(", "function push(var_args) {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "for (var i = 0; i < arguments.length; i++) {", "o[len] = arguments[i];", "len++;", "}", "o.length = len;", "return len;", "}", ");", "createArrayMethod_(", "function shift() {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "if (!len || len < 0) {", "o.length = 0;", "return undefined;", "}", "var value = o[0];", "for (var i = 0; i < len - 1; i++) {", "if ((i + 1) in o) {", "o[i] = o[i + 1];", "} else {", "delete o[i];", "}", "}", "delete o[i];", "o.length = len - 1;", "return value;", "}", ");", "createArrayMethod_(", "function unshift(var_args) {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "if (!len || len < 0) {", "len = 0;", "}", "for (var i = len - 1; i >= 0; i--) {", "if (i in o) {", "o[i + arguments.length] = o[i];", "} else {", "delete o[i + arguments.length];", "}", "}", "for (var i = 0; i < arguments.length; i++) {", "o[i] = arguments[i];", "}", "return (o.length = len + arguments.length);", "}", ");", "createArrayMethod_(", "function reverse() {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "if (!len || len < 2) {", "return o;", "}", "for (var i = 0; i < len / 2 - 0.5; i++) {", "var x = o[i];", "var hasX = i in o;", "if ((len - i - 1) in o) {", "o[i] = o[len - i - 1];", "} else {", "delete o[i];", "}", "if (hasX) {", "o[len - i - 1] = x;", "} else {", "delete o[len - i - 1];", "}", "}", "return o;", "}", ");", "createArrayMethod_(", "function indexOf(searchElement, fromIndex) {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "var n = fromIndex | 0;", "if (!len || n >= len) {", "return -1;", "}", "var i = Math.max(n >= 0 ? n : len - Math.abs(n), 0);", "while (i < len) {", "if (i in o && o[i] === searchElement) {", "return i;", "}", "i++;", "}", "return -1;", "}", ");", "createArrayMethod_(", "function lastIndexOf(searchElement, fromIndex) {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "if (!len) {", "return -1;", "}", "var n = len - 1;", "if (arguments.length > 1) {", "n = fromIndex | 0;", "if (n) {", "n = (n > 0 || -1) * Math.floor(Math.abs(n));", "}", "}", "var i = n >= 0 ? Math.min(n, len - 1) : len - Math.abs(n);", "while (i >= 0) {", "if (i in o && o[i] === searchElement) {", "return i;", "}", "i--;", "}", "return -1;", "}", ");", "createArrayMethod_(", "function slice(start, end) {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "start |= 0;", "start = (start >= 0) ? start : Math.max(0, len + start);", "if (typeof end !== 'undefined') {", "if (end !== Infinity) {", "end |= 0;", "}", "if (end < 0) {", "end = len + end;", "} else {", "end = Math.min(end, len);", "}", "} else {", "end = len;", "}", "var size = end - start;", "var cloned = new Array(size);", "for (var i = 0; i < size; i++) {", "if ((start + i) in o) {", "cloned[i] = o[start + i];", "}", "}", "return cloned;", "}", ");", "createArrayMethod_(", "function splice(start, deleteCount, var_args) {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "start |= 0;", "if (start < 0) {", "start = Math.max(len + start, 0);", "} else {", "start = Math.min(start, len);", "}", "if (arguments.length < 1) {", "deleteCount = len - start;", "} else {", "deleteCount |= 0;", "deleteCount = Math.max(0, Math.min(deleteCount, len - start));", "}", "var removed = [];", "for (var i = start; i < start + deleteCount; i++) {", "if (i in o) {", "removed.push(o[i]);", "} else {", "removed.length++;", "}", "if ((i + deleteCount) in o) {", "o[i] = o[i + deleteCount];", "} else {", "delete o[i];", "}", "}", "for (var i = start + deleteCount; i < len - deleteCount; i++) {", "if ((i + deleteCount) in o) {", "o[i] = o[i + deleteCount];", "} else {", "delete o[i];", "}", "}", "for (var i = len - deleteCount; i < len; i++) {", "delete o[i];", "}", "len -= deleteCount;", "var arl = arguments.length - 2;", "for (var i = len - 1; i >= start; i--) {", "if (i in o) {", "o[i + arl] = o[i];", "} else {", "delete o[i + arl];", "}", "}", "len += arl;", "for (var i = 2; i < arguments.length; i++) {", "o[start + i - 2] = arguments[i];", "}", "o.length = len;", "return removed;", "}", ");", "createArrayMethod_(", "function concat(var_args) {", "if (!this) throw TypeError();", "var o = Object(this);", "var cloned = [];", "for (var i = -1; i < arguments.length; i++) {", "var value = (i === -1) ? o : arguments[i];", "if (Array.isArray(value)) {", "for (var j = 0, l = value.length; j < l; j++) {", "if (j in value) {", "cloned.push(value[j]);", "} else {", "cloned.length++;", "}", "}", "} else {", "cloned.push(value);", "}", "}", "return cloned;", "}", ");", "createArrayMethod_(", "function join(opt_separator) {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "var sep = typeof opt_separator === 'undefined' ?", "',' : ('' + opt_separator);", "var str = '';", "for (var i = 0; i < len; i++) {", "if (i && sep) str += sep;", "str += (o[i] === null || o[i] === undefined) ? '' : o[i];", "}", "return str;", "}", ");", "createArrayMethod_(", "function every(callbackfn, thisArg) {", "if (!this || typeof callbackfn !== 'function') throw TypeError();", "var t, k = 0;", "var o = Object(this), len = o.length >>> 0;", "if (arguments.length > 1) t = thisArg;", "while (k < len) {", "if (k in o && !callbackfn.call(t, o[k], k, o)) return false;", "k++;", "}", "return true;", "}", ");", "createArrayMethod_(", "function filter(fun, var_args) {", "if (this === void 0 || this === null || typeof fun !== 'function') throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "var res = [];", "var thisArg = arguments.length >= 2 ? arguments[1] : void 0;", "for (var i = 0; i < len; i++) {", "if (i in o) {", "var val = o[i];", "if (fun.call(thisArg, val, i, o)) res.push(val);", "}", "}", "return res;", "}", ");", "createArrayMethod_(", "function forEach(callback, thisArg) {", "if (!this || typeof callback !== 'function') throw TypeError();", "var t, k = 0;", "var o = Object(this), len = o.length >>> 0;", "if (arguments.length > 1) t = thisArg;", "while (k < len) {", "if (k in o) callback.call(t, o[k], k, o);", "k++;", "}", "}", ");", "createArrayMethod_(", "function map(callback, thisArg) {", "if (!this || typeof callback !== 'function') throw TypeError();", "var t, k = 0;", "var o = Object(this), len = o.length >>> 0;", "if (arguments.length > 1) t = thisArg;", "var a = new Array(len);", "while (k < len) {", "if (k in o) a[k] = callback.call(t, o[k], k, o);", "k++;", "}", "return a;", "}", ");", "createArrayMethod_(", "function reduce(callback /*, initialValue*/) {", "if (!this || typeof callback !== 'function') throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "var k = 0, value;", "if (arguments.length === 2) {", "value = arguments[1];", "} else {", "while (k < len && !(k in o)) k++;", "if (k >= len) {", "throw TypeError('Reduce of empty array with no initial value');", "}", "value = o[k++];", "}", "for (; k < len; k++) {", "if (k in o) value = callback(value, o[k], k, o);", "}", "return value;", "}", ");", "createArrayMethod_(", "function reduceRight(callback /*, initialValue*/) {", "if (null === this || 'undefined' === typeof this || 'function' !== typeof callback) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "var k = len - 1, value;", "if (arguments.length >= 2) {", "value = arguments[1];", "} else {", "while (k >= 0 && !(k in o)) k--;", "if (k < 0) {", "throw TypeError('Reduce of empty array with no initial value');", "}", "value = o[k--];", "}", "for (; k >= 0; k--) {", "if (k in o) value = callback(value, o[k], k, o);", "}", "return value;", "}", ");", "createArrayMethod_(", "function some(fun/*, thisArg*/) {", "if (!this || typeof fun !== 'function') throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "var thisArg = arguments.length >= 2 ? arguments[1] : void 0;", "for (var i = 0; i < len; i++) {", "if (i in o && fun.call(thisArg, o[i], i, o)) return true;", "}", "return false;", "}", ");", "createArrayMethod_(", "function sort(opt_comp) {", "if (!this) throw TypeError();", "if (typeof opt_comp !== 'function') {", "opt_comp = undefined;", "}", "for (var i = 0; i < this.length; i++) {", "var changes = 0;", "for (var j = 0; j < this.length - i - 1; j++) {", "if (opt_comp ? (opt_comp(this[j], this[j + 1]) > 0) :", "(String(this[j]) > String(this[j + 1]))) {", "var swap = this[j];", "var hasSwap = j in this;", "if ((j + 1) in this) {", "this[j] = this[j + 1];", "} else {", "delete this[j];", "}", "if (hasSwap) {", "this[j + 1] = swap;", "} else {", "delete this[j + 1];", "}", "changes++;", "}", "}", "if (!changes) break;", "}", "return this;", "}", ");", "createArrayMethod_(", "function toLocaleString() {", "if (!this) throw TypeError();", "var o = Object(this), len = o.length >>> 0;", "var out = [];", "for (var i = 0; i < len; i++) {", "out[i] = (o[i] === null || o[i] === undefined) ? '' : o[i].toLocaleString();", "}", "return out.join(',');", "}", ");", "})();", "");
|
|
2053
|
+
};
|
|
2054
|
+
Interpreter.prototype.initString = function(globalObject) {
|
|
2055
|
+
var thisInterpreter = this;
|
|
2056
|
+
var wrapper;
|
|
2057
|
+
wrapper = function String2(value) {
|
|
2058
|
+
value = arguments.length ? Interpreter.nativeGlobal.String(value) : "";
|
|
2059
|
+
if (thisInterpreter.calledWithNew()) {
|
|
2060
|
+
this.data = value;
|
|
2061
|
+
return this;
|
|
2062
|
+
} else {
|
|
2063
|
+
return value;
|
|
2064
|
+
}
|
|
2065
|
+
};
|
|
2066
|
+
this.STRING = this.createNativeFunction(wrapper, true);
|
|
2067
|
+
this.setProperty(globalObject, "String", this.STRING, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2068
|
+
this.setProperty(this.STRING, "fromCharCode", this.createNativeFunction(String.fromCharCode, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2069
|
+
var functions = [
|
|
2070
|
+
"charAt",
|
|
2071
|
+
"charCodeAt",
|
|
2072
|
+
"concat",
|
|
2073
|
+
"indexOf",
|
|
2074
|
+
"lastIndexOf",
|
|
2075
|
+
"slice",
|
|
2076
|
+
"substr",
|
|
2077
|
+
"substring",
|
|
2078
|
+
"toLocaleLowerCase",
|
|
2079
|
+
"toLocaleUpperCase",
|
|
2080
|
+
"toLowerCase",
|
|
2081
|
+
"toUpperCase",
|
|
2082
|
+
"trim"
|
|
2083
|
+
];
|
|
2084
|
+
for (var i = 0;i < functions.length; i++) {
|
|
2085
|
+
this.setNativeFunctionPrototype(this.STRING, functions[i], String.prototype[functions[i]]);
|
|
2086
|
+
}
|
|
2087
|
+
wrapper = function localeCompare(compareString, locales, options2) {
|
|
2088
|
+
locales = thisInterpreter.pseudoToNative(locales);
|
|
2089
|
+
options2 = thisInterpreter.pseudoToNative(options2);
|
|
2090
|
+
try {
|
|
2091
|
+
return String(this).localeCompare(compareString, locales, options2);
|
|
2092
|
+
} catch (e) {
|
|
2093
|
+
thisInterpreter.throwException(thisInterpreter.ERROR, "localeCompare: " + e.message);
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
this.setNativeFunctionPrototype(this.STRING, "localeCompare", wrapper);
|
|
2097
|
+
wrapper = function split(separator, limit, callback) {
|
|
2098
|
+
var string = String(this);
|
|
2099
|
+
limit = limit ? Number(limit) : undefined;
|
|
2100
|
+
if (thisInterpreter.isa(separator, thisInterpreter.REGEXP)) {
|
|
2101
|
+
separator = separator.data;
|
|
2102
|
+
thisInterpreter.maybeThrowRegExp(separator, callback);
|
|
2103
|
+
if (thisInterpreter["REGEXP_MODE"] === 2) {
|
|
2104
|
+
if (Interpreter.vm) {
|
|
2105
|
+
var sandbox = {
|
|
2106
|
+
string,
|
|
2107
|
+
separator,
|
|
2108
|
+
limit
|
|
2109
|
+
};
|
|
2110
|
+
var code = "string.split(separator, limit)";
|
|
2111
|
+
var jsList = thisInterpreter.vmCall(code, sandbox, separator, callback);
|
|
2112
|
+
if (jsList !== Interpreter.REGEXP_TIMEOUT) {
|
|
2113
|
+
callback(thisInterpreter.arrayNativeToPseudo(jsList));
|
|
2114
|
+
}
|
|
2115
|
+
} else {
|
|
2116
|
+
var splitWorker = thisInterpreter.createWorker();
|
|
2117
|
+
var pid = thisInterpreter.regExpTimeout(separator, splitWorker, callback);
|
|
2118
|
+
splitWorker.onmessage = function(e) {
|
|
2119
|
+
clearTimeout(pid);
|
|
2120
|
+
callback(thisInterpreter.arrayNativeToPseudo(e.data));
|
|
2121
|
+
};
|
|
2122
|
+
splitWorker.postMessage(["split", string, separator, limit]);
|
|
2123
|
+
}
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
var jsList = string.split(separator, limit);
|
|
2128
|
+
callback(thisInterpreter.arrayNativeToPseudo(jsList));
|
|
2129
|
+
};
|
|
2130
|
+
this.setAsyncFunctionPrototype(this.STRING, "split", wrapper);
|
|
2131
|
+
wrapper = function match(regexp, callback) {
|
|
2132
|
+
var string = String(this);
|
|
2133
|
+
regexp = thisInterpreter.isa(regexp, thisInterpreter.REGEXP) ? regexp.data : new RegExp(regexp);
|
|
2134
|
+
thisInterpreter.maybeThrowRegExp(regexp, callback);
|
|
2135
|
+
if (thisInterpreter["REGEXP_MODE"] === 2) {
|
|
2136
|
+
if (Interpreter.vm) {
|
|
2137
|
+
var sandbox = {
|
|
2138
|
+
string,
|
|
2139
|
+
regexp
|
|
2140
|
+
};
|
|
2141
|
+
var code = "string.match(regexp)";
|
|
2142
|
+
var m = thisInterpreter.vmCall(code, sandbox, regexp, callback);
|
|
2143
|
+
if (m !== Interpreter.REGEXP_TIMEOUT) {
|
|
2144
|
+
callback(m && thisInterpreter.arrayNativeToPseudo(m));
|
|
2145
|
+
}
|
|
2146
|
+
} else {
|
|
2147
|
+
var matchWorker = thisInterpreter.createWorker();
|
|
2148
|
+
var pid = thisInterpreter.regExpTimeout(regexp, matchWorker, callback);
|
|
2149
|
+
matchWorker.onmessage = function(e) {
|
|
2150
|
+
clearTimeout(pid);
|
|
2151
|
+
callback(e.data && thisInterpreter.arrayNativeToPseudo(e.data));
|
|
2152
|
+
};
|
|
2153
|
+
matchWorker.postMessage(["match", string, regexp]);
|
|
2154
|
+
}
|
|
2155
|
+
return;
|
|
2156
|
+
}
|
|
2157
|
+
var m = string.match(regexp);
|
|
2158
|
+
callback(m && thisInterpreter.arrayNativeToPseudo(m));
|
|
2159
|
+
};
|
|
2160
|
+
this.setAsyncFunctionPrototype(this.STRING, "match", wrapper);
|
|
2161
|
+
wrapper = function search(regexp, callback) {
|
|
2162
|
+
var string = String(this);
|
|
2163
|
+
if (thisInterpreter.isa(regexp, thisInterpreter.REGEXP)) {
|
|
2164
|
+
regexp = regexp.data;
|
|
2165
|
+
} else {
|
|
2166
|
+
regexp = new RegExp(regexp);
|
|
2167
|
+
}
|
|
2168
|
+
thisInterpreter.maybeThrowRegExp(regexp, callback);
|
|
2169
|
+
if (thisInterpreter["REGEXP_MODE"] === 2) {
|
|
2170
|
+
if (Interpreter.vm) {
|
|
2171
|
+
var sandbox = {
|
|
2172
|
+
string,
|
|
2173
|
+
regexp
|
|
2174
|
+
};
|
|
2175
|
+
var code = "string.search(regexp)";
|
|
2176
|
+
var n = thisInterpreter.vmCall(code, sandbox, regexp, callback);
|
|
2177
|
+
if (n !== Interpreter.REGEXP_TIMEOUT) {
|
|
2178
|
+
callback(n);
|
|
2179
|
+
}
|
|
2180
|
+
} else {
|
|
2181
|
+
var searchWorker = thisInterpreter.createWorker();
|
|
2182
|
+
var pid = thisInterpreter.regExpTimeout(regexp, searchWorker, callback);
|
|
2183
|
+
searchWorker.onmessage = function(e) {
|
|
2184
|
+
clearTimeout(pid);
|
|
2185
|
+
callback(e.data);
|
|
2186
|
+
};
|
|
2187
|
+
searchWorker.postMessage(["search", string, regexp]);
|
|
2188
|
+
}
|
|
2189
|
+
return;
|
|
2190
|
+
}
|
|
2191
|
+
callback(string.search(regexp));
|
|
2192
|
+
};
|
|
2193
|
+
this.setAsyncFunctionPrototype(this.STRING, "search", wrapper);
|
|
2194
|
+
wrapper = function replace_(substr, newSubstr, callback) {
|
|
2195
|
+
var string = String(this);
|
|
2196
|
+
newSubstr = String(newSubstr);
|
|
2197
|
+
if (thisInterpreter.isa(substr, thisInterpreter.REGEXP)) {
|
|
2198
|
+
substr = substr.data;
|
|
2199
|
+
thisInterpreter.maybeThrowRegExp(substr, callback);
|
|
2200
|
+
if (thisInterpreter["REGEXP_MODE"] === 2) {
|
|
2201
|
+
if (Interpreter.vm) {
|
|
2202
|
+
var sandbox = {
|
|
2203
|
+
string,
|
|
2204
|
+
substr,
|
|
2205
|
+
newSubstr
|
|
2206
|
+
};
|
|
2207
|
+
var code = "string.replace(substr, newSubstr)";
|
|
2208
|
+
var str = thisInterpreter.vmCall(code, sandbox, substr, callback);
|
|
2209
|
+
if (str !== Interpreter.REGEXP_TIMEOUT) {
|
|
2210
|
+
callback(str);
|
|
2211
|
+
}
|
|
2212
|
+
} else {
|
|
2213
|
+
var replaceWorker = thisInterpreter.createWorker();
|
|
2214
|
+
var pid = thisInterpreter.regExpTimeout(substr, replaceWorker, callback);
|
|
2215
|
+
replaceWorker.onmessage = function(e) {
|
|
2216
|
+
clearTimeout(pid);
|
|
2217
|
+
callback(e.data);
|
|
2218
|
+
};
|
|
2219
|
+
replaceWorker.postMessage(["replace", string, substr, newSubstr]);
|
|
2220
|
+
}
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
callback(string.replace(substr, newSubstr));
|
|
2225
|
+
};
|
|
2226
|
+
this.setAsyncFunctionPrototype(this.STRING, "replace", wrapper);
|
|
2227
|
+
this.polyfills_.push("(function() {", "var replace_ = String.prototype.replace;", "String.prototype.replace = function replace(substr, newSubstr) {", "if (typeof newSubstr !== 'function') {", "return replace_.call(this, substr, newSubstr);", "}", "var str = this;", "if (substr instanceof RegExp) {", "var subs = [];", "var m = substr.exec(str);", "while (m) {", "m.push(m.index, str);", "var inject = newSubstr.apply(null, m);", "subs.push([m.index, m[0].length, inject]);", "m = substr.global ? substr.exec(str) : null;", "}", "for (var i = subs.length - 1; i >= 0; i--) {", "str = str.substring(0, subs[i][0]) + subs[i][2] + " + "str.substring(subs[i][0] + subs[i][1]);", "}", "} else {", "var i = str.indexOf(substr);", "if (i !== -1) {", "var inject = newSubstr(str.substr(i, substr.length), i, str);", "str = str.substring(0, i) + inject + " + "str.substring(i + substr.length);", "}", "}", "return str;", "};", "})();", "");
|
|
2228
|
+
};
|
|
2229
|
+
Interpreter.prototype.initBoolean = function(globalObject) {
|
|
2230
|
+
var thisInterpreter = this;
|
|
2231
|
+
var wrapper;
|
|
2232
|
+
wrapper = function Boolean2(value) {
|
|
2233
|
+
value = Interpreter.nativeGlobal.Boolean(value);
|
|
2234
|
+
if (thisInterpreter.calledWithNew()) {
|
|
2235
|
+
this.data = value;
|
|
2236
|
+
return this;
|
|
2237
|
+
} else {
|
|
2238
|
+
return value;
|
|
2239
|
+
}
|
|
2240
|
+
};
|
|
2241
|
+
this.BOOLEAN = this.createNativeFunction(wrapper, true);
|
|
2242
|
+
this.setProperty(globalObject, "Boolean", this.BOOLEAN, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2243
|
+
};
|
|
2244
|
+
Interpreter.prototype.initNumber = function(globalObject) {
|
|
2245
|
+
var thisInterpreter = this;
|
|
2246
|
+
var wrapper;
|
|
2247
|
+
wrapper = function Number2(value) {
|
|
2248
|
+
value = arguments.length ? Interpreter.nativeGlobal.Number(value) : 0;
|
|
2249
|
+
if (thisInterpreter.calledWithNew()) {
|
|
2250
|
+
this.data = value;
|
|
2251
|
+
return this;
|
|
2252
|
+
} else {
|
|
2253
|
+
return value;
|
|
2254
|
+
}
|
|
2255
|
+
};
|
|
2256
|
+
this.NUMBER = this.createNativeFunction(wrapper, true);
|
|
2257
|
+
this.setProperty(globalObject, "Number", this.NUMBER, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2258
|
+
var numConsts = ["MAX_VALUE", "MIN_VALUE", "NaN", "NEGATIVE_INFINITY", "POSITIVE_INFINITY"];
|
|
2259
|
+
for (var i = 0;i < numConsts.length; i++) {
|
|
2260
|
+
this.setProperty(this.NUMBER, numConsts[i], Number[numConsts[i]], Interpreter.NONCONFIGURABLE_READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2261
|
+
}
|
|
2262
|
+
wrapper = function toExponential(fractionDigits) {
|
|
2263
|
+
try {
|
|
2264
|
+
return Number(this).toExponential(fractionDigits);
|
|
2265
|
+
} catch (e) {
|
|
2266
|
+
thisInterpreter.throwException(thisInterpreter.ERROR, e.message);
|
|
2267
|
+
}
|
|
2268
|
+
};
|
|
2269
|
+
this.setNativeFunctionPrototype(this.NUMBER, "toExponential", wrapper);
|
|
2270
|
+
wrapper = function toFixed(digits) {
|
|
2271
|
+
try {
|
|
2272
|
+
return Number(this).toFixed(digits);
|
|
2273
|
+
} catch (e) {
|
|
2274
|
+
thisInterpreter.throwException(thisInterpreter.ERROR, e.message);
|
|
2275
|
+
}
|
|
2276
|
+
};
|
|
2277
|
+
this.setNativeFunctionPrototype(this.NUMBER, "toFixed", wrapper);
|
|
2278
|
+
wrapper = function toPrecision(precision) {
|
|
2279
|
+
try {
|
|
2280
|
+
return Number(this).toPrecision(precision);
|
|
2281
|
+
} catch (e) {
|
|
2282
|
+
thisInterpreter.throwException(thisInterpreter.ERROR, e.message);
|
|
2283
|
+
}
|
|
2284
|
+
};
|
|
2285
|
+
this.setNativeFunctionPrototype(this.NUMBER, "toPrecision", wrapper);
|
|
2286
|
+
wrapper = function toString(radix) {
|
|
2287
|
+
try {
|
|
2288
|
+
return Number(this).toString(radix);
|
|
2289
|
+
} catch (e) {
|
|
2290
|
+
thisInterpreter.throwException(thisInterpreter.ERROR, e.message);
|
|
2291
|
+
}
|
|
2292
|
+
};
|
|
2293
|
+
this.setNativeFunctionPrototype(this.NUMBER, "toString", wrapper);
|
|
2294
|
+
wrapper = function toLocaleString(locales, options2) {
|
|
2295
|
+
locales = locales ? thisInterpreter.pseudoToNative(locales) : undefined;
|
|
2296
|
+
options2 = options2 ? thisInterpreter.pseudoToNative(options2) : undefined;
|
|
2297
|
+
try {
|
|
2298
|
+
return Number(this).toLocaleString(locales, options2);
|
|
2299
|
+
} catch (e) {
|
|
2300
|
+
thisInterpreter.throwException(thisInterpreter.ERROR, "toLocaleString: " + e.message);
|
|
2301
|
+
}
|
|
2302
|
+
};
|
|
2303
|
+
this.setNativeFunctionPrototype(this.NUMBER, "toLocaleString", wrapper);
|
|
2304
|
+
};
|
|
2305
|
+
Interpreter.prototype.initDate = function(globalObject) {
|
|
2306
|
+
var thisInterpreter = this;
|
|
2307
|
+
var wrapper;
|
|
2308
|
+
wrapper = function Date2(_value, var_args) {
|
|
2309
|
+
if (!thisInterpreter.calledWithNew()) {
|
|
2310
|
+
return Interpreter.nativeGlobal.Date();
|
|
2311
|
+
}
|
|
2312
|
+
var args = [null].concat(Array.from(arguments));
|
|
2313
|
+
this.data = new (Function.prototype.bind.apply(Interpreter.nativeGlobal.Date, args));
|
|
2314
|
+
return this;
|
|
2315
|
+
};
|
|
2316
|
+
this.DATE = this.createNativeFunction(wrapper, true);
|
|
2317
|
+
this.DATE_PROTO = this.DATE.properties["prototype"];
|
|
2318
|
+
this.setProperty(globalObject, "Date", this.DATE, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2319
|
+
this.setProperty(this.DATE, "now", this.createNativeFunction(Date.now, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2320
|
+
this.setProperty(this.DATE, "parse", this.createNativeFunction(Date.parse, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2321
|
+
this.setProperty(this.DATE, "UTC", this.createNativeFunction(Date.UTC, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2322
|
+
var functions = [
|
|
2323
|
+
"getDate",
|
|
2324
|
+
"getDay",
|
|
2325
|
+
"getFullYear",
|
|
2326
|
+
"getHours",
|
|
2327
|
+
"getMilliseconds",
|
|
2328
|
+
"getMinutes",
|
|
2329
|
+
"getMonth",
|
|
2330
|
+
"getSeconds",
|
|
2331
|
+
"getTime",
|
|
2332
|
+
"getTimezoneOffset",
|
|
2333
|
+
"getUTCDate",
|
|
2334
|
+
"getUTCDay",
|
|
2335
|
+
"getUTCFullYear",
|
|
2336
|
+
"getUTCHours",
|
|
2337
|
+
"getUTCMilliseconds",
|
|
2338
|
+
"getUTCMinutes",
|
|
2339
|
+
"getUTCMonth",
|
|
2340
|
+
"getUTCSeconds",
|
|
2341
|
+
"getYear",
|
|
2342
|
+
"setDate",
|
|
2343
|
+
"setFullYear",
|
|
2344
|
+
"setHours",
|
|
2345
|
+
"setMilliseconds",
|
|
2346
|
+
"setMinutes",
|
|
2347
|
+
"setMonth",
|
|
2348
|
+
"setSeconds",
|
|
2349
|
+
"setTime",
|
|
2350
|
+
"setUTCDate",
|
|
2351
|
+
"setUTCFullYear",
|
|
2352
|
+
"setUTCHours",
|
|
2353
|
+
"setUTCMilliseconds",
|
|
2354
|
+
"setUTCMinutes",
|
|
2355
|
+
"setUTCMonth",
|
|
2356
|
+
"setUTCSeconds",
|
|
2357
|
+
"setYear",
|
|
2358
|
+
"toDateString",
|
|
2359
|
+
"toISOString",
|
|
2360
|
+
"toJSON",
|
|
2361
|
+
"toGMTString",
|
|
2362
|
+
"toLocaleDateString",
|
|
2363
|
+
"toLocaleString",
|
|
2364
|
+
"toLocaleTimeString",
|
|
2365
|
+
"toTimeString",
|
|
2366
|
+
"toUTCString"
|
|
2367
|
+
];
|
|
2368
|
+
for (var i = 0;i < functions.length; i++) {
|
|
2369
|
+
wrapper = function(nativeFunc) {
|
|
2370
|
+
return function(var_args) {
|
|
2371
|
+
var date = this.data;
|
|
2372
|
+
if (!(date instanceof Date)) {
|
|
2373
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, nativeFunc + " not called on a Date");
|
|
2374
|
+
}
|
|
2375
|
+
var args = [];
|
|
2376
|
+
for (var i2 = 0;i2 < arguments.length; i2++) {
|
|
2377
|
+
args[i2] = thisInterpreter.pseudoToNative(arguments[i2]);
|
|
2378
|
+
}
|
|
2379
|
+
return date[nativeFunc].apply(date, args);
|
|
2380
|
+
};
|
|
2381
|
+
}(functions[i]);
|
|
2382
|
+
this.setNativeFunctionPrototype(this.DATE, functions[i], wrapper);
|
|
2383
|
+
}
|
|
2384
|
+
};
|
|
2385
|
+
Interpreter.prototype.initRegExp = function(globalObject) {
|
|
2386
|
+
var thisInterpreter = this;
|
|
2387
|
+
var wrapper;
|
|
2388
|
+
wrapper = function RegExp2(pattern, flags) {
|
|
2389
|
+
if (thisInterpreter.calledWithNew()) {
|
|
2390
|
+
var rgx = this;
|
|
2391
|
+
} else {
|
|
2392
|
+
if (flags === undefined && thisInterpreter.isa(pattern, thisInterpreter.REGEXP)) {
|
|
2393
|
+
return pattern;
|
|
2394
|
+
}
|
|
2395
|
+
var rgx = thisInterpreter.createObjectProto(thisInterpreter.REGEXP_PROTO);
|
|
2396
|
+
}
|
|
2397
|
+
pattern = pattern === undefined ? "" : String(pattern);
|
|
2398
|
+
flags = flags ? String(flags) : "";
|
|
2399
|
+
if (!/^[gmi]*$/.test(flags)) {
|
|
2400
|
+
thisInterpreter.throwException(thisInterpreter.SYNTAX_ERROR, "Invalid regexp flag: " + flags);
|
|
2401
|
+
}
|
|
2402
|
+
try {
|
|
2403
|
+
var nativeRegExp = new Interpreter.nativeGlobal.RegExp(pattern, flags);
|
|
2404
|
+
} catch (e) {
|
|
2405
|
+
thisInterpreter.throwException(thisInterpreter.SYNTAX_ERROR, e.message);
|
|
2406
|
+
}
|
|
2407
|
+
thisInterpreter.populateRegExp(rgx, nativeRegExp);
|
|
2408
|
+
return rgx;
|
|
2409
|
+
};
|
|
2410
|
+
this.REGEXP = this.createNativeFunction(wrapper, true);
|
|
2411
|
+
this.REGEXP_PROTO = this.REGEXP.properties["prototype"];
|
|
2412
|
+
this.setProperty(globalObject, "RegExp", this.REGEXP, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2413
|
+
this.setProperty(this.REGEXP.properties["prototype"], "global", undefined, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2414
|
+
this.setProperty(this.REGEXP.properties["prototype"], "ignoreCase", undefined, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2415
|
+
this.setProperty(this.REGEXP.properties["prototype"], "multiline", undefined, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2416
|
+
this.setProperty(this.REGEXP.properties["prototype"], "source", "(?:)", Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2417
|
+
this.polyfills_.push("Object.defineProperty(RegExp.prototype, 'test',", "{configurable: true, writable: true, value:", "function test(str) {", "return !!this.exec(str);", "}", "});");
|
|
2418
|
+
wrapper = function exec(string, callback) {
|
|
2419
|
+
var regexp = this.data;
|
|
2420
|
+
string = String(string);
|
|
2421
|
+
regexp.lastIndex = Number(thisInterpreter.getProperty(this, "lastIndex"));
|
|
2422
|
+
thisInterpreter.maybeThrowRegExp(regexp, callback);
|
|
2423
|
+
if (thisInterpreter["REGEXP_MODE"] === 2) {
|
|
2424
|
+
if (Interpreter.vm) {
|
|
2425
|
+
var sandbox = {
|
|
2426
|
+
string,
|
|
2427
|
+
regexp
|
|
2428
|
+
};
|
|
2429
|
+
var code = "regexp.exec(string)";
|
|
2430
|
+
var match = thisInterpreter.vmCall(code, sandbox, regexp, callback);
|
|
2431
|
+
if (match !== Interpreter.REGEXP_TIMEOUT) {
|
|
2432
|
+
thisInterpreter.setProperty(this, "lastIndex", regexp.lastIndex);
|
|
2433
|
+
callback(matchToPseudo(match));
|
|
2434
|
+
}
|
|
2435
|
+
} else {
|
|
2436
|
+
var execWorker = thisInterpreter.createWorker();
|
|
2437
|
+
var pid = thisInterpreter.regExpTimeout(regexp, execWorker, callback);
|
|
2438
|
+
var thisPseudoRegExp = this;
|
|
2439
|
+
execWorker.onmessage = function(e) {
|
|
2440
|
+
clearTimeout(pid);
|
|
2441
|
+
thisInterpreter.setProperty(thisPseudoRegExp, "lastIndex", e.data[1]);
|
|
2442
|
+
callback(matchToPseudo(e.data[0]));
|
|
2443
|
+
};
|
|
2444
|
+
execWorker.postMessage(["exec", regexp, regexp.lastIndex, string]);
|
|
2445
|
+
}
|
|
2446
|
+
return;
|
|
2447
|
+
}
|
|
2448
|
+
var match = regexp.exec(string);
|
|
2449
|
+
thisInterpreter.setProperty(this, "lastIndex", regexp.lastIndex);
|
|
2450
|
+
callback(matchToPseudo(match));
|
|
2451
|
+
function matchToPseudo(match2) {
|
|
2452
|
+
if (match2) {
|
|
2453
|
+
var result = thisInterpreter.arrayNativeToPseudo(match2);
|
|
2454
|
+
thisInterpreter.setProperty(result, "index", match2.index);
|
|
2455
|
+
thisInterpreter.setProperty(result, "input", match2.input);
|
|
2456
|
+
return result;
|
|
2457
|
+
}
|
|
2458
|
+
return null;
|
|
2459
|
+
}
|
|
2460
|
+
};
|
|
2461
|
+
this.setAsyncFunctionPrototype(this.REGEXP, "exec", wrapper);
|
|
2462
|
+
};
|
|
2463
|
+
Interpreter.prototype.initError = function(globalObject) {
|
|
2464
|
+
var thisInterpreter = this;
|
|
2465
|
+
this.ERROR = this.createNativeFunction(function Error2(opt_message) {
|
|
2466
|
+
if (thisInterpreter.calledWithNew()) {
|
|
2467
|
+
var newError = this;
|
|
2468
|
+
} else {
|
|
2469
|
+
var newError = thisInterpreter.createObject(thisInterpreter.ERROR);
|
|
2470
|
+
}
|
|
2471
|
+
thisInterpreter.populateError(newError, opt_message);
|
|
2472
|
+
return newError;
|
|
2473
|
+
}, true);
|
|
2474
|
+
this.setProperty(globalObject, "Error", this.ERROR, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2475
|
+
this.setProperty(this.ERROR.properties["prototype"], "message", "", Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2476
|
+
this.setProperty(this.ERROR.properties["prototype"], "name", "Error", Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2477
|
+
var createErrorSubclass = function(name) {
|
|
2478
|
+
var constructor = thisInterpreter.createNativeFunction(function(opt_message) {
|
|
2479
|
+
if (thisInterpreter.calledWithNew()) {
|
|
2480
|
+
var newError = this;
|
|
2481
|
+
} else {
|
|
2482
|
+
var newError = thisInterpreter.createObject(constructor);
|
|
2483
|
+
}
|
|
2484
|
+
thisInterpreter.populateError(newError, opt_message);
|
|
2485
|
+
return newError;
|
|
2486
|
+
}, true);
|
|
2487
|
+
thisInterpreter.setProperty(constructor, "prototype", thisInterpreter.createObject(thisInterpreter.ERROR), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2488
|
+
thisInterpreter.setProperty(constructor.properties["prototype"], "name", name, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2489
|
+
thisInterpreter.setProperty(globalObject, name, constructor, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2490
|
+
return constructor;
|
|
2491
|
+
};
|
|
2492
|
+
this.EVAL_ERROR = createErrorSubclass("EvalError");
|
|
2493
|
+
this.RANGE_ERROR = createErrorSubclass("RangeError");
|
|
2494
|
+
this.REFERENCE_ERROR = createErrorSubclass("ReferenceError");
|
|
2495
|
+
this.SYNTAX_ERROR = createErrorSubclass("SyntaxError");
|
|
2496
|
+
this.TYPE_ERROR = createErrorSubclass("TypeError");
|
|
2497
|
+
this.URI_ERROR = createErrorSubclass("URIError");
|
|
2498
|
+
};
|
|
2499
|
+
Interpreter.prototype.initMath = function(globalObject) {
|
|
2500
|
+
var myMath = this.createObjectProto(this.OBJECT_PROTO);
|
|
2501
|
+
this.setProperty(globalObject, "Math", myMath, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2502
|
+
var mathConsts = ["E", "LN2", "LN10", "LOG2E", "LOG10E", "PI", "SQRT1_2", "SQRT2"];
|
|
2503
|
+
for (var i = 0;i < mathConsts.length; i++) {
|
|
2504
|
+
this.setProperty(myMath, mathConsts[i], Math[mathConsts[i]], Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2505
|
+
}
|
|
2506
|
+
var numFunctions = [
|
|
2507
|
+
"abs",
|
|
2508
|
+
"acos",
|
|
2509
|
+
"asin",
|
|
2510
|
+
"atan",
|
|
2511
|
+
"atan2",
|
|
2512
|
+
"ceil",
|
|
2513
|
+
"cos",
|
|
2514
|
+
"exp",
|
|
2515
|
+
"floor",
|
|
2516
|
+
"log",
|
|
2517
|
+
"max",
|
|
2518
|
+
"min",
|
|
2519
|
+
"pow",
|
|
2520
|
+
"random",
|
|
2521
|
+
"round",
|
|
2522
|
+
"sin",
|
|
2523
|
+
"sqrt",
|
|
2524
|
+
"tan"
|
|
2525
|
+
];
|
|
2526
|
+
for (var i = 0;i < numFunctions.length; i++) {
|
|
2527
|
+
this.setProperty(myMath, numFunctions[i], this.createNativeFunction(Math[numFunctions[i]], false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2528
|
+
}
|
|
2529
|
+
};
|
|
2530
|
+
Interpreter.prototype.initJSON = function(globalObject) {
|
|
2531
|
+
var wrapper;
|
|
2532
|
+
var thisInterpreter = this;
|
|
2533
|
+
var myJSON = thisInterpreter.createObjectProto(this.OBJECT_PROTO);
|
|
2534
|
+
this.setProperty(globalObject, "JSON", myJSON, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2535
|
+
wrapper = function parse2(text) {
|
|
2536
|
+
try {
|
|
2537
|
+
var nativeObj = JSON.parse(String(text));
|
|
2538
|
+
} catch (e) {
|
|
2539
|
+
thisInterpreter.throwException(thisInterpreter.SYNTAX_ERROR, e.message);
|
|
2540
|
+
}
|
|
2541
|
+
return thisInterpreter.nativeToPseudo(nativeObj);
|
|
2542
|
+
};
|
|
2543
|
+
this.setProperty(myJSON, "parse", this.createNativeFunction(wrapper, false));
|
|
2544
|
+
wrapper = function stringify(value, replacer, space) {
|
|
2545
|
+
if (replacer && replacer.class === "Function") {
|
|
2546
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, "Function replacer on JSON.stringify not supported");
|
|
2547
|
+
} else if (replacer && replacer.class === "Array") {
|
|
2548
|
+
replacer = thisInterpreter.arrayPseudoToNative(replacer);
|
|
2549
|
+
replacer = replacer.filter(function(word) {
|
|
2550
|
+
return typeof word === "string" || typeof word === "number";
|
|
2551
|
+
});
|
|
2552
|
+
} else {
|
|
2553
|
+
replacer = null;
|
|
2554
|
+
}
|
|
2555
|
+
if (typeof space !== "string" && typeof space !== "number") {
|
|
2556
|
+
space = undefined;
|
|
2557
|
+
}
|
|
2558
|
+
var nativeObj = thisInterpreter.pseudoToNative(value);
|
|
2559
|
+
try {
|
|
2560
|
+
var str = JSON.stringify(nativeObj, replacer, space);
|
|
2561
|
+
} catch (e) {
|
|
2562
|
+
thisInterpreter.throwException(thisInterpreter.TYPE_ERROR, e.message);
|
|
2563
|
+
}
|
|
2564
|
+
return str;
|
|
2565
|
+
};
|
|
2566
|
+
this.setProperty(myJSON, "stringify", this.createNativeFunction(wrapper, false));
|
|
2567
|
+
};
|
|
2568
|
+
Interpreter.prototype.isa = function(child, constructor) {
|
|
2569
|
+
if (child === null || child === undefined || !constructor) {
|
|
2570
|
+
return false;
|
|
2571
|
+
}
|
|
2572
|
+
var proto = constructor.properties["prototype"];
|
|
2573
|
+
if (child === proto) {
|
|
2574
|
+
return true;
|
|
2575
|
+
}
|
|
2576
|
+
child = this.getPrototype(child);
|
|
2577
|
+
while (child) {
|
|
2578
|
+
if (child === proto) {
|
|
2579
|
+
return true;
|
|
2580
|
+
}
|
|
2581
|
+
child = child.proto;
|
|
2582
|
+
}
|
|
2583
|
+
return false;
|
|
2584
|
+
};
|
|
2585
|
+
Interpreter.prototype.populateRegExp = function(pseudoRegexp, nativeRegexp) {
|
|
2586
|
+
pseudoRegexp.data = new RegExp(nativeRegexp.source, nativeRegexp.flags);
|
|
2587
|
+
this.setProperty(pseudoRegexp, "lastIndex", nativeRegexp.lastIndex, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2588
|
+
this.setProperty(pseudoRegexp, "source", nativeRegexp.source, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2589
|
+
this.setProperty(pseudoRegexp, "global", nativeRegexp.global, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2590
|
+
this.setProperty(pseudoRegexp, "ignoreCase", nativeRegexp.ignoreCase, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2591
|
+
this.setProperty(pseudoRegexp, "multiline", nativeRegexp.multiline, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2592
|
+
};
|
|
2593
|
+
Interpreter.prototype.populateError = function(pseudoError, opt_message) {
|
|
2594
|
+
if (opt_message) {
|
|
2595
|
+
this.setProperty(pseudoError, "message", String(opt_message), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2596
|
+
}
|
|
2597
|
+
var tracebackData = [];
|
|
2598
|
+
for (var i = this.stateStack.length - 1;i >= 0; i--) {
|
|
2599
|
+
var state = this.stateStack[i];
|
|
2600
|
+
var node = state.node;
|
|
2601
|
+
if (node.type === "CallExpression") {
|
|
2602
|
+
var func = state.func_;
|
|
2603
|
+
if (func && tracebackData.length) {
|
|
2604
|
+
tracebackData[tracebackData.length - 1].datumName = this.getProperty(func, "name");
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
if (node.loc && (!tracebackData.length || node.type === "CallExpression")) {
|
|
2608
|
+
tracebackData.push({ datumLoc: node.loc });
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
var errorName = String(this.getProperty(pseudoError, "name"));
|
|
2612
|
+
var errorMessage = String(this.getProperty(pseudoError, "message"));
|
|
2613
|
+
var stackString = errorName + ": " + errorMessage + `
|
|
2614
|
+
`;
|
|
2615
|
+
for (var i = 0;i < tracebackData.length; i++) {
|
|
2616
|
+
var loc = tracebackData[i].datumLoc;
|
|
2617
|
+
var name = tracebackData[i].datumName;
|
|
2618
|
+
var locString = loc.source + ":" + loc.start.line + ":" + loc.start.column;
|
|
2619
|
+
if (name) {
|
|
2620
|
+
stackString += " at " + name + " (" + locString + `)
|
|
2621
|
+
`;
|
|
2622
|
+
} else {
|
|
2623
|
+
stackString += " at " + locString + `
|
|
2624
|
+
`;
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
this.setProperty(pseudoError, "stack", stackString.trim(), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2628
|
+
};
|
|
2629
|
+
Interpreter.prototype.createWorker = function() {
|
|
2630
|
+
var blob = this.createWorker.blob_;
|
|
2631
|
+
if (!blob) {
|
|
2632
|
+
blob = new Blob([Interpreter.WORKER_CODE.join(`
|
|
2633
|
+
`)], { type: "application/javascript" });
|
|
2634
|
+
this.createWorker.blob_ = blob;
|
|
2635
|
+
}
|
|
2636
|
+
return new Worker(URL.createObjectURL(blob));
|
|
2637
|
+
};
|
|
2638
|
+
Interpreter.prototype.vmCall = function(code, sandbox, nativeRegExp, callback) {
|
|
2639
|
+
var options2 = { timeout: this["REGEXP_THREAD_TIMEOUT"] };
|
|
2640
|
+
try {
|
|
2641
|
+
return Interpreter.vm["runInNewContext"](code, sandbox, options2);
|
|
2642
|
+
} catch (_e) {
|
|
2643
|
+
callback(null);
|
|
2644
|
+
this.throwException(this.ERROR, "RegExp Timeout: " + nativeRegExp);
|
|
2645
|
+
}
|
|
2646
|
+
return Interpreter.REGEXP_TIMEOUT;
|
|
2647
|
+
};
|
|
2648
|
+
Interpreter.prototype.maybeThrowRegExp = function(nativeRegExp, callback) {
|
|
2649
|
+
var ok;
|
|
2650
|
+
if (this["REGEXP_MODE"] === 0) {
|
|
2651
|
+
ok = false;
|
|
2652
|
+
} else if (this["REGEXP_MODE"] === 1) {
|
|
2653
|
+
ok = true;
|
|
2654
|
+
} else {
|
|
2655
|
+
if (Interpreter.vm) {
|
|
2656
|
+
ok = true;
|
|
2657
|
+
} else if (typeof Worker === "function" && typeof URL === "function") {
|
|
2658
|
+
ok = true;
|
|
2659
|
+
} else if (true) {
|
|
2660
|
+
try {
|
|
2661
|
+
Interpreter.vm = __require("vm");
|
|
2662
|
+
} catch (_e) {}
|
|
2663
|
+
ok = !!Interpreter.vm;
|
|
2664
|
+
} else {}
|
|
2665
|
+
}
|
|
2666
|
+
if (!ok) {
|
|
2667
|
+
callback(null);
|
|
2668
|
+
this.throwException(this.ERROR, "Regular expressions not supported: " + nativeRegExp);
|
|
2669
|
+
}
|
|
2670
|
+
};
|
|
2671
|
+
Interpreter.prototype.regExpTimeout = function(nativeRegExp, worker, callback) {
|
|
2672
|
+
var thisInterpreter = this;
|
|
2673
|
+
return setTimeout(function() {
|
|
2674
|
+
worker.terminate();
|
|
2675
|
+
callback(null);
|
|
2676
|
+
try {
|
|
2677
|
+
thisInterpreter.throwException(thisInterpreter.ERROR, "RegExp Timeout: " + nativeRegExp);
|
|
2678
|
+
} catch (_e) {}
|
|
2679
|
+
}, this["REGEXP_THREAD_TIMEOUT"]);
|
|
2680
|
+
};
|
|
2681
|
+
Interpreter.prototype.createObject = function(constructor) {
|
|
2682
|
+
return this.createObjectProto(constructor && constructor.properties["prototype"]);
|
|
2683
|
+
};
|
|
2684
|
+
Interpreter.prototype.createObjectProto = function(proto) {
|
|
2685
|
+
if (typeof proto !== "object") {
|
|
2686
|
+
throw Error("Non object prototype");
|
|
2687
|
+
}
|
|
2688
|
+
var obj = new Interpreter.Object(proto);
|
|
2689
|
+
if (this.isa(obj, this.ERROR)) {
|
|
2690
|
+
obj.class = "Error";
|
|
2691
|
+
}
|
|
2692
|
+
return obj;
|
|
2693
|
+
};
|
|
2694
|
+
Interpreter.prototype.createArray = function() {
|
|
2695
|
+
var array = this.createObjectProto(this.ARRAY_PROTO);
|
|
2696
|
+
this.setProperty(array, "length", 0, { configurable: false, enumerable: false, writable: true });
|
|
2697
|
+
array.class = "Array";
|
|
2698
|
+
return array;
|
|
2699
|
+
};
|
|
2700
|
+
Interpreter.prototype.createFunctionBase_ = function(argumentLength, isConstructor) {
|
|
2701
|
+
var func = this.createObjectProto(this.FUNCTION_PROTO);
|
|
2702
|
+
if (isConstructor) {
|
|
2703
|
+
var proto = this.createObjectProto(this.OBJECT_PROTO);
|
|
2704
|
+
this.setProperty(func, "prototype", proto, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2705
|
+
this.setProperty(proto, "constructor", func, Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
2706
|
+
} else {
|
|
2707
|
+
func.illegalConstructor = true;
|
|
2708
|
+
}
|
|
2709
|
+
this.setProperty(func, "length", argumentLength, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2710
|
+
func.class = "Function";
|
|
2711
|
+
return func;
|
|
2712
|
+
};
|
|
2713
|
+
Interpreter.prototype.createFunction = function(node, scope, opt_name) {
|
|
2714
|
+
var func = this.createFunctionBase_(node.params.length, true);
|
|
2715
|
+
func.parentScope = scope;
|
|
2716
|
+
func.node = node;
|
|
2717
|
+
var name = node.id ? String(node.id.name) : opt_name || "";
|
|
2718
|
+
this.setProperty(func, "name", name, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2719
|
+
return func;
|
|
2720
|
+
};
|
|
2721
|
+
Interpreter.prototype.createNativeFunction = function(nativeFunc, isConstructor) {
|
|
2722
|
+
var func = this.createFunctionBase_(nativeFunc.length, isConstructor);
|
|
2723
|
+
func.nativeFunc = nativeFunc;
|
|
2724
|
+
nativeFunc.id = this.functionCounter_++;
|
|
2725
|
+
this.setProperty(func, "name", nativeFunc.name, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2726
|
+
return func;
|
|
2727
|
+
};
|
|
2728
|
+
Interpreter.prototype.createAsyncFunction = function(asyncFunc) {
|
|
2729
|
+
var func = this.createFunctionBase_(asyncFunc.length, true);
|
|
2730
|
+
func.asyncFunc = asyncFunc;
|
|
2731
|
+
asyncFunc.id = this.functionCounter_++;
|
|
2732
|
+
this.setProperty(func, "name", asyncFunc.name, Interpreter.READONLY_NONENUMERABLE_DESCRIPTOR);
|
|
2733
|
+
return func;
|
|
2734
|
+
};
|
|
2735
|
+
Interpreter.prototype.nativeToPseudo = function(nativeObj) {
|
|
2736
|
+
if (nativeObj instanceof Interpreter.Object) {
|
|
2737
|
+
throw Error("Object is already pseudo");
|
|
2738
|
+
}
|
|
2739
|
+
if (nativeObj === null || nativeObj === undefined || nativeObj === true || nativeObj === false || typeof nativeObj === "string" || typeof nativeObj === "number") {
|
|
2740
|
+
return nativeObj;
|
|
2741
|
+
}
|
|
2742
|
+
if (nativeObj instanceof RegExp) {
|
|
2743
|
+
var pseudoRegexp = this.createObjectProto(this.REGEXP_PROTO);
|
|
2744
|
+
this.populateRegExp(pseudoRegexp, nativeObj);
|
|
2745
|
+
return pseudoRegexp;
|
|
2746
|
+
}
|
|
2747
|
+
if (nativeObj instanceof Date) {
|
|
2748
|
+
var pseudoDate = this.createObjectProto(this.DATE_PROTO);
|
|
2749
|
+
pseudoDate.data = new Date(nativeObj.valueOf());
|
|
2750
|
+
return pseudoDate;
|
|
2751
|
+
}
|
|
2752
|
+
if (typeof nativeObj === "function") {
|
|
2753
|
+
var thisInterpreter = this;
|
|
2754
|
+
var wrapper = function() {
|
|
2755
|
+
var args = Array.prototype.slice.call(arguments).map(function(i2) {
|
|
2756
|
+
return thisInterpreter.pseudoToNative(i2);
|
|
2757
|
+
});
|
|
2758
|
+
var value = nativeObj.apply(thisInterpreter, args);
|
|
2759
|
+
return thisInterpreter.nativeToPseudo(value);
|
|
2760
|
+
};
|
|
2761
|
+
var prototype = Object.getOwnPropertyDescriptor(nativeObj, "prototype");
|
|
2762
|
+
return this.createNativeFunction(wrapper, !!prototype);
|
|
2763
|
+
}
|
|
2764
|
+
if (Array.isArray(nativeObj)) {
|
|
2765
|
+
var pseudoArray = this.createArray();
|
|
2766
|
+
for (var i = 0;i < nativeObj.length; i++) {
|
|
2767
|
+
if (i in nativeObj) {
|
|
2768
|
+
this.setProperty(pseudoArray, i, this.nativeToPseudo(nativeObj[i]));
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
return pseudoArray;
|
|
2772
|
+
}
|
|
2773
|
+
var pseudoObj = this.createObjectProto(this.OBJECT_PROTO);
|
|
2774
|
+
for (var key in nativeObj) {
|
|
2775
|
+
this.setProperty(pseudoObj, key, this.nativeToPseudo(nativeObj[key]));
|
|
2776
|
+
}
|
|
2777
|
+
return pseudoObj;
|
|
2778
|
+
};
|
|
2779
|
+
Interpreter.prototype.pseudoToNative = function(pseudoObj, opt_cycles) {
|
|
2780
|
+
if (typeof pseudoObj !== "object" && typeof pseudoObj !== "function" || pseudoObj === null) {
|
|
2781
|
+
return pseudoObj;
|
|
2782
|
+
}
|
|
2783
|
+
if (!(pseudoObj instanceof Interpreter.Object)) {
|
|
2784
|
+
throw Error("Object is not pseudo");
|
|
2785
|
+
}
|
|
2786
|
+
if (this.isa(pseudoObj, this.REGEXP)) {
|
|
2787
|
+
var nativeRegExp = new RegExp(pseudoObj.data.source, pseudoObj.data.flags);
|
|
2788
|
+
nativeRegExp.lastIndex = pseudoObj.data.lastIndex;
|
|
2789
|
+
return nativeRegExp;
|
|
2790
|
+
}
|
|
2791
|
+
if (this.isa(pseudoObj, this.DATE)) {
|
|
2792
|
+
return new Date(pseudoObj.data.valueOf());
|
|
2793
|
+
}
|
|
2794
|
+
var cycles = opt_cycles || {
|
|
2795
|
+
pseudo: [],
|
|
2796
|
+
native: []
|
|
2797
|
+
};
|
|
2798
|
+
var index = cycles.pseudo.indexOf(pseudoObj);
|
|
2799
|
+
if (index !== -1) {
|
|
2800
|
+
return cycles.native[index];
|
|
2801
|
+
}
|
|
2802
|
+
cycles.pseudo.push(pseudoObj);
|
|
2803
|
+
var nativeObj;
|
|
2804
|
+
if (this.isa(pseudoObj, this.ARRAY)) {
|
|
2805
|
+
nativeObj = [];
|
|
2806
|
+
cycles.native.push(nativeObj);
|
|
2807
|
+
var len = this.getProperty(pseudoObj, "length");
|
|
2808
|
+
for (var i = 0;i < len; i++) {
|
|
2809
|
+
if (this.hasProperty(pseudoObj, i)) {
|
|
2810
|
+
nativeObj[i] = this.pseudoToNative(this.getProperty(pseudoObj, i), cycles);
|
|
2811
|
+
}
|
|
2812
|
+
}
|
|
2813
|
+
} else {
|
|
2814
|
+
nativeObj = {};
|
|
2815
|
+
cycles.native.push(nativeObj);
|
|
2816
|
+
var val;
|
|
2817
|
+
for (var key in pseudoObj.properties) {
|
|
2818
|
+
val = this.pseudoToNative(pseudoObj.properties[key], cycles);
|
|
2819
|
+
Object.defineProperty(nativeObj, key, {
|
|
2820
|
+
value: val,
|
|
2821
|
+
writable: true,
|
|
2822
|
+
enumerable: true,
|
|
2823
|
+
configurable: true
|
|
2824
|
+
});
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
cycles.pseudo.pop();
|
|
2828
|
+
cycles.native.pop();
|
|
2829
|
+
return nativeObj;
|
|
2830
|
+
};
|
|
2831
|
+
Interpreter.prototype.arrayNativeToPseudo = function(nativeArray) {
|
|
2832
|
+
var pseudoArray = this.createArray();
|
|
2833
|
+
var props = Object.getOwnPropertyNames(nativeArray);
|
|
2834
|
+
for (var i = 0;i < props.length; i++) {
|
|
2835
|
+
this.setProperty(pseudoArray, props[i], nativeArray[props[i]]);
|
|
2836
|
+
}
|
|
2837
|
+
return pseudoArray;
|
|
2838
|
+
};
|
|
2839
|
+
Interpreter.prototype.arrayPseudoToNative = function(pseudoArray) {
|
|
2840
|
+
var nativeArray = [];
|
|
2841
|
+
for (var key in pseudoArray.properties) {
|
|
2842
|
+
nativeArray[key] = this.getProperty(pseudoArray, key);
|
|
2843
|
+
}
|
|
2844
|
+
nativeArray.length = Interpreter.legalArrayLength(this.getProperty(pseudoArray, "length")) || 0;
|
|
2845
|
+
return nativeArray;
|
|
2846
|
+
};
|
|
2847
|
+
Interpreter.prototype.getPrototype = function(value) {
|
|
2848
|
+
switch (typeof value) {
|
|
2849
|
+
case "number":
|
|
2850
|
+
return this.NUMBER.properties["prototype"];
|
|
2851
|
+
case "boolean":
|
|
2852
|
+
return this.BOOLEAN.properties["prototype"];
|
|
2853
|
+
case "string":
|
|
2854
|
+
return this.STRING.properties["prototype"];
|
|
2855
|
+
}
|
|
2856
|
+
if (value) {
|
|
2857
|
+
return value.proto;
|
|
2858
|
+
}
|
|
2859
|
+
return null;
|
|
2860
|
+
};
|
|
2861
|
+
Interpreter.prototype.getProperty = function(obj, name) {
|
|
2862
|
+
if (this.getterStep_) {
|
|
2863
|
+
throw Error("Getter not supported in that context");
|
|
2864
|
+
}
|
|
2865
|
+
name = String(name);
|
|
2866
|
+
if (obj === undefined || obj === null) {
|
|
2867
|
+
this.throwException(this.TYPE_ERROR, "Cannot read property '" + name + "' of " + obj);
|
|
2868
|
+
}
|
|
2869
|
+
if (typeof obj === "object" && !(obj instanceof Interpreter.Object)) {
|
|
2870
|
+
throw TypeError("Expecting native value or pseudo object");
|
|
2871
|
+
}
|
|
2872
|
+
if (name === "length") {
|
|
2873
|
+
if (this.isa(obj, this.STRING)) {
|
|
2874
|
+
return String(obj).length;
|
|
2875
|
+
}
|
|
2876
|
+
} else if (name.charCodeAt(0) < 64) {
|
|
2877
|
+
if (this.isa(obj, this.STRING)) {
|
|
2878
|
+
var n = Interpreter.legalArrayIndex(name);
|
|
2879
|
+
if (!isNaN(n) && n < String(obj).length) {
|
|
2880
|
+
return String(obj)[n];
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
do {
|
|
2885
|
+
if (obj.properties && name in obj.properties) {
|
|
2886
|
+
var getter = obj.getter[name];
|
|
2887
|
+
if (getter) {
|
|
2888
|
+
this.getterStep_ = true;
|
|
2889
|
+
return getter;
|
|
2890
|
+
}
|
|
2891
|
+
return obj.properties[name];
|
|
2892
|
+
}
|
|
2893
|
+
} while (obj = this.getPrototype(obj));
|
|
2894
|
+
return;
|
|
2895
|
+
};
|
|
2896
|
+
Interpreter.prototype.hasProperty = function(obj, name) {
|
|
2897
|
+
if (!(obj instanceof Interpreter.Object)) {
|
|
2898
|
+
throw TypeError("Primitive data type has no properties");
|
|
2899
|
+
}
|
|
2900
|
+
name = String(name);
|
|
2901
|
+
if (name === "length" && this.isa(obj, this.STRING)) {
|
|
2902
|
+
return true;
|
|
2903
|
+
}
|
|
2904
|
+
if (this.isa(obj, this.STRING)) {
|
|
2905
|
+
var n = Interpreter.legalArrayIndex(name);
|
|
2906
|
+
if (!isNaN(n) && n < String(obj).length) {
|
|
2907
|
+
return true;
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
do {
|
|
2911
|
+
if (obj.properties && name in obj.properties) {
|
|
2912
|
+
return true;
|
|
2913
|
+
}
|
|
2914
|
+
} while (obj = this.getPrototype(obj));
|
|
2915
|
+
return false;
|
|
2916
|
+
};
|
|
2917
|
+
Interpreter.prototype.setProperty = function(obj, name, value, opt_descriptor) {
|
|
2918
|
+
if (this.setterStep_) {
|
|
2919
|
+
throw Error("Setter not supported in that context");
|
|
2920
|
+
}
|
|
2921
|
+
name = String(name);
|
|
2922
|
+
if (obj === undefined || obj === null) {
|
|
2923
|
+
this.throwException(this.TYPE_ERROR, "Cannot set property '" + name + "' of " + obj);
|
|
2924
|
+
}
|
|
2925
|
+
if (typeof obj === "object" && !(obj instanceof Interpreter.Object)) {
|
|
2926
|
+
throw TypeError("Expecting native value or pseudo object");
|
|
2927
|
+
}
|
|
2928
|
+
if (opt_descriptor && (("get" in opt_descriptor) || ("set" in opt_descriptor)) && (("value" in opt_descriptor) || ("writable" in opt_descriptor))) {
|
|
2929
|
+
this.throwException(this.TYPE_ERROR, "Invalid property descriptor. " + "Cannot both specify accessors and a value or writable attribute");
|
|
2930
|
+
}
|
|
2931
|
+
var strict2 = !this.stateStack || this.getScope().strict;
|
|
2932
|
+
if (!(obj instanceof Interpreter.Object)) {
|
|
2933
|
+
if (strict2) {
|
|
2934
|
+
this.throwException(this.TYPE_ERROR, "Can't create property '" + name + "' on '" + obj + "'");
|
|
2935
|
+
}
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
if (this.isa(obj, this.STRING)) {
|
|
2939
|
+
var n = Interpreter.legalArrayIndex(name);
|
|
2940
|
+
if (name === "length" || !isNaN(n) && n < String(obj).length) {
|
|
2941
|
+
if (strict2) {
|
|
2942
|
+
this.throwException(this.TYPE_ERROR, "Cannot assign to read only " + "property '" + name + "' of String '" + obj.data + "'");
|
|
2943
|
+
}
|
|
2944
|
+
return;
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
if (obj.class === "Array") {
|
|
2948
|
+
var len = obj.properties.length;
|
|
2949
|
+
var i;
|
|
2950
|
+
if (name === "length") {
|
|
2951
|
+
if (opt_descriptor) {
|
|
2952
|
+
if (!("value" in opt_descriptor)) {
|
|
2953
|
+
return;
|
|
2954
|
+
}
|
|
2955
|
+
value = opt_descriptor["value"];
|
|
2956
|
+
}
|
|
2957
|
+
value = Interpreter.legalArrayLength(value);
|
|
2958
|
+
if (isNaN(value)) {
|
|
2959
|
+
this.throwException(this.RANGE_ERROR, "Invalid array length");
|
|
2960
|
+
}
|
|
2961
|
+
if (value < len) {
|
|
2962
|
+
for (i in obj.properties) {
|
|
2963
|
+
i = Interpreter.legalArrayIndex(i);
|
|
2964
|
+
if (!isNaN(i) && value <= i) {
|
|
2965
|
+
delete obj.properties[i];
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
} else if (!isNaN(i = Interpreter.legalArrayIndex(name))) {
|
|
2970
|
+
obj.properties.length = Math.max(len, i + 1);
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
if (obj.preventExtensions && !(name in obj.properties)) {
|
|
2974
|
+
if (strict2) {
|
|
2975
|
+
this.throwException(this.TYPE_ERROR, "Can't add property '" + name + "', object is not extensible");
|
|
2976
|
+
}
|
|
2977
|
+
return;
|
|
2978
|
+
}
|
|
2979
|
+
if (opt_descriptor) {
|
|
2980
|
+
var descriptor = {};
|
|
2981
|
+
if ("get" in opt_descriptor && opt_descriptor["get"]) {
|
|
2982
|
+
obj.getter[name] = opt_descriptor["get"];
|
|
2983
|
+
descriptor["get"] = this.setProperty.placeholderGet_;
|
|
2984
|
+
}
|
|
2985
|
+
if ("set" in opt_descriptor && opt_descriptor["set"]) {
|
|
2986
|
+
obj.setter[name] = opt_descriptor["set"];
|
|
2987
|
+
descriptor["set"] = this.setProperty.placeholderSet_;
|
|
2988
|
+
}
|
|
2989
|
+
if ("configurable" in opt_descriptor) {
|
|
2990
|
+
descriptor["configurable"] = opt_descriptor["configurable"];
|
|
2991
|
+
}
|
|
2992
|
+
if ("enumerable" in opt_descriptor) {
|
|
2993
|
+
descriptor["enumerable"] = opt_descriptor["enumerable"];
|
|
2994
|
+
}
|
|
2995
|
+
if ("writable" in opt_descriptor) {
|
|
2996
|
+
descriptor["writable"] = opt_descriptor["writable"];
|
|
2997
|
+
delete obj.getter[name];
|
|
2998
|
+
delete obj.setter[name];
|
|
2999
|
+
}
|
|
3000
|
+
if ("value" in opt_descriptor) {
|
|
3001
|
+
descriptor["value"] = opt_descriptor["value"];
|
|
3002
|
+
delete obj.getter[name];
|
|
3003
|
+
delete obj.setter[name];
|
|
3004
|
+
} else if (value !== Interpreter.VALUE_IN_DESCRIPTOR) {
|
|
3005
|
+
descriptor["value"] = value;
|
|
3006
|
+
delete obj.getter[name];
|
|
3007
|
+
delete obj.setter[name];
|
|
3008
|
+
}
|
|
3009
|
+
try {
|
|
3010
|
+
Object.defineProperty(obj.properties, name, descriptor);
|
|
3011
|
+
} catch (e) {
|
|
3012
|
+
this.throwException(this.TYPE_ERROR, "Cannot redefine property: " + name);
|
|
3013
|
+
}
|
|
3014
|
+
if ("get" in opt_descriptor && !opt_descriptor["get"]) {
|
|
3015
|
+
delete obj.getter[name];
|
|
3016
|
+
}
|
|
3017
|
+
if ("set" in opt_descriptor && !opt_descriptor["set"]) {
|
|
3018
|
+
delete obj.setter[name];
|
|
3019
|
+
}
|
|
3020
|
+
} else {
|
|
3021
|
+
if (value === Interpreter.VALUE_IN_DESCRIPTOR) {
|
|
3022
|
+
throw ReferenceError("Value not specified");
|
|
3023
|
+
}
|
|
3024
|
+
var defObj = obj;
|
|
3025
|
+
while (!(name in defObj.properties)) {
|
|
3026
|
+
defObj = this.getPrototype(defObj);
|
|
3027
|
+
if (!defObj) {
|
|
3028
|
+
defObj = obj;
|
|
3029
|
+
break;
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
if (defObj.setter && defObj.setter[name]) {
|
|
3033
|
+
this.setterStep_ = true;
|
|
3034
|
+
return defObj.setter[name];
|
|
3035
|
+
}
|
|
3036
|
+
if (defObj.getter && defObj.getter[name]) {
|
|
3037
|
+
if (strict2) {
|
|
3038
|
+
this.throwException(this.TYPE_ERROR, "Cannot set property '" + name + "' of object '" + obj + "' which only has a getter");
|
|
3039
|
+
}
|
|
3040
|
+
} else {
|
|
3041
|
+
try {
|
|
3042
|
+
obj.properties[name] = value;
|
|
3043
|
+
} catch (_e) {
|
|
3044
|
+
if (strict2) {
|
|
3045
|
+
this.throwException(this.TYPE_ERROR, "Cannot assign to read only " + "property '" + name + "' of object '" + obj + "'");
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
};
|
|
3051
|
+
Interpreter.prototype.setProperty.placeholderGet_ = function() {
|
|
3052
|
+
throw Error("Placeholder getter");
|
|
3053
|
+
};
|
|
3054
|
+
Interpreter.prototype.setProperty.placeholderSet_ = function() {
|
|
3055
|
+
throw Error("Placeholder setter");
|
|
3056
|
+
};
|
|
3057
|
+
Interpreter.prototype.setNativeFunctionPrototype = function(obj, name, wrapper) {
|
|
3058
|
+
this.setProperty(obj.properties["prototype"], name, this.createNativeFunction(wrapper, false), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
3059
|
+
};
|
|
3060
|
+
Interpreter.prototype.setAsyncFunctionPrototype = function(obj, name, wrapper) {
|
|
3061
|
+
this.setProperty(obj.properties["prototype"], name, this.createAsyncFunction(wrapper), Interpreter.NONENUMERABLE_DESCRIPTOR);
|
|
3062
|
+
};
|
|
3063
|
+
Interpreter.prototype.getScope = function() {
|
|
3064
|
+
var scope = this.stateStack[this.stateStack.length - 1].scope;
|
|
3065
|
+
if (!scope) {
|
|
3066
|
+
throw Error("No scope found");
|
|
3067
|
+
}
|
|
3068
|
+
return scope;
|
|
3069
|
+
};
|
|
3070
|
+
Interpreter.prototype.createScope = function(node, parentScope) {
|
|
3071
|
+
var strict2 = false;
|
|
3072
|
+
if (parentScope && parentScope.strict) {
|
|
3073
|
+
strict2 = true;
|
|
3074
|
+
} else {
|
|
3075
|
+
var firstNode = node.body && node.body[0];
|
|
3076
|
+
if (firstNode && firstNode.expression && firstNode.expression.type === "Literal" && firstNode.expression.value === "use strict") {
|
|
3077
|
+
strict2 = true;
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
var object = this.createObjectProto(null);
|
|
3081
|
+
var scope = new Interpreter.Scope(parentScope, strict2, object);
|
|
3082
|
+
if (!parentScope) {
|
|
3083
|
+
this.initGlobal(scope.object);
|
|
3084
|
+
}
|
|
3085
|
+
this.populateScope_(node, scope);
|
|
3086
|
+
return scope;
|
|
3087
|
+
};
|
|
3088
|
+
Interpreter.prototype.createSpecialScope = function(parentScope, opt_object) {
|
|
3089
|
+
if (!parentScope) {
|
|
3090
|
+
throw Error("parentScope required");
|
|
3091
|
+
}
|
|
3092
|
+
var object = opt_object || this.createObjectProto(null);
|
|
3093
|
+
return new Interpreter.Scope(parentScope, parentScope.strict, object);
|
|
3094
|
+
};
|
|
3095
|
+
Interpreter.prototype.getValueFromScope = function(name) {
|
|
3096
|
+
var scope = this.getScope();
|
|
3097
|
+
while (scope && scope !== this.globalScope) {
|
|
3098
|
+
if (name in scope.object.properties) {
|
|
3099
|
+
return scope.object.properties[name];
|
|
3100
|
+
}
|
|
3101
|
+
scope = scope.parentScope;
|
|
3102
|
+
}
|
|
3103
|
+
if (scope === this.globalScope && this.hasProperty(scope.object, name)) {
|
|
3104
|
+
return this.getProperty(scope.object, name);
|
|
3105
|
+
}
|
|
3106
|
+
var prevNode = this.stateStack[this.stateStack.length - 1].node;
|
|
3107
|
+
if (prevNode.type === "UnaryExpression" && prevNode.operator === "typeof") {
|
|
3108
|
+
return;
|
|
3109
|
+
}
|
|
3110
|
+
this.throwException(this.REFERENCE_ERROR, name + " is not defined");
|
|
3111
|
+
};
|
|
3112
|
+
Interpreter.prototype.setValueToScope = function(name, value) {
|
|
3113
|
+
var scope = this.getScope();
|
|
3114
|
+
var strict2 = scope.strict;
|
|
3115
|
+
while (scope && scope !== this.globalScope) {
|
|
3116
|
+
if (name in scope.object.properties) {
|
|
3117
|
+
try {
|
|
3118
|
+
scope.object.properties[name] = value;
|
|
3119
|
+
} catch (_e) {
|
|
3120
|
+
if (strict2) {
|
|
3121
|
+
this.throwException(this.TYPE_ERROR, "Cannot assign to read only variable '" + name + "'");
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
return;
|
|
3125
|
+
}
|
|
3126
|
+
scope = scope.parentScope;
|
|
3127
|
+
}
|
|
3128
|
+
if (scope === this.globalScope && (!strict2 || this.hasProperty(scope.object, name))) {
|
|
3129
|
+
return this.setProperty(scope.object, name, value);
|
|
3130
|
+
}
|
|
3131
|
+
this.throwException(this.REFERENCE_ERROR, name + " is not defined");
|
|
3132
|
+
};
|
|
3133
|
+
Interpreter.prototype.populateScope_ = function(node, scope) {
|
|
3134
|
+
var variableCache;
|
|
3135
|
+
if (!node.variableCache_) {
|
|
3136
|
+
variableCache = Object.create(null);
|
|
3137
|
+
switch (node.type) {
|
|
3138
|
+
case "VariableDeclaration":
|
|
3139
|
+
for (var i = 0;i < node.declarations.length; i++) {
|
|
3140
|
+
variableCache[node.declarations[i].id.name] = true;
|
|
3141
|
+
}
|
|
3142
|
+
break;
|
|
3143
|
+
case "FunctionDeclaration":
|
|
3144
|
+
variableCache[node.id.name] = node;
|
|
3145
|
+
break;
|
|
3146
|
+
case "BlockStatement":
|
|
3147
|
+
case "CatchClause":
|
|
3148
|
+
case "DoWhileStatement":
|
|
3149
|
+
case "ForInStatement":
|
|
3150
|
+
case "ForStatement":
|
|
3151
|
+
case "IfStatement":
|
|
3152
|
+
case "LabeledStatement":
|
|
3153
|
+
case "Program":
|
|
3154
|
+
case "SwitchCase":
|
|
3155
|
+
case "SwitchStatement":
|
|
3156
|
+
case "TryStatement":
|
|
3157
|
+
case "WithStatement":
|
|
3158
|
+
case "WhileStatement":
|
|
3159
|
+
var nodeClass = node.constructor;
|
|
3160
|
+
for (var name in node) {
|
|
3161
|
+
if (name === "loc")
|
|
3162
|
+
continue;
|
|
3163
|
+
var prop = node[name];
|
|
3164
|
+
if (prop && typeof prop === "object") {
|
|
3165
|
+
var childCache;
|
|
3166
|
+
if (Array.isArray(prop)) {
|
|
3167
|
+
for (var i = 0;i < prop.length; i++) {
|
|
3168
|
+
if (prop[i] && prop[i].constructor === nodeClass) {
|
|
3169
|
+
childCache = this.populateScope_(prop[i], scope);
|
|
3170
|
+
for (var name in childCache) {
|
|
3171
|
+
variableCache[name] = childCache[name];
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3175
|
+
} else {
|
|
3176
|
+
if (prop.constructor === nodeClass) {
|
|
3177
|
+
childCache = this.populateScope_(prop, scope);
|
|
3178
|
+
for (var name in childCache) {
|
|
3179
|
+
variableCache[name] = childCache[name];
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
node.variableCache_ = variableCache;
|
|
3187
|
+
} else {
|
|
3188
|
+
variableCache = node.variableCache_;
|
|
3189
|
+
}
|
|
3190
|
+
for (var name in variableCache) {
|
|
3191
|
+
if (variableCache[name] === true) {
|
|
3192
|
+
this.setProperty(scope.object, name, undefined, Interpreter.VARIABLE_DESCRIPTOR);
|
|
3193
|
+
} else {
|
|
3194
|
+
this.setProperty(scope.object, name, this.createFunction(variableCache[name], scope), Interpreter.VARIABLE_DESCRIPTOR);
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
return variableCache;
|
|
3198
|
+
};
|
|
3199
|
+
Interpreter.prototype.calledWithNew = function() {
|
|
3200
|
+
return this.stateStack[this.stateStack.length - 1].isConstructor;
|
|
3201
|
+
};
|
|
3202
|
+
Interpreter.prototype.getValue = function(ref) {
|
|
3203
|
+
if (ref[0] === Interpreter.SCOPE_REFERENCE) {
|
|
3204
|
+
return this.getValueFromScope(ref[1]);
|
|
3205
|
+
} else {
|
|
3206
|
+
return this.getProperty(ref[0], ref[1]);
|
|
3207
|
+
}
|
|
3208
|
+
};
|
|
3209
|
+
Interpreter.prototype.setValue = function(ref, value) {
|
|
3210
|
+
if (ref[0] === Interpreter.SCOPE_REFERENCE) {
|
|
3211
|
+
return this.setValueToScope(ref[1], value);
|
|
3212
|
+
}
|
|
3213
|
+
return this.setProperty(ref[0], ref[1], value);
|
|
3214
|
+
};
|
|
3215
|
+
Interpreter.prototype.throwException = function(errorClass, opt_message) {
|
|
3216
|
+
if (!this.globalScope) {
|
|
3217
|
+
throw opt_message === undefined ? errorClass : opt_message;
|
|
3218
|
+
}
|
|
3219
|
+
if (opt_message === undefined || !(errorClass instanceof Interpreter.Object)) {
|
|
3220
|
+
var error = errorClass;
|
|
3221
|
+
} else {
|
|
3222
|
+
var error = this.createObject(errorClass);
|
|
3223
|
+
this.populateError(error, opt_message);
|
|
3224
|
+
}
|
|
3225
|
+
this.unwind(Interpreter.Completion.THROW, error, undefined);
|
|
3226
|
+
throw Interpreter.STEP_ERROR;
|
|
3227
|
+
};
|
|
3228
|
+
Interpreter.prototype.unwind = function(type, value, label) {
|
|
3229
|
+
if (type === Interpreter.Completion.NORMAL) {
|
|
3230
|
+
throw TypeError("Should not unwind for NORMAL completions");
|
|
3231
|
+
}
|
|
3232
|
+
loop:
|
|
3233
|
+
for (var stack = this.stateStack;stack.length > 0; stack.pop()) {
|
|
3234
|
+
var state = stack[stack.length - 1];
|
|
3235
|
+
switch (state.node.type) {
|
|
3236
|
+
case "TryStatement":
|
|
3237
|
+
state.cv = { type, value, label };
|
|
3238
|
+
return;
|
|
3239
|
+
case "CallExpression":
|
|
3240
|
+
case "NewExpression":
|
|
3241
|
+
if (type === Interpreter.Completion.RETURN) {
|
|
3242
|
+
state.value = value;
|
|
3243
|
+
return;
|
|
3244
|
+
} else if (type !== Interpreter.Completion.THROW) {
|
|
3245
|
+
throw Error("Unsyntactic break/continue not rejected by Acorn");
|
|
3246
|
+
}
|
|
3247
|
+
break;
|
|
3248
|
+
case "Program":
|
|
3249
|
+
state.done = true;
|
|
3250
|
+
break loop;
|
|
3251
|
+
}
|
|
3252
|
+
if (type === Interpreter.Completion.BREAK) {
|
|
3253
|
+
if (label ? state.labels && state.labels.indexOf(label) !== -1 : state.isLoop || state.isSwitch) {
|
|
3254
|
+
stack.pop();
|
|
3255
|
+
return;
|
|
3256
|
+
}
|
|
3257
|
+
} else if (type === Interpreter.Completion.CONTINUE) {
|
|
3258
|
+
if (label ? state.labels && state.labels.indexOf(label) !== -1 : state.isLoop) {
|
|
3259
|
+
return;
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
var realError;
|
|
3264
|
+
if (this.isa(value, this.ERROR)) {
|
|
3265
|
+
var errorTable = {
|
|
3266
|
+
EvalError,
|
|
3267
|
+
RangeError,
|
|
3268
|
+
ReferenceError,
|
|
3269
|
+
SyntaxError,
|
|
3270
|
+
TypeError,
|
|
3271
|
+
URIError
|
|
3272
|
+
};
|
|
3273
|
+
var name = String(this.getProperty(value, "name"));
|
|
3274
|
+
var message = this.getProperty(value, "message").valueOf();
|
|
3275
|
+
var errorConstructor = errorTable[name] || Error;
|
|
3276
|
+
realError = errorConstructor(message);
|
|
3277
|
+
realError.stack = String(this.getProperty(value, "stack"));
|
|
3278
|
+
} else {
|
|
3279
|
+
realError = String(value);
|
|
3280
|
+
}
|
|
3281
|
+
this.value = realError;
|
|
3282
|
+
throw realError;
|
|
3283
|
+
};
|
|
3284
|
+
Interpreter.prototype.nodeSummary = function(node) {
|
|
3285
|
+
switch (node.type) {
|
|
3286
|
+
case "ArrayExpression":
|
|
3287
|
+
return "[...]";
|
|
3288
|
+
case "BinaryExpression":
|
|
3289
|
+
case "LogicalExpression":
|
|
3290
|
+
return this.nodeSummary(node.left) + " " + node.operator + " " + this.nodeSummary(node.right);
|
|
3291
|
+
case "CallExpression":
|
|
3292
|
+
return this.nodeSummary(node.callee) + "(...)";
|
|
3293
|
+
case "ConditionalExpression":
|
|
3294
|
+
return this.nodeSummary(node.test) + " ? " + this.nodeSummary(node.consequent) + " : " + this.nodeSummary(node.alternate);
|
|
3295
|
+
case "Identifier":
|
|
3296
|
+
return node.name;
|
|
3297
|
+
case "Literal":
|
|
3298
|
+
return node.raw;
|
|
3299
|
+
case "MemberExpression":
|
|
3300
|
+
var obj = this.nodeSummary(node.object);
|
|
3301
|
+
var prop = this.nodeSummary(node.property);
|
|
3302
|
+
return node.computed ? obj + "[" + prop + "]" : obj + "." + prop;
|
|
3303
|
+
case "NewExpression":
|
|
3304
|
+
return "new " + this.nodeSummary(node.callee) + "(...)";
|
|
3305
|
+
case "ObjectExpression":
|
|
3306
|
+
return "{...}";
|
|
3307
|
+
case "ThisExpression":
|
|
3308
|
+
return "this";
|
|
3309
|
+
case "UnaryExpression":
|
|
3310
|
+
return node.operator + " " + this.nodeSummary(node.argument);
|
|
3311
|
+
case "UpdateExpression":
|
|
3312
|
+
var argument = this.nodeSummary(node.argument);
|
|
3313
|
+
return node.prefix ? node.operator + argument : argument + node.operator;
|
|
3314
|
+
}
|
|
3315
|
+
return "???";
|
|
3316
|
+
};
|
|
3317
|
+
Interpreter.prototype.createTask_ = function(isInterval, args) {
|
|
3318
|
+
var parentState = this.stateStack[this.stateStack.length - 1];
|
|
3319
|
+
var argsArray = Array.from(args);
|
|
3320
|
+
var exec = argsArray.shift();
|
|
3321
|
+
var delay = Math.max(Number(argsArray.shift() || 0), 0);
|
|
3322
|
+
var node = this.newNode();
|
|
3323
|
+
var scope, functionRef, ast;
|
|
3324
|
+
if (exec instanceof Interpreter.Object && exec.class === "Function") {
|
|
3325
|
+
functionRef = exec;
|
|
3326
|
+
node.type = "CallExpression";
|
|
3327
|
+
scope = parentState.scope;
|
|
3328
|
+
} else {
|
|
3329
|
+
try {
|
|
3330
|
+
ast = this.parse_(String(exec), "taskCode" + this.taskCodeNumber_++);
|
|
3331
|
+
} catch (e) {
|
|
3332
|
+
this.throwException(this.SYNTAX_ERROR, "Invalid code: " + e.message);
|
|
3333
|
+
}
|
|
3334
|
+
node.type = "EvalProgram_";
|
|
3335
|
+
node.body = ast.body;
|
|
3336
|
+
var execNode = parentState.node.arguments[0];
|
|
3337
|
+
var execStart = execNode ? execNode.start : undefined;
|
|
3338
|
+
var execEnd = execNode ? execNode.end : undefined;
|
|
3339
|
+
Interpreter.stripLocations_(node, execStart, execEnd);
|
|
3340
|
+
scope = this.globalScope;
|
|
3341
|
+
argsArray.length = 0;
|
|
3342
|
+
}
|
|
3343
|
+
var task = new Interpreter.Task(functionRef, argsArray, scope, node, isInterval ? delay : -1);
|
|
3344
|
+
this.scheduleTask_(task, delay);
|
|
3345
|
+
return task.pid;
|
|
3346
|
+
};
|
|
3347
|
+
Interpreter.prototype.scheduleTask_ = function(task, delay) {
|
|
3348
|
+
task.time = Date.now() + delay;
|
|
3349
|
+
this.tasks.push(task);
|
|
3350
|
+
this.tasks.sort(function(a, b) {
|
|
3351
|
+
return a.time - b.time;
|
|
3352
|
+
});
|
|
3353
|
+
};
|
|
3354
|
+
Interpreter.prototype.deleteTask_ = function(pid) {
|
|
3355
|
+
for (var i = 0;i < this.tasks.length; i++) {
|
|
3356
|
+
if (this.tasks[i].pid == pid) {
|
|
3357
|
+
this.tasks.splice(i, 1);
|
|
3358
|
+
break;
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
};
|
|
3362
|
+
Interpreter.prototype.nextTask_ = function() {
|
|
3363
|
+
var task = this.tasks[0];
|
|
3364
|
+
if (!task || task.time > Date.now()) {
|
|
3365
|
+
return null;
|
|
3366
|
+
}
|
|
3367
|
+
this.tasks.shift();
|
|
3368
|
+
if (task.interval >= 0) {
|
|
3369
|
+
this.scheduleTask_(task, task.interval);
|
|
3370
|
+
}
|
|
3371
|
+
var state = new Interpreter.State(task.node, task.scope);
|
|
3372
|
+
if (task.functionRef) {
|
|
3373
|
+
state.doneCallee_ = 2;
|
|
3374
|
+
state.funcThis_ = this.globalObject;
|
|
3375
|
+
state.func_ = task.functionRef;
|
|
3376
|
+
state.doneArgs_ = true;
|
|
3377
|
+
state.arguments_ = task.argsArray;
|
|
3378
|
+
}
|
|
3379
|
+
return state;
|
|
3380
|
+
};
|
|
3381
|
+
Interpreter.prototype.createGetter_ = function(func, left) {
|
|
3382
|
+
if (!this.getterStep_) {
|
|
3383
|
+
throw Error("Unexpected call to createGetter");
|
|
3384
|
+
}
|
|
3385
|
+
this.getterStep_ = false;
|
|
3386
|
+
var funcThis = Array.isArray(left) ? left[0] : left;
|
|
3387
|
+
var node = this.newNode();
|
|
3388
|
+
node.type = "CallExpression";
|
|
3389
|
+
var state = new Interpreter.State(node, this.stateStack[this.stateStack.length - 1].scope);
|
|
3390
|
+
state.doneCallee_ = 2;
|
|
3391
|
+
state.funcThis_ = funcThis;
|
|
3392
|
+
state.func_ = func;
|
|
3393
|
+
state.doneArgs_ = true;
|
|
3394
|
+
state.arguments_ = [];
|
|
3395
|
+
return state;
|
|
3396
|
+
};
|
|
3397
|
+
Interpreter.prototype.createSetter_ = function(func, left, value) {
|
|
3398
|
+
if (!this.setterStep_) {
|
|
3399
|
+
throw Error("Unexpected call to createSetter");
|
|
3400
|
+
}
|
|
3401
|
+
this.setterStep_ = false;
|
|
3402
|
+
var funcThis = Array.isArray(left) ? left[0] : this.globalObject;
|
|
3403
|
+
var node = this.newNode();
|
|
3404
|
+
node.type = "CallExpression";
|
|
3405
|
+
var state = new Interpreter.State(node, this.stateStack[this.stateStack.length - 1].scope);
|
|
3406
|
+
state.doneCallee_ = 2;
|
|
3407
|
+
state.funcThis_ = funcThis;
|
|
3408
|
+
state.func_ = func;
|
|
3409
|
+
state.doneArgs_ = true;
|
|
3410
|
+
state.arguments_ = [value];
|
|
3411
|
+
return state;
|
|
3412
|
+
};
|
|
3413
|
+
Interpreter.prototype.boxThis_ = function(value) {
|
|
3414
|
+
if (value === undefined || value === null) {
|
|
3415
|
+
return this.globalObject;
|
|
3416
|
+
}
|
|
3417
|
+
if (!(value instanceof Interpreter.Object)) {
|
|
3418
|
+
var box = this.createObjectProto(this.getPrototype(value));
|
|
3419
|
+
box.data = value;
|
|
3420
|
+
return box;
|
|
3421
|
+
}
|
|
3422
|
+
return value;
|
|
3423
|
+
};
|
|
3424
|
+
Interpreter.prototype.getGlobalScope = function() {
|
|
3425
|
+
return this.globalScope;
|
|
3426
|
+
};
|
|
3427
|
+
Interpreter.prototype.getStateStack = function() {
|
|
3428
|
+
return this.stateStack;
|
|
3429
|
+
};
|
|
3430
|
+
Interpreter.prototype.setStateStack = function(newStack) {
|
|
3431
|
+
this.stateStack = newStack;
|
|
3432
|
+
};
|
|
3433
|
+
Interpreter.Value;
|
|
3434
|
+
|
|
3435
|
+
class State {
|
|
3436
|
+
constructor(node, scope) {
|
|
3437
|
+
this.node = node;
|
|
3438
|
+
this.scope = scope;
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
Interpreter.State = State;
|
|
3442
|
+
|
|
3443
|
+
class Scope {
|
|
3444
|
+
constructor(parentScope, strict2, object) {
|
|
3445
|
+
this.parentScope = parentScope;
|
|
3446
|
+
this.strict = strict2;
|
|
3447
|
+
this.object = object;
|
|
3448
|
+
}
|
|
3449
|
+
}
|
|
3450
|
+
Interpreter.Scope = Scope;
|
|
3451
|
+
Interpreter.Object = function(proto) {
|
|
3452
|
+
this.getter = Object.create(null);
|
|
3453
|
+
this.setter = Object.create(null);
|
|
3454
|
+
this.properties = Object.create(null);
|
|
3455
|
+
this.proto = proto;
|
|
3456
|
+
};
|
|
3457
|
+
Interpreter.Object.prototype.proto = null;
|
|
3458
|
+
Interpreter.Object.prototype.class = "Object";
|
|
3459
|
+
Interpreter.Object.prototype.data = null;
|
|
3460
|
+
Interpreter.Object.prototype.toString = function() {
|
|
3461
|
+
if (!Interpreter.currentInterpreter_) {
|
|
3462
|
+
return "[object Interpreter.Object]";
|
|
3463
|
+
}
|
|
3464
|
+
if (!(this instanceof Interpreter.Object)) {
|
|
3465
|
+
return String(this);
|
|
3466
|
+
}
|
|
3467
|
+
if (this.class === "Array") {
|
|
3468
|
+
var cycles = Interpreter.toStringCycles_;
|
|
3469
|
+
cycles.push(this);
|
|
3470
|
+
try {
|
|
3471
|
+
var strs = [];
|
|
3472
|
+
var maxLength = this.properties.length;
|
|
3473
|
+
var truncated = false;
|
|
3474
|
+
if (maxLength > 1024) {
|
|
3475
|
+
maxLength = 1000;
|
|
3476
|
+
truncated = true;
|
|
3477
|
+
}
|
|
3478
|
+
for (var i = 0;i < maxLength; i++) {
|
|
3479
|
+
var value = this.properties[i];
|
|
3480
|
+
strs[i] = value instanceof Interpreter.Object && cycles.indexOf(value) !== -1 ? "..." : value;
|
|
3481
|
+
}
|
|
3482
|
+
if (truncated) {
|
|
3483
|
+
strs.push("...");
|
|
3484
|
+
}
|
|
3485
|
+
} finally {
|
|
3486
|
+
cycles.pop();
|
|
3487
|
+
}
|
|
3488
|
+
return strs.join(",");
|
|
3489
|
+
}
|
|
3490
|
+
if (this.class === "Error") {
|
|
3491
|
+
var cycles = Interpreter.toStringCycles_;
|
|
3492
|
+
if (cycles.indexOf(this) !== -1) {
|
|
3493
|
+
return "[object Error]";
|
|
3494
|
+
}
|
|
3495
|
+
var name, message;
|
|
3496
|
+
var obj = this;
|
|
3497
|
+
do {
|
|
3498
|
+
if ("name" in obj.properties) {
|
|
3499
|
+
name = obj.properties.name;
|
|
3500
|
+
break;
|
|
3501
|
+
}
|
|
3502
|
+
} while (obj = obj.proto);
|
|
3503
|
+
obj = this;
|
|
3504
|
+
do {
|
|
3505
|
+
if ("message" in obj.properties) {
|
|
3506
|
+
message = obj.properties.message;
|
|
3507
|
+
break;
|
|
3508
|
+
}
|
|
3509
|
+
} while (obj = obj.proto);
|
|
3510
|
+
cycles.push(this);
|
|
3511
|
+
try {
|
|
3512
|
+
name = name && String(name);
|
|
3513
|
+
message = message && String(message);
|
|
3514
|
+
} finally {
|
|
3515
|
+
cycles.pop();
|
|
3516
|
+
}
|
|
3517
|
+
return message ? name + ": " + message : String(name);
|
|
3518
|
+
}
|
|
3519
|
+
if (this.data !== null) {
|
|
3520
|
+
return String(this.data);
|
|
3521
|
+
}
|
|
3522
|
+
return "[object " + this.class + "]";
|
|
3523
|
+
};
|
|
3524
|
+
Interpreter.Object.prototype.valueOf = function() {
|
|
3525
|
+
if (!Interpreter.currentInterpreter_) {
|
|
3526
|
+
return this;
|
|
3527
|
+
}
|
|
3528
|
+
if (this.data === undefined || this.data === null || this.data instanceof RegExp) {
|
|
3529
|
+
return this;
|
|
3530
|
+
}
|
|
3531
|
+
if (this.data instanceof Date) {
|
|
3532
|
+
return this.data.valueOf();
|
|
3533
|
+
}
|
|
3534
|
+
return this.data;
|
|
3535
|
+
};
|
|
3536
|
+
Interpreter.Task = function(functionRef, argsArray, scope, node, interval) {
|
|
3537
|
+
this.functionRef = functionRef;
|
|
3538
|
+
this.argsArray = argsArray;
|
|
3539
|
+
this.scope = scope;
|
|
3540
|
+
this.node = node;
|
|
3541
|
+
this.interval = interval;
|
|
3542
|
+
this.pid = ++Interpreter.Task.pid;
|
|
3543
|
+
this.time = 0;
|
|
3544
|
+
};
|
|
3545
|
+
Interpreter.Task.pid = 0;
|
|
3546
|
+
Interpreter.prototype["stepArrayExpression"] = function(stack, state, node) {
|
|
3547
|
+
var elements = node.elements;
|
|
3548
|
+
var n = state.n_ || 0;
|
|
3549
|
+
if (!state.array_) {
|
|
3550
|
+
state.array_ = this.createArray();
|
|
3551
|
+
state.array_.properties.length = elements.length;
|
|
3552
|
+
} else {
|
|
3553
|
+
this.setProperty(state.array_, n, state.value);
|
|
3554
|
+
n++;
|
|
3555
|
+
}
|
|
3556
|
+
while (n < elements.length) {
|
|
3557
|
+
if (elements[n]) {
|
|
3558
|
+
state.n_ = n;
|
|
3559
|
+
return new Interpreter.State(elements[n], state.scope);
|
|
3560
|
+
}
|
|
3561
|
+
n++;
|
|
3562
|
+
}
|
|
3563
|
+
stack.pop();
|
|
3564
|
+
stack[stack.length - 1].value = state.array_;
|
|
3565
|
+
};
|
|
3566
|
+
Interpreter.prototype["stepAssignmentExpression"] = function(stack, state, node) {
|
|
3567
|
+
if (!state.doneLeft_) {
|
|
3568
|
+
state.doneLeft_ = true;
|
|
3569
|
+
var nextState = new Interpreter.State(node.left, state.scope);
|
|
3570
|
+
nextState.components = true;
|
|
3571
|
+
return nextState;
|
|
3572
|
+
}
|
|
3573
|
+
if (!state.doneRight_) {
|
|
3574
|
+
if (!state.leftReference_) {
|
|
3575
|
+
state.leftReference_ = state.value;
|
|
3576
|
+
}
|
|
3577
|
+
if (state.doneGetter_) {
|
|
3578
|
+
state.leftValue_ = state.value;
|
|
3579
|
+
}
|
|
3580
|
+
if (!state.doneGetter_ && node.operator !== "=") {
|
|
3581
|
+
var leftValue = this.getValue(state.leftReference_);
|
|
3582
|
+
state.leftValue_ = leftValue;
|
|
3583
|
+
if (this.getterStep_) {
|
|
3584
|
+
state.doneGetter_ = true;
|
|
3585
|
+
var func = leftValue;
|
|
3586
|
+
return this.createGetter_(func, state.leftReference_);
|
|
3587
|
+
}
|
|
3588
|
+
}
|
|
3589
|
+
state.doneRight_ = true;
|
|
3590
|
+
if (node.operator === "=" && node.left.type === "Identifier") {
|
|
3591
|
+
state.destinationName = node.left.name;
|
|
3592
|
+
}
|
|
3593
|
+
return new Interpreter.State(node.right, state.scope);
|
|
3594
|
+
}
|
|
3595
|
+
if (state.doneSetter_) {
|
|
3596
|
+
stack.pop();
|
|
3597
|
+
stack[stack.length - 1].value = state.setterValue_;
|
|
3598
|
+
return;
|
|
3599
|
+
}
|
|
3600
|
+
var value = state.leftValue_;
|
|
3601
|
+
var rightValue = state.value;
|
|
3602
|
+
switch (node.operator) {
|
|
3603
|
+
case "=":
|
|
3604
|
+
value = rightValue;
|
|
3605
|
+
break;
|
|
3606
|
+
case "+=":
|
|
3607
|
+
value += rightValue;
|
|
3608
|
+
break;
|
|
3609
|
+
case "-=":
|
|
3610
|
+
value -= rightValue;
|
|
3611
|
+
break;
|
|
3612
|
+
case "*=":
|
|
3613
|
+
value *= rightValue;
|
|
3614
|
+
break;
|
|
3615
|
+
case "/=":
|
|
3616
|
+
value /= rightValue;
|
|
3617
|
+
break;
|
|
3618
|
+
case "%=":
|
|
3619
|
+
value %= rightValue;
|
|
3620
|
+
break;
|
|
3621
|
+
case "<<=":
|
|
3622
|
+
value <<= rightValue;
|
|
3623
|
+
break;
|
|
3624
|
+
case ">>=":
|
|
3625
|
+
value >>= rightValue;
|
|
3626
|
+
break;
|
|
3627
|
+
case ">>>=":
|
|
3628
|
+
value >>>= rightValue;
|
|
3629
|
+
break;
|
|
3630
|
+
case "&=":
|
|
3631
|
+
value &= rightValue;
|
|
3632
|
+
break;
|
|
3633
|
+
case "^=":
|
|
3634
|
+
value ^= rightValue;
|
|
3635
|
+
break;
|
|
3636
|
+
case "|=":
|
|
3637
|
+
value |= rightValue;
|
|
3638
|
+
break;
|
|
3639
|
+
default:
|
|
3640
|
+
throw SyntaxError("Unknown assignment expression: " + node.operator);
|
|
3641
|
+
}
|
|
3642
|
+
var setter = this.setValue(state.leftReference_, value);
|
|
3643
|
+
if (setter) {
|
|
3644
|
+
state.doneSetter_ = true;
|
|
3645
|
+
state.setterValue_ = value;
|
|
3646
|
+
return this.createSetter_(setter, state.leftReference_, value);
|
|
3647
|
+
}
|
|
3648
|
+
stack.pop();
|
|
3649
|
+
stack[stack.length - 1].value = value;
|
|
3650
|
+
};
|
|
3651
|
+
Interpreter.prototype["stepBinaryExpression"] = function(stack, state, node) {
|
|
3652
|
+
if (!state.doneLeft_) {
|
|
3653
|
+
state.doneLeft_ = true;
|
|
3654
|
+
return new Interpreter.State(node.left, state.scope);
|
|
3655
|
+
}
|
|
3656
|
+
if (!state.doneRight_) {
|
|
3657
|
+
state.doneRight_ = true;
|
|
3658
|
+
state.leftValue_ = state.value;
|
|
3659
|
+
return new Interpreter.State(node.right, state.scope);
|
|
3660
|
+
}
|
|
3661
|
+
stack.pop();
|
|
3662
|
+
var leftValue = state.leftValue_;
|
|
3663
|
+
var rightValue = state.value;
|
|
3664
|
+
var value;
|
|
3665
|
+
switch (node.operator) {
|
|
3666
|
+
case "==":
|
|
3667
|
+
value = leftValue == rightValue;
|
|
3668
|
+
break;
|
|
3669
|
+
case "!=":
|
|
3670
|
+
value = leftValue != rightValue;
|
|
3671
|
+
break;
|
|
3672
|
+
case "===":
|
|
3673
|
+
value = leftValue === rightValue;
|
|
3674
|
+
break;
|
|
3675
|
+
case "!==":
|
|
3676
|
+
value = leftValue !== rightValue;
|
|
3677
|
+
break;
|
|
3678
|
+
case ">":
|
|
3679
|
+
value = leftValue > rightValue;
|
|
3680
|
+
break;
|
|
3681
|
+
case ">=":
|
|
3682
|
+
value = leftValue >= rightValue;
|
|
3683
|
+
break;
|
|
3684
|
+
case "<":
|
|
3685
|
+
value = leftValue < rightValue;
|
|
3686
|
+
break;
|
|
3687
|
+
case "<=":
|
|
3688
|
+
value = leftValue <= rightValue;
|
|
3689
|
+
break;
|
|
3690
|
+
case "+":
|
|
3691
|
+
value = leftValue + rightValue;
|
|
3692
|
+
break;
|
|
3693
|
+
case "-":
|
|
3694
|
+
value = leftValue - rightValue;
|
|
3695
|
+
break;
|
|
3696
|
+
case "*":
|
|
3697
|
+
value = leftValue * rightValue;
|
|
3698
|
+
break;
|
|
3699
|
+
case "/":
|
|
3700
|
+
value = leftValue / rightValue;
|
|
3701
|
+
break;
|
|
3702
|
+
case "%":
|
|
3703
|
+
value = leftValue % rightValue;
|
|
3704
|
+
break;
|
|
3705
|
+
case "&":
|
|
3706
|
+
value = leftValue & rightValue;
|
|
3707
|
+
break;
|
|
3708
|
+
case "|":
|
|
3709
|
+
value = leftValue | rightValue;
|
|
3710
|
+
break;
|
|
3711
|
+
case "^":
|
|
3712
|
+
value = leftValue ^ rightValue;
|
|
3713
|
+
break;
|
|
3714
|
+
case "<<":
|
|
3715
|
+
value = leftValue << rightValue;
|
|
3716
|
+
break;
|
|
3717
|
+
case ">>":
|
|
3718
|
+
value = leftValue >> rightValue;
|
|
3719
|
+
break;
|
|
3720
|
+
case ">>>":
|
|
3721
|
+
value = leftValue >>> rightValue;
|
|
3722
|
+
break;
|
|
3723
|
+
case "in":
|
|
3724
|
+
if (!(rightValue instanceof Interpreter.Object)) {
|
|
3725
|
+
this.throwException(this.TYPE_ERROR, "'in' expects an object, not '" + rightValue + "'");
|
|
3726
|
+
}
|
|
3727
|
+
value = this.hasProperty(rightValue, leftValue);
|
|
3728
|
+
break;
|
|
3729
|
+
case "instanceof":
|
|
3730
|
+
if (!this.isa(rightValue, this.FUNCTION)) {
|
|
3731
|
+
this.throwException(this.TYPE_ERROR, "'instanceof' expects an object, not '" + rightValue + "'");
|
|
3732
|
+
}
|
|
3733
|
+
value = leftValue instanceof Interpreter.Object ? this.isa(leftValue, rightValue) : false;
|
|
3734
|
+
break;
|
|
3735
|
+
default:
|
|
3736
|
+
throw SyntaxError("Unknown binary operator: " + node.operator);
|
|
3737
|
+
}
|
|
3738
|
+
stack[stack.length - 1].value = value;
|
|
3739
|
+
};
|
|
3740
|
+
Interpreter.prototype["stepBlockStatement"] = function(stack, state, node) {
|
|
3741
|
+
var n = state.n_ || 0;
|
|
3742
|
+
var expression = node.body[n];
|
|
3743
|
+
if (expression) {
|
|
3744
|
+
state.n_ = n + 1;
|
|
3745
|
+
return new Interpreter.State(expression, state.scope);
|
|
3746
|
+
}
|
|
3747
|
+
stack.pop();
|
|
3748
|
+
};
|
|
3749
|
+
Interpreter.prototype["stepBreakStatement"] = function(stack, state, node) {
|
|
3750
|
+
var label = node.label && node.label.name;
|
|
3751
|
+
this.unwind(Interpreter.Completion.BREAK, undefined, label);
|
|
3752
|
+
};
|
|
3753
|
+
Interpreter.prototype.evalCodeNumber_ = 0;
|
|
3754
|
+
Interpreter.prototype["stepCallExpression"] = function(stack, state, node) {
|
|
3755
|
+
if (!state.doneCallee_) {
|
|
3756
|
+
state.doneCallee_ = 1;
|
|
3757
|
+
var nextState = new Interpreter.State(node.callee, state.scope);
|
|
3758
|
+
nextState.components = true;
|
|
3759
|
+
return nextState;
|
|
3760
|
+
}
|
|
3761
|
+
if (state.doneCallee_ === 1) {
|
|
3762
|
+
state.doneCallee_ = 2;
|
|
3763
|
+
var func = state.value;
|
|
3764
|
+
if (Array.isArray(func)) {
|
|
3765
|
+
state.func_ = this.getValue(func);
|
|
3766
|
+
if (func[0] === Interpreter.SCOPE_REFERENCE) {
|
|
3767
|
+
state.directEval_ = func[1] === "eval";
|
|
3768
|
+
} else {
|
|
3769
|
+
state.funcThis_ = func[0];
|
|
3770
|
+
}
|
|
3771
|
+
func = state.func_;
|
|
3772
|
+
if (this.getterStep_) {
|
|
3773
|
+
state.doneCallee_ = 1;
|
|
3774
|
+
return this.createGetter_(func, state.value);
|
|
3775
|
+
}
|
|
3776
|
+
} else {
|
|
3777
|
+
state.func_ = func;
|
|
3778
|
+
}
|
|
3779
|
+
state.arguments_ = [];
|
|
3780
|
+
state.n_ = 0;
|
|
3781
|
+
}
|
|
3782
|
+
var func = state.func_;
|
|
3783
|
+
if (!state.doneArgs_) {
|
|
3784
|
+
if (state.n_ !== 0) {
|
|
3785
|
+
state.arguments_.push(state.value);
|
|
3786
|
+
}
|
|
3787
|
+
if (node.arguments[state.n_]) {
|
|
3788
|
+
return new Interpreter.State(node.arguments[state.n_++], state.scope);
|
|
3789
|
+
}
|
|
3790
|
+
if (node.type === "NewExpression") {
|
|
3791
|
+
if (!(func instanceof Interpreter.Object) || func.illegalConstructor) {
|
|
3792
|
+
this.throwException(this.TYPE_ERROR, this.nodeSummary(node.callee) + " is not a constructor");
|
|
3793
|
+
}
|
|
3794
|
+
if (func === this.ARRAY) {
|
|
3795
|
+
state.funcThis_ = this.createArray();
|
|
3796
|
+
} else {
|
|
3797
|
+
var proto = func.properties["prototype"];
|
|
3798
|
+
if (typeof proto !== "object" || proto === null) {
|
|
3799
|
+
proto = this.OBJECT_PROTO;
|
|
3800
|
+
}
|
|
3801
|
+
state.funcThis_ = this.createObjectProto(proto);
|
|
3802
|
+
}
|
|
3803
|
+
state.isConstructor = true;
|
|
3804
|
+
}
|
|
3805
|
+
state.doneArgs_ = true;
|
|
3806
|
+
}
|
|
3807
|
+
if (!state.doneExec_) {
|
|
3808
|
+
state.doneExec_ = true;
|
|
3809
|
+
if (!(func instanceof Interpreter.Object)) {
|
|
3810
|
+
this.throwException(this.TYPE_ERROR, this.nodeSummary(node.callee) + " is not a function");
|
|
3811
|
+
}
|
|
3812
|
+
var funcNode = func.node;
|
|
3813
|
+
if (funcNode) {
|
|
3814
|
+
var scope = this.createScope(funcNode.body, func.parentScope);
|
|
3815
|
+
var argsList = this.createArray();
|
|
3816
|
+
for (var i = 0;i < state.arguments_.length; i++) {
|
|
3817
|
+
this.setProperty(argsList, i, state.arguments_[i]);
|
|
3818
|
+
}
|
|
3819
|
+
this.setProperty(scope.object, "arguments", argsList);
|
|
3820
|
+
for (var i = 0;i < funcNode.params.length; i++) {
|
|
3821
|
+
var paramName = funcNode.params[i].name;
|
|
3822
|
+
var paramValue = state.arguments_.length > i ? state.arguments_[i] : undefined;
|
|
3823
|
+
this.setProperty(scope.object, paramName, paramValue);
|
|
3824
|
+
}
|
|
3825
|
+
if (!scope.strict) {
|
|
3826
|
+
state.funcThis_ = this.boxThis_(state.funcThis_);
|
|
3827
|
+
}
|
|
3828
|
+
this.setProperty(scope.object, "this", state.funcThis_, Interpreter.READONLY_DESCRIPTOR);
|
|
3829
|
+
state.value = undefined;
|
|
3830
|
+
return new Interpreter.State(funcNode.body, scope);
|
|
3831
|
+
} else if (func.eval) {
|
|
3832
|
+
var code = state.arguments_[0];
|
|
3833
|
+
if (typeof code !== "string") {
|
|
3834
|
+
state.value = code;
|
|
3835
|
+
} else {
|
|
3836
|
+
try {
|
|
3837
|
+
var ast = this.parse_(String(code), "eval" + this.evalCodeNumber_++);
|
|
3838
|
+
} catch (e) {
|
|
3839
|
+
this.throwException(this.SYNTAX_ERROR, "Invalid code: " + e.message);
|
|
3840
|
+
}
|
|
3841
|
+
var evalNode = this.newNode();
|
|
3842
|
+
evalNode.type = "EvalProgram_";
|
|
3843
|
+
evalNode.body = ast.body;
|
|
3844
|
+
Interpreter.stripLocations_(evalNode, node.start, node.end);
|
|
3845
|
+
var scope = state.directEval_ ? state.scope : this.globalScope;
|
|
3846
|
+
if (scope.strict) {
|
|
3847
|
+
scope = this.createScope(ast, scope);
|
|
3848
|
+
} else {
|
|
3849
|
+
this.populateScope_(ast, scope);
|
|
3850
|
+
}
|
|
3851
|
+
this.value = undefined;
|
|
3852
|
+
return new Interpreter.State(evalNode, scope);
|
|
3853
|
+
}
|
|
3854
|
+
} else if (func.nativeFunc) {
|
|
3855
|
+
if (!state.scope.strict) {
|
|
3856
|
+
state.funcThis_ = this.boxThis_(state.funcThis_);
|
|
3857
|
+
}
|
|
3858
|
+
state.value = func.nativeFunc.apply(state.funcThis_, state.arguments_);
|
|
3859
|
+
} else if (func.asyncFunc) {
|
|
3860
|
+
var thisInterpreter = this;
|
|
3861
|
+
var callback = function(value) {
|
|
3862
|
+
state.value = value;
|
|
3863
|
+
thisInterpreter.paused_ = false;
|
|
3864
|
+
};
|
|
3865
|
+
var argLength = func.asyncFunc.length - 1;
|
|
3866
|
+
var argsWithCallback = state.arguments_.concat(new Array(argLength)).slice(0, argLength);
|
|
3867
|
+
argsWithCallback.push(callback);
|
|
3868
|
+
this.paused_ = true;
|
|
3869
|
+
if (!state.scope.strict) {
|
|
3870
|
+
state.funcThis_ = this.boxThis_(state.funcThis_);
|
|
3871
|
+
}
|
|
3872
|
+
func.asyncFunc.apply(state.funcThis_, argsWithCallback);
|
|
3873
|
+
return;
|
|
3874
|
+
} else {
|
|
3875
|
+
this.throwException(this.TYPE_ERROR, this.nodeSummary(node.callee) + " is not callable");
|
|
3876
|
+
}
|
|
3877
|
+
} else {
|
|
3878
|
+
stack.pop();
|
|
3879
|
+
if (state.isConstructor && typeof state.value !== "object") {
|
|
3880
|
+
stack[stack.length - 1].value = state.funcThis_;
|
|
3881
|
+
} else {
|
|
3882
|
+
stack[stack.length - 1].value = state.value;
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
};
|
|
3886
|
+
Interpreter.prototype["stepConditionalExpression"] = function(stack, state, node) {
|
|
3887
|
+
var mode = state.mode_ || 0;
|
|
3888
|
+
if (mode === 0) {
|
|
3889
|
+
state.mode_ = 1;
|
|
3890
|
+
return new Interpreter.State(node.test, state.scope);
|
|
3891
|
+
}
|
|
3892
|
+
if (mode === 1) {
|
|
3893
|
+
state.mode_ = 2;
|
|
3894
|
+
var value = Boolean(state.value);
|
|
3895
|
+
if (value && node.consequent) {
|
|
3896
|
+
return new Interpreter.State(node.consequent, state.scope);
|
|
3897
|
+
} else if (!value && node.alternate) {
|
|
3898
|
+
return new Interpreter.State(node.alternate, state.scope);
|
|
3899
|
+
}
|
|
3900
|
+
this.value = undefined;
|
|
3901
|
+
}
|
|
3902
|
+
stack.pop();
|
|
3903
|
+
if (node.type === "ConditionalExpression") {
|
|
3904
|
+
stack[stack.length - 1].value = state.value;
|
|
3905
|
+
}
|
|
3906
|
+
};
|
|
3907
|
+
Interpreter.prototype["stepContinueStatement"] = function(stack, state, node) {
|
|
3908
|
+
var label = node.label && node.label.name;
|
|
3909
|
+
this.unwind(Interpreter.Completion.CONTINUE, undefined, label);
|
|
3910
|
+
};
|
|
3911
|
+
Interpreter.prototype["stepDebuggerStatement"] = function(stack, state, node) {
|
|
3912
|
+
stack.pop();
|
|
3913
|
+
};
|
|
3914
|
+
Interpreter.prototype["stepDoWhileStatement"] = function(stack, state, node) {
|
|
3915
|
+
if (node.type === "DoWhileStatement" && state.test_ === undefined) {
|
|
3916
|
+
state.value = true;
|
|
3917
|
+
state.test_ = true;
|
|
3918
|
+
}
|
|
3919
|
+
if (!state.test_) {
|
|
3920
|
+
state.test_ = true;
|
|
3921
|
+
return new Interpreter.State(node.test, state.scope);
|
|
3922
|
+
}
|
|
3923
|
+
if (!state.value) {
|
|
3924
|
+
stack.pop();
|
|
3925
|
+
} else if (node.body) {
|
|
3926
|
+
state.test_ = false;
|
|
3927
|
+
state.isLoop = true;
|
|
3928
|
+
return new Interpreter.State(node.body, state.scope);
|
|
3929
|
+
}
|
|
3930
|
+
};
|
|
3931
|
+
Interpreter.prototype["stepEmptyStatement"] = function(stack, state, node) {
|
|
3932
|
+
stack.pop();
|
|
3933
|
+
};
|
|
3934
|
+
Interpreter.prototype["stepEvalProgram_"] = function(stack, state, node) {
|
|
3935
|
+
var n = state.n_ || 0;
|
|
3936
|
+
var expression = node.body[n];
|
|
3937
|
+
if (expression) {
|
|
3938
|
+
state.n_ = n + 1;
|
|
3939
|
+
return new Interpreter.State(expression, state.scope);
|
|
3940
|
+
}
|
|
3941
|
+
stack.pop();
|
|
3942
|
+
stack[stack.length - 1].value = this.value;
|
|
3943
|
+
};
|
|
3944
|
+
Interpreter.prototype["stepExpressionStatement"] = function(stack, state, node) {
|
|
3945
|
+
if (!state.done_) {
|
|
3946
|
+
this.value = undefined;
|
|
3947
|
+
state.done_ = true;
|
|
3948
|
+
return new Interpreter.State(node.expression, state.scope);
|
|
3949
|
+
}
|
|
3950
|
+
stack.pop();
|
|
3951
|
+
this.value = state.value;
|
|
3952
|
+
};
|
|
3953
|
+
Interpreter.prototype["stepForInStatement"] = function(stack, state, node) {
|
|
3954
|
+
if (!state.doneInit_) {
|
|
3955
|
+
state.doneInit_ = true;
|
|
3956
|
+
if (node.left.declarations && node.left.declarations[0].init) {
|
|
3957
|
+
if (state.scope.strict) {
|
|
3958
|
+
this.throwException(this.SYNTAX_ERROR, "for-in loop variable declaration may not have an initializer");
|
|
3959
|
+
}
|
|
3960
|
+
return new Interpreter.State(node.left, state.scope);
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
if (!state.doneObject_) {
|
|
3964
|
+
state.doneObject_ = true;
|
|
3965
|
+
if (!state.variable_) {
|
|
3966
|
+
state.variable_ = state.value;
|
|
3967
|
+
}
|
|
3968
|
+
return new Interpreter.State(node.right, state.scope);
|
|
3969
|
+
}
|
|
3970
|
+
if (!state.isLoop) {
|
|
3971
|
+
state.isLoop = true;
|
|
3972
|
+
state.object_ = state.value;
|
|
3973
|
+
state.visited_ = Object.create(null);
|
|
3974
|
+
}
|
|
3975
|
+
if (state.name_ === undefined) {
|
|
3976
|
+
gotPropName:
|
|
3977
|
+
while (true) {
|
|
3978
|
+
if (state.object_ instanceof Interpreter.Object) {
|
|
3979
|
+
if (!state.props_) {
|
|
3980
|
+
state.props_ = Object.getOwnPropertyNames(state.object_.properties);
|
|
3981
|
+
}
|
|
3982
|
+
while (true) {
|
|
3983
|
+
var prop = state.props_.shift();
|
|
3984
|
+
if (prop === undefined) {
|
|
3985
|
+
break;
|
|
3986
|
+
}
|
|
3987
|
+
if (!Object.prototype.hasOwnProperty.call(state.object_.properties, prop)) {
|
|
3988
|
+
continue;
|
|
3989
|
+
}
|
|
3990
|
+
if (state.visited_[prop]) {
|
|
3991
|
+
continue;
|
|
3992
|
+
}
|
|
3993
|
+
state.visited_[prop] = true;
|
|
3994
|
+
if (!Object.prototype.propertyIsEnumerable.call(state.object_.properties, prop)) {
|
|
3995
|
+
continue;
|
|
3996
|
+
}
|
|
3997
|
+
state.name_ = prop;
|
|
3998
|
+
break gotPropName;
|
|
3999
|
+
}
|
|
4000
|
+
} else if (state.object_ !== null && state.object_ !== undefined) {
|
|
4001
|
+
if (!state.props_) {
|
|
4002
|
+
state.props_ = Object.getOwnPropertyNames(state.object_);
|
|
4003
|
+
}
|
|
4004
|
+
while (true) {
|
|
4005
|
+
var prop = state.props_.shift();
|
|
4006
|
+
if (prop === undefined) {
|
|
4007
|
+
break;
|
|
4008
|
+
}
|
|
4009
|
+
state.visited_[prop] = true;
|
|
4010
|
+
if (!Object.prototype.propertyIsEnumerable.call(state.object_, prop)) {
|
|
4011
|
+
continue;
|
|
4012
|
+
}
|
|
4013
|
+
state.name_ = prop;
|
|
4014
|
+
break gotPropName;
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
state.object_ = this.getPrototype(state.object_);
|
|
4018
|
+
state.props_ = null;
|
|
4019
|
+
if (state.object_ === null) {
|
|
4020
|
+
stack.pop();
|
|
4021
|
+
return;
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
4025
|
+
if (!state.doneVariable_) {
|
|
4026
|
+
state.doneVariable_ = true;
|
|
4027
|
+
var left = node.left;
|
|
4028
|
+
if (left.type === "VariableDeclaration") {
|
|
4029
|
+
state.variable_ = [Interpreter.SCOPE_REFERENCE, left.declarations[0].id.name];
|
|
4030
|
+
} else {
|
|
4031
|
+
state.variable_ = null;
|
|
4032
|
+
var nextState = new Interpreter.State(left, state.scope);
|
|
4033
|
+
nextState.components = true;
|
|
4034
|
+
return nextState;
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
if (!state.variable_) {
|
|
4038
|
+
state.variable_ = state.value;
|
|
4039
|
+
}
|
|
4040
|
+
if (!state.doneSetter_) {
|
|
4041
|
+
state.doneSetter_ = true;
|
|
4042
|
+
var value = state.name_;
|
|
4043
|
+
var setter = this.setValue(state.variable_, value);
|
|
4044
|
+
if (setter) {
|
|
4045
|
+
return this.createSetter_(setter, state.variable_, value);
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
state.name_ = undefined;
|
|
4049
|
+
state.doneVariable_ = false;
|
|
4050
|
+
state.doneSetter_ = false;
|
|
4051
|
+
if (node.body) {
|
|
4052
|
+
return new Interpreter.State(node.body, state.scope);
|
|
4053
|
+
}
|
|
4054
|
+
};
|
|
4055
|
+
Interpreter.prototype["stepForStatement"] = function(stack, state, node) {
|
|
4056
|
+
switch (state.mode_) {
|
|
4057
|
+
default:
|
|
4058
|
+
state.mode_ = 1;
|
|
4059
|
+
if (node.init) {
|
|
4060
|
+
return new Interpreter.State(node.init, state.scope);
|
|
4061
|
+
}
|
|
4062
|
+
break;
|
|
4063
|
+
case 1:
|
|
4064
|
+
state.mode_ = 2;
|
|
4065
|
+
if (node.test) {
|
|
4066
|
+
return new Interpreter.State(node.test, state.scope);
|
|
4067
|
+
}
|
|
4068
|
+
break;
|
|
4069
|
+
case 2:
|
|
4070
|
+
state.mode_ = 3;
|
|
4071
|
+
if (node.test && !state.value) {
|
|
4072
|
+
stack.pop();
|
|
4073
|
+
} else {
|
|
4074
|
+
state.isLoop = true;
|
|
4075
|
+
return new Interpreter.State(node.body, state.scope);
|
|
4076
|
+
}
|
|
4077
|
+
break;
|
|
4078
|
+
case 3:
|
|
4079
|
+
state.mode_ = 1;
|
|
4080
|
+
if (node.update) {
|
|
4081
|
+
return new Interpreter.State(node.update, state.scope);
|
|
4082
|
+
}
|
|
4083
|
+
break;
|
|
4084
|
+
}
|
|
4085
|
+
};
|
|
4086
|
+
Interpreter.prototype["stepFunctionDeclaration"] = function(stack, state, node) {
|
|
4087
|
+
stack.pop();
|
|
4088
|
+
};
|
|
4089
|
+
Interpreter.prototype["stepFunctionExpression"] = function(stack, state, node) {
|
|
4090
|
+
stack.pop();
|
|
4091
|
+
state = stack[stack.length - 1];
|
|
4092
|
+
var parentScope = state.scope;
|
|
4093
|
+
if (node.id) {
|
|
4094
|
+
parentScope = this.createSpecialScope(parentScope);
|
|
4095
|
+
}
|
|
4096
|
+
state.value = this.createFunction(node, parentScope, state.destinationName);
|
|
4097
|
+
if (node.id) {
|
|
4098
|
+
this.setProperty(parentScope.object, node.id.name, state.value, Interpreter.READONLY_DESCRIPTOR);
|
|
4099
|
+
}
|
|
4100
|
+
};
|
|
4101
|
+
Interpreter.prototype["stepIdentifier"] = function(stack, state, node) {
|
|
4102
|
+
stack.pop();
|
|
4103
|
+
if (state.components) {
|
|
4104
|
+
stack[stack.length - 1].value = [Interpreter.SCOPE_REFERENCE, node.name];
|
|
4105
|
+
return;
|
|
4106
|
+
}
|
|
4107
|
+
var value = this.getValueFromScope(node.name);
|
|
4108
|
+
if (this.getterStep_) {
|
|
4109
|
+
var func = value;
|
|
4110
|
+
return this.createGetter_(func, this.globalObject);
|
|
4111
|
+
}
|
|
4112
|
+
stack[stack.length - 1].value = value;
|
|
4113
|
+
};
|
|
4114
|
+
Interpreter.prototype["stepIfStatement"] = Interpreter.prototype["stepConditionalExpression"];
|
|
4115
|
+
Interpreter.prototype["stepLabeledStatement"] = function(stack, state, node) {
|
|
4116
|
+
stack.pop();
|
|
4117
|
+
var labels2 = state.labels || [];
|
|
4118
|
+
labels2.push(node.label.name);
|
|
4119
|
+
var nextState = new Interpreter.State(node.body, state.scope);
|
|
4120
|
+
nextState.labels = labels2;
|
|
4121
|
+
return nextState;
|
|
4122
|
+
};
|
|
4123
|
+
Interpreter.prototype["stepLiteral"] = function(stack, state, node) {
|
|
4124
|
+
stack.pop();
|
|
4125
|
+
var value = node.value;
|
|
4126
|
+
if (value instanceof RegExp) {
|
|
4127
|
+
var pseudoRegexp = this.createObjectProto(this.REGEXP_PROTO);
|
|
4128
|
+
this.populateRegExp(pseudoRegexp, value);
|
|
4129
|
+
value = pseudoRegexp;
|
|
4130
|
+
}
|
|
4131
|
+
stack[stack.length - 1].value = value;
|
|
4132
|
+
};
|
|
4133
|
+
Interpreter.prototype["stepLogicalExpression"] = function(stack, state, node) {
|
|
4134
|
+
if (node.operator !== "&&" && node.operator !== "||") {
|
|
4135
|
+
throw SyntaxError("Unknown logical operator: " + node.operator);
|
|
4136
|
+
}
|
|
4137
|
+
if (!state.doneLeft_) {
|
|
4138
|
+
state.doneLeft_ = true;
|
|
4139
|
+
return new Interpreter.State(node.left, state.scope);
|
|
4140
|
+
}
|
|
4141
|
+
if (!state.doneRight_) {
|
|
4142
|
+
if (node.operator === "&&" && !state.value || node.operator === "||" && state.value) {
|
|
4143
|
+
stack.pop();
|
|
4144
|
+
stack[stack.length - 1].value = state.value;
|
|
4145
|
+
} else {
|
|
4146
|
+
state.doneRight_ = true;
|
|
4147
|
+
return new Interpreter.State(node.right, state.scope);
|
|
4148
|
+
}
|
|
4149
|
+
} else {
|
|
4150
|
+
stack.pop();
|
|
4151
|
+
stack[stack.length - 1].value = state.value;
|
|
4152
|
+
}
|
|
4153
|
+
};
|
|
4154
|
+
Interpreter.prototype["stepMemberExpression"] = function(stack, state, node) {
|
|
4155
|
+
if (!state.doneObject_) {
|
|
4156
|
+
state.doneObject_ = true;
|
|
4157
|
+
return new Interpreter.State(node.object, state.scope);
|
|
4158
|
+
}
|
|
4159
|
+
var propName;
|
|
4160
|
+
if (!node.computed) {
|
|
4161
|
+
state.object_ = state.value;
|
|
4162
|
+
propName = node.property.name;
|
|
4163
|
+
} else if (!state.doneProperty_) {
|
|
4164
|
+
state.object_ = state.value;
|
|
4165
|
+
state.doneProperty_ = true;
|
|
4166
|
+
return new Interpreter.State(node.property, state.scope);
|
|
4167
|
+
} else {
|
|
4168
|
+
propName = state.value;
|
|
4169
|
+
}
|
|
4170
|
+
stack.pop();
|
|
4171
|
+
if (state.components) {
|
|
4172
|
+
stack[stack.length - 1].value = [state.object_, propName];
|
|
4173
|
+
} else {
|
|
4174
|
+
var value = this.getProperty(state.object_, propName);
|
|
4175
|
+
if (this.getterStep_) {
|
|
4176
|
+
var func = value;
|
|
4177
|
+
return this.createGetter_(func, state.object_);
|
|
4178
|
+
}
|
|
4179
|
+
stack[stack.length - 1].value = value;
|
|
4180
|
+
}
|
|
4181
|
+
};
|
|
4182
|
+
Interpreter.prototype["stepNewExpression"] = Interpreter.prototype["stepCallExpression"];
|
|
4183
|
+
Interpreter.prototype["stepObjectExpression"] = function(stack, state, node) {
|
|
4184
|
+
var n = state.n_ || 0;
|
|
4185
|
+
var property = node.properties[n];
|
|
4186
|
+
if (!state.object_) {
|
|
4187
|
+
state.object_ = this.createObjectProto(this.OBJECT_PROTO);
|
|
4188
|
+
state.properties_ = Object.create(null);
|
|
4189
|
+
} else {
|
|
4190
|
+
var propName = state.destinationName;
|
|
4191
|
+
if (!state.properties_[propName]) {
|
|
4192
|
+
state.properties_[propName] = {};
|
|
4193
|
+
}
|
|
4194
|
+
state.properties_[propName][property.kind] = state.value;
|
|
4195
|
+
state.n_ = ++n;
|
|
4196
|
+
property = node.properties[n];
|
|
4197
|
+
}
|
|
4198
|
+
if (property) {
|
|
4199
|
+
var key = property.key;
|
|
4200
|
+
if (key.type === "Identifier") {
|
|
4201
|
+
var propName = key.name;
|
|
4202
|
+
} else if (key.type === "Literal") {
|
|
4203
|
+
var propName = key.value;
|
|
4204
|
+
} else {
|
|
4205
|
+
throw SyntaxError("Unknown object structure: " + key.type);
|
|
4206
|
+
}
|
|
4207
|
+
state.destinationName = propName;
|
|
4208
|
+
return new Interpreter.State(property.value, state.scope);
|
|
4209
|
+
}
|
|
4210
|
+
for (var key in state.properties_) {
|
|
4211
|
+
var kinds = state.properties_[key];
|
|
4212
|
+
if ("get" in kinds || "set" in kinds) {
|
|
4213
|
+
var descriptor = {
|
|
4214
|
+
configurable: true,
|
|
4215
|
+
enumerable: true,
|
|
4216
|
+
get: kinds["get"],
|
|
4217
|
+
set: kinds["set"]
|
|
4218
|
+
};
|
|
4219
|
+
this.setProperty(state.object_, key, Interpreter.VALUE_IN_DESCRIPTOR, descriptor);
|
|
4220
|
+
} else {
|
|
4221
|
+
this.setProperty(state.object_, key, kinds["init"]);
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
stack.pop();
|
|
4225
|
+
stack[stack.length - 1].value = state.object_;
|
|
4226
|
+
};
|
|
4227
|
+
Interpreter.prototype["stepProgram"] = function(stack, state, node) {
|
|
4228
|
+
var expression = node.body.shift();
|
|
4229
|
+
if (expression) {
|
|
4230
|
+
state.done = false;
|
|
4231
|
+
return new Interpreter.State(expression, state.scope);
|
|
4232
|
+
}
|
|
4233
|
+
state.done = true;
|
|
4234
|
+
};
|
|
4235
|
+
Interpreter.prototype["stepReturnStatement"] = function(stack, state, node) {
|
|
4236
|
+
if (node.argument && !state.done_) {
|
|
4237
|
+
state.done_ = true;
|
|
4238
|
+
return new Interpreter.State(node.argument, state.scope);
|
|
4239
|
+
}
|
|
4240
|
+
this.unwind(Interpreter.Completion.RETURN, state.value, undefined);
|
|
4241
|
+
};
|
|
4242
|
+
Interpreter.prototype["stepSequenceExpression"] = function(stack, state, node) {
|
|
4243
|
+
var n = state.n_ || 0;
|
|
4244
|
+
var expression = node.expressions[n];
|
|
4245
|
+
if (expression) {
|
|
4246
|
+
state.n_ = n + 1;
|
|
4247
|
+
return new Interpreter.State(expression, state.scope);
|
|
4248
|
+
}
|
|
4249
|
+
stack.pop();
|
|
4250
|
+
stack[stack.length - 1].value = state.value;
|
|
4251
|
+
};
|
|
4252
|
+
Interpreter.prototype["stepSwitchStatement"] = function(stack, state, node) {
|
|
4253
|
+
if (!state.test_) {
|
|
4254
|
+
state.test_ = 1;
|
|
4255
|
+
return new Interpreter.State(node.discriminant, state.scope);
|
|
4256
|
+
}
|
|
4257
|
+
if (state.test_ === 1) {
|
|
4258
|
+
state.test_ = 2;
|
|
4259
|
+
state.switchValue_ = state.value;
|
|
4260
|
+
state.defaultCase_ = -1;
|
|
4261
|
+
}
|
|
4262
|
+
while (true) {
|
|
4263
|
+
var index = state.index_ || 0;
|
|
4264
|
+
var switchCase = node.cases[index];
|
|
4265
|
+
if (!state.matched_ && switchCase && !switchCase.test) {
|
|
4266
|
+
state.defaultCase_ = index;
|
|
4267
|
+
state.index_ = index + 1;
|
|
4268
|
+
continue;
|
|
4269
|
+
}
|
|
4270
|
+
if (!switchCase && !state.matched_ && state.defaultCase_ !== -1) {
|
|
4271
|
+
state.matched_ = true;
|
|
4272
|
+
state.index_ = state.defaultCase_;
|
|
4273
|
+
continue;
|
|
4274
|
+
}
|
|
4275
|
+
if (switchCase) {
|
|
4276
|
+
if (!state.matched_ && !state.tested_ && switchCase.test) {
|
|
4277
|
+
state.tested_ = true;
|
|
4278
|
+
return new Interpreter.State(switchCase.test, state.scope);
|
|
4279
|
+
}
|
|
4280
|
+
if (state.matched_ || state.value === state.switchValue_) {
|
|
4281
|
+
state.matched_ = true;
|
|
4282
|
+
var n = state.n_ || 0;
|
|
4283
|
+
if (switchCase.consequent[n]) {
|
|
4284
|
+
state.isSwitch = true;
|
|
4285
|
+
state.n_ = n + 1;
|
|
4286
|
+
return new Interpreter.State(switchCase.consequent[n], state.scope);
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
state.tested_ = false;
|
|
4290
|
+
state.n_ = 0;
|
|
4291
|
+
state.index_ = index + 1;
|
|
4292
|
+
} else {
|
|
4293
|
+
stack.pop();
|
|
4294
|
+
return;
|
|
4295
|
+
}
|
|
4296
|
+
}
|
|
4297
|
+
};
|
|
4298
|
+
Interpreter.prototype["stepThisExpression"] = function(stack, state, node) {
|
|
4299
|
+
stack.pop();
|
|
4300
|
+
stack[stack.length - 1].value = this.getValueFromScope("this");
|
|
4301
|
+
};
|
|
4302
|
+
Interpreter.prototype["stepThrowStatement"] = function(stack, state, node) {
|
|
4303
|
+
if (!state.done_) {
|
|
4304
|
+
state.done_ = true;
|
|
4305
|
+
return new Interpreter.State(node.argument, state.scope);
|
|
4306
|
+
} else {
|
|
4307
|
+
this.throwException(state.value);
|
|
4308
|
+
}
|
|
4309
|
+
};
|
|
4310
|
+
Interpreter.prototype["stepTryStatement"] = function(stack, state, node) {
|
|
4311
|
+
if (!state.doneBlock_) {
|
|
4312
|
+
state.doneBlock_ = true;
|
|
4313
|
+
return new Interpreter.State(node.block, state.scope);
|
|
4314
|
+
}
|
|
4315
|
+
if (state.cv && state.cv.type === Interpreter.Completion.THROW && !state.doneHandler_ && node.handler) {
|
|
4316
|
+
state.doneHandler_ = true;
|
|
4317
|
+
var scope = this.createSpecialScope(state.scope);
|
|
4318
|
+
this.setProperty(scope.object, node.handler.param.name, state.cv.value);
|
|
4319
|
+
state.cv = undefined;
|
|
4320
|
+
return new Interpreter.State(node.handler.body, scope);
|
|
4321
|
+
}
|
|
4322
|
+
if (!state.doneFinalizer_ && node.finalizer) {
|
|
4323
|
+
state.doneFinalizer_ = true;
|
|
4324
|
+
return new Interpreter.State(node.finalizer, state.scope);
|
|
4325
|
+
}
|
|
4326
|
+
stack.pop();
|
|
4327
|
+
if (state.cv) {
|
|
4328
|
+
this.unwind(state.cv.type, state.cv.value, state.cv.label);
|
|
4329
|
+
}
|
|
4330
|
+
};
|
|
4331
|
+
Interpreter.prototype["stepUnaryExpression"] = function(stack, state, node) {
|
|
4332
|
+
if (!state.done_) {
|
|
4333
|
+
state.done_ = true;
|
|
4334
|
+
var nextState = new Interpreter.State(node.argument, state.scope);
|
|
4335
|
+
nextState.components = node.operator === "delete";
|
|
4336
|
+
return nextState;
|
|
4337
|
+
}
|
|
4338
|
+
stack.pop();
|
|
4339
|
+
var value = state.value;
|
|
4340
|
+
switch (node.operator) {
|
|
4341
|
+
case "-":
|
|
4342
|
+
value = -value;
|
|
4343
|
+
break;
|
|
4344
|
+
case "+":
|
|
4345
|
+
value = +value;
|
|
4346
|
+
break;
|
|
4347
|
+
case "!":
|
|
4348
|
+
value = !value;
|
|
4349
|
+
break;
|
|
4350
|
+
case "~":
|
|
4351
|
+
value = ~value;
|
|
4352
|
+
break;
|
|
4353
|
+
case "delete":
|
|
4354
|
+
var result = true;
|
|
4355
|
+
if (Array.isArray(value)) {
|
|
4356
|
+
var obj = value[0];
|
|
4357
|
+
if (obj === Interpreter.SCOPE_REFERENCE) {
|
|
4358
|
+
obj = state.scope;
|
|
4359
|
+
}
|
|
4360
|
+
var name = String(value[1]);
|
|
4361
|
+
try {
|
|
4362
|
+
delete obj.properties[name];
|
|
4363
|
+
} catch (_e) {
|
|
4364
|
+
if (state.scope.strict) {
|
|
4365
|
+
this.throwException(this.TYPE_ERROR, "Cannot delete property '" + name + "' of '" + obj + "'");
|
|
4366
|
+
} else {
|
|
4367
|
+
result = false;
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
value = result;
|
|
4372
|
+
break;
|
|
4373
|
+
case "typeof":
|
|
4374
|
+
value = value && value.class === "Function" ? "function" : typeof value;
|
|
4375
|
+
break;
|
|
4376
|
+
case "void":
|
|
4377
|
+
value = undefined;
|
|
4378
|
+
break;
|
|
4379
|
+
default:
|
|
4380
|
+
throw SyntaxError("Unknown unary operator: " + node.operator);
|
|
4381
|
+
}
|
|
4382
|
+
stack[stack.length - 1].value = value;
|
|
4383
|
+
};
|
|
4384
|
+
Interpreter.prototype["stepUpdateExpression"] = function(stack, state, node) {
|
|
4385
|
+
if (!state.doneLeft_) {
|
|
4386
|
+
state.doneLeft_ = true;
|
|
4387
|
+
var nextState = new Interpreter.State(node.argument, state.scope);
|
|
4388
|
+
nextState.components = true;
|
|
4389
|
+
return nextState;
|
|
4390
|
+
}
|
|
4391
|
+
if (!state.leftSide_) {
|
|
4392
|
+
state.leftSide_ = state.value;
|
|
4393
|
+
}
|
|
4394
|
+
if (state.doneGetter_) {
|
|
4395
|
+
state.leftValue_ = state.value;
|
|
4396
|
+
}
|
|
4397
|
+
if (!state.doneGetter_) {
|
|
4398
|
+
var leftValue = this.getValue(state.leftSide_);
|
|
4399
|
+
state.leftValue_ = leftValue;
|
|
4400
|
+
if (this.getterStep_) {
|
|
4401
|
+
state.doneGetter_ = true;
|
|
4402
|
+
var func = leftValue;
|
|
4403
|
+
return this.createGetter_(func, state.leftSide_);
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
if (state.doneSetter_) {
|
|
4407
|
+
stack.pop();
|
|
4408
|
+
stack[stack.length - 1].value = state.setterValue_;
|
|
4409
|
+
return;
|
|
4410
|
+
}
|
|
4411
|
+
var leftValue = Number(state.leftValue_);
|
|
4412
|
+
var changeValue;
|
|
4413
|
+
if (node.operator === "++") {
|
|
4414
|
+
changeValue = leftValue + 1;
|
|
4415
|
+
} else if (node.operator === "--") {
|
|
4416
|
+
changeValue = leftValue - 1;
|
|
4417
|
+
} else {
|
|
4418
|
+
throw SyntaxError("Unknown update expression: " + node.operator);
|
|
4419
|
+
}
|
|
4420
|
+
var returnValue = node.prefix ? changeValue : leftValue;
|
|
4421
|
+
var setter = this.setValue(state.leftSide_, changeValue);
|
|
4422
|
+
if (setter) {
|
|
4423
|
+
state.doneSetter_ = true;
|
|
4424
|
+
state.setterValue_ = returnValue;
|
|
4425
|
+
return this.createSetter_(setter, state.leftSide_, changeValue);
|
|
4426
|
+
}
|
|
4427
|
+
stack.pop();
|
|
4428
|
+
stack[stack.length - 1].value = returnValue;
|
|
4429
|
+
};
|
|
4430
|
+
Interpreter.prototype["stepVariableDeclaration"] = function(stack, state, node) {
|
|
4431
|
+
var declarations = node.declarations;
|
|
4432
|
+
var n = state.n_ || 0;
|
|
4433
|
+
var declarationNode = declarations[n];
|
|
4434
|
+
if (state.init_ && declarationNode) {
|
|
4435
|
+
this.setValueToScope(declarationNode.id.name, state.value);
|
|
4436
|
+
state.init_ = false;
|
|
4437
|
+
declarationNode = declarations[++n];
|
|
4438
|
+
}
|
|
4439
|
+
while (declarationNode) {
|
|
4440
|
+
if (declarationNode.init) {
|
|
4441
|
+
state.n_ = n;
|
|
4442
|
+
state.init_ = true;
|
|
4443
|
+
state.destinationName = declarationNode.id.name;
|
|
4444
|
+
return new Interpreter.State(declarationNode.init, state.scope);
|
|
4445
|
+
}
|
|
4446
|
+
declarationNode = declarations[++n];
|
|
4447
|
+
}
|
|
4448
|
+
stack.pop();
|
|
4449
|
+
};
|
|
4450
|
+
Interpreter.prototype["stepWithStatement"] = function(stack, state, node) {
|
|
4451
|
+
if (!state.doneObject_) {
|
|
4452
|
+
state.doneObject_ = true;
|
|
4453
|
+
return new Interpreter.State(node.object, state.scope);
|
|
4454
|
+
}
|
|
4455
|
+
stack.pop();
|
|
4456
|
+
var scope = this.createSpecialScope(state.scope, state.value);
|
|
4457
|
+
return new Interpreter.State(node.body, scope);
|
|
4458
|
+
};
|
|
4459
|
+
Interpreter.prototype["stepWhileStatement"] = Interpreter.prototype["stepDoWhileStatement"];
|
|
4460
|
+
Interpreter.nativeGlobal["Interpreter"] = Interpreter;
|
|
4461
|
+
Interpreter.prototype["step"] = Interpreter.prototype.step;
|
|
4462
|
+
Interpreter.prototype["run"] = Interpreter.prototype.run;
|
|
4463
|
+
Interpreter.prototype["appendCode"] = Interpreter.prototype.appendCode;
|
|
4464
|
+
Interpreter.prototype["createObject"] = Interpreter.prototype.createObject;
|
|
4465
|
+
Interpreter.prototype["createObjectProto"] = Interpreter.prototype.createObjectProto;
|
|
4466
|
+
Interpreter.prototype["createAsyncFunction"] = Interpreter.prototype.createAsyncFunction;
|
|
4467
|
+
Interpreter.prototype["createNativeFunction"] = Interpreter.prototype.createNativeFunction;
|
|
4468
|
+
Interpreter.prototype["getProperty"] = Interpreter.prototype.getProperty;
|
|
4469
|
+
Interpreter.prototype["setProperty"] = Interpreter.prototype.setProperty;
|
|
4470
|
+
Interpreter.prototype["getStatus"] = Interpreter.prototype.getStatus;
|
|
4471
|
+
Interpreter.prototype["nativeToPseudo"] = Interpreter.prototype.nativeToPseudo;
|
|
4472
|
+
Interpreter.prototype["pseudoToNative"] = Interpreter.prototype.pseudoToNative;
|
|
4473
|
+
Interpreter.prototype["getGlobalScope"] = Interpreter.prototype.getGlobalScope;
|
|
4474
|
+
Interpreter.prototype["getStateStack"] = Interpreter.prototype.getStateStack;
|
|
4475
|
+
Interpreter.prototype["setStateStack"] = Interpreter.prototype.setStateStack;
|
|
4476
|
+
Interpreter["VALUE_IN_DESCRIPTOR"] = Interpreter.VALUE_IN_DESCRIPTOR;
|
|
4477
|
+
Interpreter["Status"] = Interpreter.Status;
|
|
4478
|
+
|
|
4479
|
+
// src/task/JavaScriptTask.ts
|
|
4480
|
+
var isValidIdentifier = (key) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
|
|
4481
|
+
function runJavaScript(input2, configuredCode) {
|
|
4482
|
+
const output = {};
|
|
4483
|
+
const code = input2.javascript_code || configuredCode;
|
|
4484
|
+
if (code) {
|
|
4485
|
+
try {
|
|
4486
|
+
const inputVariables = Object.keys(input2).filter((key) => key !== "javascript_code").filter(isValidIdentifier);
|
|
4487
|
+
const inputVariablesString = inputVariables.map((key) => `var ${key} = ${JSON.stringify(input2[key])};`).join(`
|
|
4488
|
+
`);
|
|
4489
|
+
const myInterpreter = new Interpreter(`${inputVariablesString} ${code}`);
|
|
4490
|
+
myInterpreter.run();
|
|
4491
|
+
output.output = myInterpreter.value;
|
|
4492
|
+
} catch (e) {
|
|
4493
|
+
throw new TaskInvalidInputError(`JavaScript execution failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
4494
|
+
}
|
|
4495
|
+
}
|
|
4496
|
+
return output;
|
|
4497
|
+
}
|
|
4498
|
+
var configSchema = {
|
|
4499
|
+
type: "object",
|
|
4500
|
+
properties: {
|
|
4501
|
+
...TaskConfigSchema["properties"],
|
|
4502
|
+
javascript_code: {
|
|
4503
|
+
type: "string",
|
|
4504
|
+
title: "Code",
|
|
4505
|
+
minLength: 1,
|
|
4506
|
+
description: "JavaScript code to execute",
|
|
4507
|
+
format: "code:javascript"
|
|
4508
|
+
}
|
|
4509
|
+
},
|
|
4510
|
+
additionalProperties: false
|
|
4511
|
+
};
|
|
4512
|
+
var inputSchema = {
|
|
4513
|
+
type: "object",
|
|
4514
|
+
properties: {
|
|
4515
|
+
javascript_code: {
|
|
4516
|
+
type: "string",
|
|
4517
|
+
title: "Code",
|
|
4518
|
+
minLength: 1,
|
|
4519
|
+
description: "JavaScript code to execute",
|
|
4520
|
+
format: "code:javascript"
|
|
4521
|
+
}
|
|
4522
|
+
},
|
|
4523
|
+
required: ["javascript_code"],
|
|
4524
|
+
additionalProperties: true
|
|
4525
|
+
};
|
|
4526
|
+
var outputSchema = {
|
|
4527
|
+
type: "object",
|
|
4528
|
+
properties: {
|
|
4529
|
+
output: {
|
|
4530
|
+
title: "Output",
|
|
4531
|
+
description: "The output of the JavaScript code"
|
|
4532
|
+
}
|
|
4533
|
+
},
|
|
4534
|
+
required: ["output"],
|
|
4535
|
+
additionalProperties: false
|
|
4536
|
+
};
|
|
4537
|
+
|
|
4538
|
+
class JavaScriptTask extends Task {
|
|
4539
|
+
static type = "JavaScriptTask";
|
|
4540
|
+
static category = "Utility";
|
|
4541
|
+
static title = "JavaScript Interpreter";
|
|
4542
|
+
static description = "Executes JavaScript code in a sandboxed interpreter environment";
|
|
4543
|
+
static customizable = true;
|
|
4544
|
+
static hasDynamicSchemas = true;
|
|
4545
|
+
static entitlements() {
|
|
4546
|
+
return {
|
|
4547
|
+
entitlements: [
|
|
4548
|
+
{
|
|
4549
|
+
id: Entitlements.CODE_EXECUTION_JS,
|
|
4550
|
+
reason: "Executes user-provided JavaScript code in a sandboxed interpreter"
|
|
4551
|
+
}
|
|
4552
|
+
]
|
|
4553
|
+
};
|
|
4554
|
+
}
|
|
4555
|
+
static configSchema() {
|
|
4556
|
+
return configSchema;
|
|
4557
|
+
}
|
|
4558
|
+
static inputSchema() {
|
|
4559
|
+
return inputSchema;
|
|
4560
|
+
}
|
|
4561
|
+
static outputSchema() {
|
|
4562
|
+
return outputSchema;
|
|
4563
|
+
}
|
|
4564
|
+
inputSchema() {
|
|
4565
|
+
if (this.config?.javascript_code) {
|
|
4566
|
+
if (this.config.inputSchema) {
|
|
4567
|
+
return this.config.inputSchema;
|
|
4568
|
+
}
|
|
4569
|
+
return {
|
|
4570
|
+
type: "object",
|
|
4571
|
+
properties: {},
|
|
4572
|
+
additionalProperties: true
|
|
4573
|
+
};
|
|
4574
|
+
}
|
|
4575
|
+
return inputSchema;
|
|
4576
|
+
}
|
|
4577
|
+
async execute(input2) {
|
|
4578
|
+
return runJavaScript(input2, this.config.javascript_code);
|
|
4579
|
+
}
|
|
4580
|
+
async executePreview(input2) {
|
|
4581
|
+
return runJavaScript(input2, this.config.javascript_code);
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4584
|
+
var javaScript = (input2, config = {}) => {
|
|
4585
|
+
return new JavaScriptTask(config).run(input2);
|
|
4586
|
+
};
|
|
4587
|
+
Workflow.prototype.javaScript = CreateWorkflow(JavaScriptTask);
|
|
4588
|
+
export {
|
|
4589
|
+
javaScript,
|
|
4590
|
+
JavaScriptTask
|
|
4591
|
+
};
|
|
4592
|
+
|
|
4593
|
+
//# debugId=6FEE0CBA2077225564756E2164756E21
|