blob: 24d8d2bfa188bf3544e03083597e1dd7edd8ea2d [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// -------------------------------------------------------------------
6
7(function(global, utils) {
8
9%CheckIsBootstrapping();
10
11// -------------------------------------------------------------------
12// Imports
13
14var ArrayJoin;
15var Bool16x8ToString;
16var Bool32x4ToString;
17var Bool8x16ToString;
18var callSiteReceiverSymbol =
19 utils.ImportNow("call_site_receiver_symbol");
20var callSiteFunctionSymbol =
21 utils.ImportNow("call_site_function_symbol");
22var callSitePositionSymbol =
23 utils.ImportNow("call_site_position_symbol");
24var callSiteStrictSymbol =
25 utils.ImportNow("call_site_strict_symbol");
Ben Murdochc5610432016-08-08 18:44:38 +010026var callSiteWasmObjectSymbol =
27 utils.ImportNow("call_site_wasm_obj_symbol");
28var callSiteWasmFunctionIndexSymbol =
29 utils.ImportNow("call_site_wasm_func_index_symbol");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030var Float32x4ToString;
31var formattedStackTraceSymbol =
32 utils.ImportNow("formatted_stack_trace_symbol");
33var GlobalObject = global.Object;
34var Int16x8ToString;
35var Int32x4ToString;
36var Int8x16ToString;
37var InternalArray = utils.InternalArray;
38var internalErrorSymbol = utils.ImportNow("internal_error_symbol");
Ben Murdochda12d292016-06-02 14:46:10 +010039var ObjectHasOwnProperty;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040var ObjectToString = utils.ImportNow("object_to_string");
41var Script = utils.ImportNow("Script");
42var stackTraceSymbol = utils.ImportNow("stack_trace_symbol");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043var StringIndexOf;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044var SymbolToString;
45var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
46var Uint16x8ToString;
47var Uint32x4ToString;
48var Uint8x16ToString;
49
50utils.Import(function(from) {
51 ArrayJoin = from.ArrayJoin;
52 Bool16x8ToString = from.Bool16x8ToString;
53 Bool32x4ToString = from.Bool32x4ToString;
54 Bool8x16ToString = from.Bool8x16ToString;
55 Float32x4ToString = from.Float32x4ToString;
56 Int16x8ToString = from.Int16x8ToString;
57 Int32x4ToString = from.Int32x4ToString;
58 Int8x16ToString = from.Int8x16ToString;
Ben Murdochda12d292016-06-02 14:46:10 +010059 ObjectHasOwnProperty = from.ObjectHasOwnProperty;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 StringIndexOf = from.StringIndexOf;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061 SymbolToString = from.SymbolToString;
62 Uint16x8ToString = from.Uint16x8ToString;
63 Uint32x4ToString = from.Uint32x4ToString;
64 Uint8x16ToString = from.Uint8x16ToString;
65});
66
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067// -------------------------------------------------------------------
68
69var GlobalError;
70var GlobalTypeError;
71var GlobalRangeError;
72var GlobalURIError;
73var GlobalSyntaxError;
74var GlobalReferenceError;
75var GlobalEvalError;
76
77
78function NoSideEffectsObjectToString() {
79 if (IS_UNDEFINED(this)) return "[object Undefined]";
80 if (IS_NULL(this)) return "[object Null]";
81 var O = TO_OBJECT(this);
82 var builtinTag = %_ClassOf(O);
Ben Murdochda12d292016-06-02 14:46:10 +010083 var tag = %GetDataProperty(O, toStringTagSymbol);
84 if (!IS_STRING(tag)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085 tag = builtinTag;
86 }
87 return `[object ${tag}]`;
88}
89
90function IsErrorObject(obj) {
91 return HAS_PRIVATE(obj, stackTraceSymbol);
92}
93
94function NoSideEffectsErrorToString() {
95 var name = %GetDataProperty(this, "name");
96 var message = %GetDataProperty(this, "message");
97 name = IS_UNDEFINED(name) ? "Error" : NoSideEffectsToString(name);
98 message = IS_UNDEFINED(message) ? "" : NoSideEffectsToString(message);
99 if (name == "") return message;
100 if (message == "") return name;
101 return `${name}: ${message}`;
102}
103
104function NoSideEffectsToString(obj) {
105 if (IS_STRING(obj)) return obj;
106 if (IS_NUMBER(obj)) return %_NumberToString(obj);
107 if (IS_BOOLEAN(obj)) return obj ? 'true' : 'false';
108 if (IS_UNDEFINED(obj)) return 'undefined';
109 if (IS_NULL(obj)) return 'null';
110 if (IS_FUNCTION(obj)) {
111 var str = %FunctionToString(obj);
112 if (str.length > 128) {
113 str = %_SubString(str, 0, 111) + "...<omitted>..." +
114 %_SubString(str, str.length - 2, str.length);
115 }
116 return str;
117 }
118 if (IS_SYMBOL(obj)) return %_Call(SymbolToString, obj);
119 if (IS_SIMD_VALUE(obj)) {
120 switch (typeof(obj)) {
121 case 'float32x4': return %_Call(Float32x4ToString, obj);
122 case 'int32x4': return %_Call(Int32x4ToString, obj);
123 case 'int16x8': return %_Call(Int16x8ToString, obj);
124 case 'int8x16': return %_Call(Int8x16ToString, obj);
125 case 'uint32x4': return %_Call(Uint32x4ToString, obj);
126 case 'uint16x8': return %_Call(Uint16x8ToString, obj);
127 case 'uint8x16': return %_Call(Uint8x16ToString, obj);
128 case 'bool32x4': return %_Call(Bool32x4ToString, obj);
129 case 'bool16x8': return %_Call(Bool16x8ToString, obj);
130 case 'bool8x16': return %_Call(Bool8x16ToString, obj);
131 }
132 }
133
134 if (IS_RECEIVER(obj)) {
135 // When internally formatting error objects, use a side-effects-free version
136 // of Error.prototype.toString independent of the actually installed
137 // toString method.
138 if (IsErrorObject(obj) ||
139 %GetDataProperty(obj, "toString") === ErrorToString) {
140 return %_Call(NoSideEffectsErrorToString, obj);
141 }
142
143 if (%GetDataProperty(obj, "toString") === ObjectToString) {
144 var constructor = %GetDataProperty(obj, "constructor");
145 if (IS_FUNCTION(constructor)) {
146 var constructor_name = %FunctionGetName(constructor);
147 if (constructor_name != "") return `#<${constructor_name}>`;
148 }
149 }
150 }
151
152 return %_Call(NoSideEffectsObjectToString, obj);
153}
154
155
156function MakeGenericError(constructor, type, arg0, arg1, arg2) {
157 var error = new constructor(FormatMessage(type, arg0, arg1, arg2));
158 error[internalErrorSymbol] = true;
159 return error;
160}
161
162
163/**
164 * Set up the Script function and constructor.
165 */
166%FunctionSetInstanceClassName(Script, 'Script');
167%AddNamedProperty(Script.prototype, 'constructor', Script,
168 DONT_ENUM | DONT_DELETE | READ_ONLY);
169%SetCode(Script, function(x) {
170 // Script objects can only be created by the VM.
171 throw MakeError(kUnsupported);
172});
173
174
175// Helper functions; called from the runtime system.
176function FormatMessage(type, arg0, arg1, arg2) {
177 var arg0 = NoSideEffectsToString(arg0);
178 var arg1 = NoSideEffectsToString(arg1);
179 var arg2 = NoSideEffectsToString(arg2);
180 try {
181 return %FormatMessageString(type, arg0, arg1, arg2);
182 } catch (e) {
183 return "<error>";
184 }
185}
186
187
188function GetLineNumber(message) {
189 var start_position = %MessageGetStartPosition(message);
190 if (start_position == -1) return kNoLineNumberInfo;
191 var script = %MessageGetScript(message);
192 var location = script.locationFromPosition(start_position, true);
193 if (location == null) return kNoLineNumberInfo;
194 return location.line + 1;
195}
196
197
198//Returns the offset of the given position within the containing line.
199function GetColumnNumber(message) {
200 var script = %MessageGetScript(message);
201 var start_position = %MessageGetStartPosition(message);
202 var location = script.locationFromPosition(start_position, true);
203 if (location == null) return -1;
204 return location.column;
205}
206
207
208// Returns the source code line containing the given source
209// position, or the empty string if the position is invalid.
210function GetSourceLine(message) {
211 var script = %MessageGetScript(message);
212 var start_position = %MessageGetStartPosition(message);
213 var location = script.locationFromPosition(start_position, true);
214 if (location == null) return "";
Ben Murdoch61f157c2016-09-16 13:49:30 +0100215 return location.sourceText;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216}
217
Ben Murdochc5610432016-08-08 18:44:38 +0100218
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219/**
220 * Get information on a specific source position.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100221 * Returns an object with the following following properties:
222 * script : script object for the source
223 * line : source line number
224 * column : source column within the line
225 * position : position within the source
226 * sourceText : a string containing the current line
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 * @param {number} position The source position
228 * @param {boolean} include_resource_offset Set to true to have the resource
229 * offset added to the location
Ben Murdoch61f157c2016-09-16 13:49:30 +0100230 * @return If line is negative or not in the source null is returned.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 */
232function ScriptLocationFromPosition(position,
233 include_resource_offset) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100234 return %ScriptPositionInfo(this, position, !!include_resource_offset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235}
236
237
238/**
239 * If sourceURL comment is available returns sourceURL comment contents.
240 * Otherwise, script name is returned. See
241 * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
242 * and Source Map Revision 3 proposal for details on using //# sourceURL and
243 * deprecated //@ sourceURL comment to identify scripts that don't have name.
244 *
245 * @return {?string} script name if present, value for //# sourceURL comment or
246 * deprecated //@ sourceURL comment otherwise.
247 */
248function ScriptNameOrSourceURL() {
249 if (this.source_url) return this.source_url;
250 return this.name;
251}
252
253
254utils.SetUpLockedPrototype(Script, [
255 "source",
256 "name",
257 "source_url",
258 "source_mapping_url",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 "line_offset",
260 "column_offset"
261 ], [
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 "locationFromPosition", ScriptLocationFromPosition,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 "nameOrSourceURL", ScriptNameOrSourceURL,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264 ]
265);
266
267
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268function GetStackTraceLine(recv, fun, pos, isGlobal) {
269 return new CallSite(recv, fun, pos, false).toString();
270}
271
272// ----------------------------------------------------------------------------
273// Error implementation
274
275function CallSite(receiver, fun, pos, strict_mode) {
Ben Murdochc5610432016-08-08 18:44:38 +0100276 // For wasm frames, receiver is the wasm object and fun is the function index
277 // instead of an actual function.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100278 if (!IS_FUNCTION(fun) && !%IsWasmObject(receiver)) {
279 throw MakeTypeError(kCallSiteExpectsFunction, typeof receiver, typeof fun);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 }
281
282 if (IS_UNDEFINED(new.target)) {
283 return new CallSite(receiver, fun, pos, strict_mode);
284 }
285
Ben Murdochc5610432016-08-08 18:44:38 +0100286 if (IS_FUNCTION(fun)) {
287 SET_PRIVATE(this, callSiteReceiverSymbol, receiver);
288 SET_PRIVATE(this, callSiteFunctionSymbol, fun);
289 } else {
290 SET_PRIVATE(this, callSiteWasmObjectSymbol, receiver);
291 SET_PRIVATE(this, callSiteWasmFunctionIndexSymbol, TO_UINT32(fun));
292 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 SET_PRIVATE(this, callSitePositionSymbol, TO_INT32(pos));
294 SET_PRIVATE(this, callSiteStrictSymbol, TO_BOOLEAN(strict_mode));
295}
296
Ben Murdochda12d292016-06-02 14:46:10 +0100297function CheckCallSite(obj, name) {
Ben Murdochc5610432016-08-08 18:44:38 +0100298 if (!IS_RECEIVER(obj) || !HAS_PRIVATE(obj, callSitePositionSymbol)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100299 throw MakeTypeError(kCallSiteMethod, name);
300 }
301}
302
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303function CallSiteGetThis() {
Ben Murdochda12d292016-06-02 14:46:10 +0100304 CheckCallSite(this, "getThis");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305 return GET_PRIVATE(this, callSiteStrictSymbol)
306 ? UNDEFINED : GET_PRIVATE(this, callSiteReceiverSymbol);
307}
308
309function CallSiteGetFunction() {
Ben Murdochda12d292016-06-02 14:46:10 +0100310 CheckCallSite(this, "getFunction");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 return GET_PRIVATE(this, callSiteStrictSymbol)
312 ? UNDEFINED : GET_PRIVATE(this, callSiteFunctionSymbol);
313}
314
315function CallSiteGetPosition() {
Ben Murdochda12d292016-06-02 14:46:10 +0100316 CheckCallSite(this, "getPosition");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 return GET_PRIVATE(this, callSitePositionSymbol);
318}
319
320function CallSiteGetTypeName() {
Ben Murdochda12d292016-06-02 14:46:10 +0100321 CheckCallSite(this, "getTypeName");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322 return GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), false);
323}
324
325function CallSiteIsToplevel() {
Ben Murdochda12d292016-06-02 14:46:10 +0100326 CheckCallSite(this, "isTopLevel");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 return %CallSiteIsToplevelRT(this);
328}
329
330function CallSiteIsEval() {
Ben Murdochda12d292016-06-02 14:46:10 +0100331 CheckCallSite(this, "isEval");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332 return %CallSiteIsEvalRT(this);
333}
334
335function CallSiteGetEvalOrigin() {
Ben Murdochda12d292016-06-02 14:46:10 +0100336 CheckCallSite(this, "getEvalOrigin");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 var script = %FunctionGetScript(GET_PRIVATE(this, callSiteFunctionSymbol));
338 return FormatEvalOrigin(script);
339}
340
341function CallSiteGetScriptNameOrSourceURL() {
Ben Murdochda12d292016-06-02 14:46:10 +0100342 CheckCallSite(this, "getScriptNameOrSourceURL");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 return %CallSiteGetScriptNameOrSourceUrlRT(this);
344}
345
346function CallSiteGetFunctionName() {
347 // See if the function knows its own name
Ben Murdochda12d292016-06-02 14:46:10 +0100348 CheckCallSite(this, "getFunctionName");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349 return %CallSiteGetFunctionNameRT(this);
350}
351
352function CallSiteGetMethodName() {
353 // See if we can find a unique property on the receiver that holds
354 // this function.
Ben Murdochda12d292016-06-02 14:46:10 +0100355 CheckCallSite(this, "getMethodName");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 return %CallSiteGetMethodNameRT(this);
357}
358
359function CallSiteGetFileName() {
Ben Murdochda12d292016-06-02 14:46:10 +0100360 CheckCallSite(this, "getFileName");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361 return %CallSiteGetFileNameRT(this);
362}
363
364function CallSiteGetLineNumber() {
Ben Murdochc5610432016-08-08 18:44:38 +0100365 if (HAS_PRIVATE(this, callSiteWasmObjectSymbol)) {
366 return GET_PRIVATE(this, callSiteWasmFunctionIndexSymbol);
367 }
Ben Murdochda12d292016-06-02 14:46:10 +0100368 CheckCallSite(this, "getLineNumber");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000369 return %CallSiteGetLineNumberRT(this);
370}
371
372function CallSiteGetColumnNumber() {
Ben Murdochda12d292016-06-02 14:46:10 +0100373 CheckCallSite(this, "getColumnNumber");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374 return %CallSiteGetColumnNumberRT(this);
375}
376
377function CallSiteIsNative() {
Ben Murdochda12d292016-06-02 14:46:10 +0100378 CheckCallSite(this, "isNative");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379 return %CallSiteIsNativeRT(this);
380}
381
382function CallSiteIsConstructor() {
Ben Murdochda12d292016-06-02 14:46:10 +0100383 CheckCallSite(this, "isConstructor");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 return %CallSiteIsConstructorRT(this);
385}
386
387function CallSiteToString() {
Ben Murdochc5610432016-08-08 18:44:38 +0100388 if (HAS_PRIVATE(this, callSiteWasmObjectSymbol)) {
389 var funName = this.getFunctionName();
390 var funcIndex = GET_PRIVATE(this, callSiteWasmFunctionIndexSymbol);
391 var pos = this.getPosition();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100392 if (IS_NULL(funName)) funName = "<WASM UNNAMED>";
393 return funName + " (<WASM>[" + funcIndex + "]+" + pos + ")";
Ben Murdochc5610432016-08-08 18:44:38 +0100394 }
395
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396 var fileName;
397 var fileLocation = "";
398 if (this.isNative()) {
399 fileLocation = "native";
400 } else {
401 fileName = this.getScriptNameOrSourceURL();
402 if (!fileName && this.isEval()) {
403 fileLocation = this.getEvalOrigin();
404 fileLocation += ", "; // Expecting source position to follow.
405 }
406
407 if (fileName) {
408 fileLocation += fileName;
409 } else {
410 // Source code does not originate from a file and is not native, but we
411 // can still get the source position inside the source string, e.g. in
412 // an eval string.
413 fileLocation += "<anonymous>";
414 }
415 var lineNumber = this.getLineNumber();
416 if (lineNumber != null) {
417 fileLocation += ":" + lineNumber;
418 var columnNumber = this.getColumnNumber();
419 if (columnNumber) {
420 fileLocation += ":" + columnNumber;
421 }
422 }
423 }
424
425 var line = "";
426 var functionName = this.getFunctionName();
427 var addSuffix = true;
428 var isConstructor = this.isConstructor();
429 var isMethodCall = !(this.isToplevel() || isConstructor);
430 if (isMethodCall) {
431 var typeName = GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), true);
432 var methodName = this.getMethodName();
433 if (functionName) {
434 if (typeName && %_Call(StringIndexOf, functionName, typeName) != 0) {
435 line += typeName + ".";
436 }
437 line += functionName;
438 if (methodName &&
439 (%_Call(StringIndexOf, functionName, "." + methodName) !=
440 functionName.length - methodName.length - 1)) {
441 line += " [as " + methodName + "]";
442 }
443 } else {
444 line += typeName + "." + (methodName || "<anonymous>");
445 }
446 } else if (isConstructor) {
447 line += "new " + (functionName || "<anonymous>");
448 } else if (functionName) {
449 line += functionName;
450 } else {
451 line += fileLocation;
452 addSuffix = false;
453 }
454 if (addSuffix) {
455 line += " (" + fileLocation + ")";
456 }
457 return line;
458}
459
460utils.SetUpLockedPrototype(CallSite, ["receiver", "fun", "pos"], [
461 "getThis", CallSiteGetThis,
462 "getTypeName", CallSiteGetTypeName,
463 "isToplevel", CallSiteIsToplevel,
464 "isEval", CallSiteIsEval,
465 "getEvalOrigin", CallSiteGetEvalOrigin,
466 "getScriptNameOrSourceURL", CallSiteGetScriptNameOrSourceURL,
467 "getFunction", CallSiteGetFunction,
468 "getFunctionName", CallSiteGetFunctionName,
469 "getMethodName", CallSiteGetMethodName,
470 "getFileName", CallSiteGetFileName,
471 "getLineNumber", CallSiteGetLineNumber,
472 "getColumnNumber", CallSiteGetColumnNumber,
473 "isNative", CallSiteIsNative,
474 "getPosition", CallSiteGetPosition,
475 "isConstructor", CallSiteIsConstructor,
476 "toString", CallSiteToString
477]);
478
479
480function FormatEvalOrigin(script) {
481 var sourceURL = script.nameOrSourceURL();
482 if (sourceURL) {
483 return sourceURL;
484 }
485
486 var eval_origin = "eval at ";
487 if (script.eval_from_function_name) {
488 eval_origin += script.eval_from_function_name;
489 } else {
490 eval_origin += "<anonymous>";
491 }
492
493 var eval_from_script = script.eval_from_script;
494 if (eval_from_script) {
495 if (eval_from_script.compilation_type == COMPILATION_TYPE_EVAL) {
496 // eval script originated from another eval.
497 eval_origin += " (" + FormatEvalOrigin(eval_from_script) + ")";
498 } else {
499 // eval script originated from "real" source.
500 if (eval_from_script.name) {
501 eval_origin += " (" + eval_from_script.name;
502 var location = eval_from_script.locationFromPosition(
503 script.eval_from_script_position, true);
504 if (location) {
505 eval_origin += ":" + (location.line + 1);
506 eval_origin += ":" + (location.column + 1);
507 }
508 eval_origin += ")";
509 } else {
510 eval_origin += " (unknown source)";
511 }
512 }
513 }
514
515 return eval_origin;
516}
517
518
519function FormatErrorString(error) {
520 try {
521 return %_Call(ErrorToString, error);
522 } catch (e) {
523 try {
524 return "<error: " + e + ">";
525 } catch (ee) {
526 return "<error>";
527 }
528 }
529}
530
531
532function GetStackFrames(raw_stack) {
Ben Murdochc5610432016-08-08 18:44:38 +0100533 var internal_raw_stack = new InternalArray();
534 %MoveArrayContents(raw_stack, internal_raw_stack);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000535 var frames = new InternalArray();
Ben Murdochc5610432016-08-08 18:44:38 +0100536 var sloppy_frames = internal_raw_stack[0];
537 for (var i = 1; i < internal_raw_stack.length; i += 4) {
538 var recv = internal_raw_stack[i];
539 var fun = internal_raw_stack[i + 1];
540 var code = internal_raw_stack[i + 2];
541 var pc = internal_raw_stack[i + 3];
542 // For traps in wasm, the bytecode offset is passed as (-1 - offset).
543 // Otherwise, lookup the position from the pc.
544 var pos = IS_NUMBER(fun) && pc < 0 ? (-1 - pc) :
545 %FunctionGetPositionForOffset(code, pc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546 sloppy_frames--;
547 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
548 }
549 return frames;
550}
551
552
553// Flag to prevent recursive call of Error.prepareStackTrace.
554var formatting_custom_stack_trace = false;
555
556
557function FormatStackTrace(obj, raw_stack) {
558 var frames = GetStackFrames(raw_stack);
559 if (IS_FUNCTION(GlobalError.prepareStackTrace) &&
560 !formatting_custom_stack_trace) {
561 var array = [];
562 %MoveArrayContents(frames, array);
563 formatting_custom_stack_trace = true;
564 var stack_trace = UNDEFINED;
565 try {
566 stack_trace = GlobalError.prepareStackTrace(obj, array);
567 } catch (e) {
568 throw e; // The custom formatting function threw. Rethrow.
569 } finally {
570 formatting_custom_stack_trace = false;
571 }
572 return stack_trace;
573 }
574
575 var lines = new InternalArray();
576 lines.push(FormatErrorString(obj));
577 for (var i = 0; i < frames.length; i++) {
578 var frame = frames[i];
579 var line;
580 try {
581 line = frame.toString();
582 } catch (e) {
583 try {
584 line = "<error: " + e + ">";
585 } catch (ee) {
586 // Any code that reaches this point is seriously nasty!
587 line = "<error>";
588 }
589 }
590 lines.push(" at " + line);
591 }
592 return %_Call(ArrayJoin, lines, "\n");
593}
594
595
596function GetTypeName(receiver, requireConstructor) {
597 if (IS_NULL_OR_UNDEFINED(receiver)) return null;
598 if (IS_PROXY(receiver)) return "Proxy";
599
600 var constructor = %GetDataProperty(TO_OBJECT(receiver), "constructor");
601 if (!IS_FUNCTION(constructor)) {
602 return requireConstructor ? null : %_Call(NoSideEffectsToString, receiver);
603 }
604 return %FunctionGetName(constructor);
605}
606
607
608// Format the stack trace if not yet done, and return it.
609// Cache the formatted stack trace on the holder.
610var StackTraceGetter = function() {
611 var formatted_stack_trace = UNDEFINED;
612 var holder = this;
613 while (holder) {
614 var formatted_stack_trace =
615 GET_PRIVATE(holder, formattedStackTraceSymbol);
616 if (IS_UNDEFINED(formatted_stack_trace)) {
617 // No formatted stack trace available.
618 var stack_trace = GET_PRIVATE(holder, stackTraceSymbol);
619 if (IS_UNDEFINED(stack_trace)) {
620 // Neither formatted nor structured stack trace available.
621 // Look further up the prototype chain.
Ben Murdochc5610432016-08-08 18:44:38 +0100622 holder = %object_get_prototype_of(holder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000623 continue;
624 }
625 formatted_stack_trace = FormatStackTrace(holder, stack_trace);
626 SET_PRIVATE(holder, stackTraceSymbol, UNDEFINED);
627 SET_PRIVATE(holder, formattedStackTraceSymbol, formatted_stack_trace);
628 }
629 return formatted_stack_trace;
630 }
631 return UNDEFINED;
632};
633
634
635// If the receiver equals the holder, set the formatted stack trace that the
636// getter returns.
637var StackTraceSetter = function(v) {
638 if (IsErrorObject(this)) {
639 SET_PRIVATE(this, stackTraceSymbol, UNDEFINED);
640 SET_PRIVATE(this, formattedStackTraceSymbol, v);
641 }
642};
643
644
645// Use a dummy function since we do not actually want to capture a stack trace
646// when constructing the initial Error prototytpes.
647var captureStackTrace = function() {};
648
649
650// Set up special error type constructors.
651function SetUpError(error_function) {
652 %FunctionSetInstanceClassName(error_function, 'Error');
653 var name = error_function.name;
654 var prototype = new GlobalObject();
655 if (name !== 'Error') {
656 %InternalSetPrototype(error_function, GlobalError);
657 %InternalSetPrototype(prototype, GlobalError.prototype);
658 }
659 %FunctionSetPrototype(error_function, prototype);
660
661 %AddNamedProperty(error_function.prototype, 'name', name, DONT_ENUM);
662 %AddNamedProperty(error_function.prototype, 'message', '', DONT_ENUM);
663 %AddNamedProperty(
664 error_function.prototype, 'constructor', error_function, DONT_ENUM);
665
666 %SetCode(error_function, function(m) {
667 if (IS_UNDEFINED(new.target)) return new error_function(m);
668
669 try { captureStackTrace(this, error_function); } catch (e) { }
670 // Define all the expected properties directly on the error
671 // object. This avoids going through getters and setters defined
672 // on prototype objects.
673 if (!IS_UNDEFINED(m)) {
674 %AddNamedProperty(this, 'message', TO_STRING(m), DONT_ENUM);
675 }
676 });
677
678 %SetNativeFlag(error_function);
679 return error_function;
680};
681
682GlobalError = SetUpError(global.Error);
683GlobalEvalError = SetUpError(global.EvalError);
684GlobalRangeError = SetUpError(global.RangeError);
685GlobalReferenceError = SetUpError(global.ReferenceError);
686GlobalSyntaxError = SetUpError(global.SyntaxError);
687GlobalTypeError = SetUpError(global.TypeError);
688GlobalURIError = SetUpError(global.URIError);
689
690utils.InstallFunctions(GlobalError.prototype, DONT_ENUM,
691 ['toString', ErrorToString]);
692
693function ErrorToString() {
694 if (!IS_RECEIVER(this)) {
695 throw MakeTypeError(kCalledOnNonObject, "Error.prototype.toString");
696 }
697
698 var name = this.name;
699 name = IS_UNDEFINED(name) ? "Error" : TO_STRING(name);
700
701 var message = this.message;
702 message = IS_UNDEFINED(message) ? "" : TO_STRING(message);
703
704 if (name == "") return message;
705 if (message == "") return name;
706 return `${name}: ${message}`
707}
708
709function MakeError(type, arg0, arg1, arg2) {
710 return MakeGenericError(GlobalError, type, arg0, arg1, arg2);
711}
712
713function MakeRangeError(type, arg0, arg1, arg2) {
714 return MakeGenericError(GlobalRangeError, type, arg0, arg1, arg2);
715}
716
717function MakeSyntaxError(type, arg0, arg1, arg2) {
718 return MakeGenericError(GlobalSyntaxError, type, arg0, arg1, arg2);
719}
720
721function MakeTypeError(type, arg0, arg1, arg2) {
722 return MakeGenericError(GlobalTypeError, type, arg0, arg1, arg2);
723}
724
725function MakeURIError() {
726 return MakeGenericError(GlobalURIError, kURIMalformed);
727}
728
729// Boilerplate for exceptions for stack overflows. Used from
730// Isolate::StackOverflow().
731var StackOverflowBoilerplate = MakeRangeError(kStackOverflow);
732utils.InstallGetterSetter(StackOverflowBoilerplate, 'stack',
733 StackTraceGetter, StackTraceSetter)
734
735// Define actual captureStackTrace function after everything has been set up.
736captureStackTrace = function captureStackTrace(obj, cons_opt) {
737 // Define accessors first, as this may fail and throw.
Ben Murdochc5610432016-08-08 18:44:38 +0100738 %object_define_property(obj, 'stack', { get: StackTraceGetter,
739 set: StackTraceSetter,
740 configurable: true });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace);
742};
743
744GlobalError.captureStackTrace = captureStackTrace;
745
746%InstallToContext([
747 "get_stack_trace_line_fun", GetStackTraceLine,
748 "make_error_function", MakeGenericError,
749 "make_range_error", MakeRangeError,
750 "make_type_error", MakeTypeError,
751 "message_get_column_number", GetColumnNumber,
752 "message_get_line_number", GetLineNumber,
753 "message_get_source_line", GetSourceLine,
754 "no_side_effects_to_string_fun", NoSideEffectsToString,
755 "stack_overflow_boilerplate", StackOverflowBoilerplate,
756]);
757
758utils.Export(function(to) {
759 to.ErrorToString = ErrorToString;
760 to.MakeError = MakeError;
761 to.MakeRangeError = MakeRangeError;
762 to.MakeSyntaxError = MakeSyntaxError;
763 to.MakeTypeError = MakeTypeError;
764 to.MakeURIError = MakeURIError;
765});
766
767});