Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/workers/WorkerError.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "WorkerError.h"
8
9
#include "mozilla/DOMEventTargetHelper.h"
10
#include "mozilla/dom/ErrorEvent.h"
11
#include "mozilla/dom/ErrorEventBinding.h"
12
#include "mozilla/dom/ServiceWorkerManager.h"
13
#include "mozilla/dom/SimpleGlobalObject.h"
14
#include "mozilla/dom/WorkerDebuggerGlobalScopeBinding.h"
15
#include "mozilla/dom/WorkerGlobalScopeBinding.h"
16
#include "mozilla/EventDispatcher.h"
17
#include "nsGlobalWindowInner.h"
18
#include "nsIConsoleService.h"
19
#include "nsScriptError.h"
20
#include "WorkerRunnable.h"
21
#include "WorkerPrivate.h"
22
#include "WorkerScope.h"
23
24
namespace mozilla {
25
namespace dom {
26
27
namespace {
28
29
class ReportErrorRunnable final : public WorkerRunnable
30
{
31
  WorkerErrorReport mReport;
32
33
public:
34
  // aWorkerPrivate is the worker thread we're on (or the main thread, if null)
35
  // aTarget is the worker object that we are going to fire an error at
36
  // (if any).
37
  static void
38
  ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
39
              bool aFireAtScope, DOMEventTargetHelper* aTarget,
40
              const WorkerErrorReport& aReport, uint64_t aInnerWindowId,
41
              JS::Handle<JS::Value> aException = JS::NullHandleValue)
42
0
  {
43
0
    if (aWorkerPrivate) {
44
0
      aWorkerPrivate->AssertIsOnWorkerThread();
45
0
    } else {
46
0
      AssertIsOnMainThread();
47
0
    }
48
0
49
0
    // We should not fire error events for warnings but instead make sure that
50
0
    // they show up in the error console.
51
0
    if (!JSREPORT_IS_WARNING(aReport.mFlags)) {
52
0
      // First fire an ErrorEvent at the worker.
53
0
      RootedDictionary<ErrorEventInit> init(aCx);
54
0
55
0
      if (aReport.mMutedError) {
56
0
        init.mMessage.AssignLiteral("Script error.");
57
0
      } else {
58
0
        init.mMessage = aReport.mMessage;
59
0
        init.mFilename = aReport.mFilename;
60
0
        init.mLineno = aReport.mLineNumber;
61
0
        init.mError = aException;
62
0
      }
63
0
64
0
      init.mCancelable = true;
65
0
      init.mBubbles = false;
66
0
67
0
      if (aTarget) {
68
0
        RefPtr<ErrorEvent> event =
69
0
          ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
70
0
        event->SetTrusted(true);
71
0
72
0
        bool defaultActionEnabled =
73
0
          aTarget->DispatchEvent(*event, CallerType::System, IgnoreErrors());
74
0
        if (!defaultActionEnabled) {
75
0
          return;
76
0
        }
77
0
      }
78
0
79
0
      // Now fire an event at the global object, but don't do that if the error
80
0
      // code is too much recursion and this is the same script threw the error.
81
0
      // XXXbz the interaction of this with worker errors seems kinda broken.
82
0
      // An overrecursion in the debugger or debugger sandbox will get turned
83
0
      // into an error event on our parent worker!
84
0
      // https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks making this
85
0
      // better.
86
0
      if (aFireAtScope &&
87
0
          (aTarget || aReport.mErrorNumber != JSMSG_OVER_RECURSED)) {
88
0
        JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
89
0
        NS_ASSERTION(global, "This should never be null!");
90
0
91
0
        nsEventStatus status = nsEventStatus_eIgnore;
92
0
93
0
        if (aWorkerPrivate) {
94
0
          WorkerGlobalScope* globalScope = nullptr;
95
0
          UNWRAP_OBJECT(WorkerGlobalScope, &global, globalScope);
96
0
97
0
          if (!globalScope) {
98
0
            WorkerDebuggerGlobalScope* globalScope = nullptr;
99
0
            UNWRAP_OBJECT(WorkerDebuggerGlobalScope, &global, globalScope);
100
0
101
0
            MOZ_ASSERT_IF(globalScope, globalScope->GetWrapperPreserveColor() == global);
102
0
            if (globalScope || IsWorkerDebuggerSandbox(global)) {
103
0
              aWorkerPrivate->ReportErrorToDebugger(aReport.mFilename, aReport.mLineNumber,
104
0
                                                    aReport.mMessage);
105
0
              return;
106
0
            }
107
0
108
0
            MOZ_ASSERT(SimpleGlobalObject::SimpleGlobalType(global) ==
109
0
                         SimpleGlobalObject::GlobalType::BindingDetail);
110
0
            // XXXbz We should really log this to console, but unwinding out of
111
0
            // this stuff without ending up firing any events is ... hard.  Just
112
0
            // return for now.
113
0
            // https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks
114
0
            // making this better.
115
0
            return;
116
0
          }
117
0
118
0
          MOZ_ASSERT(globalScope->GetWrapperPreserveColor() == global);
119
0
120
0
          RefPtr<ErrorEvent> event =
121
0
            ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
122
0
          event->SetTrusted(true);
123
0
124
0
          if (NS_FAILED(EventDispatcher::DispatchDOMEvent(ToSupports(globalScope),
125
0
                                                          nullptr,
126
0
                                                          event, nullptr,
127
0
                                                          &status))) {
128
0
            NS_WARNING("Failed to dispatch worker thread error event!");
129
0
            status = nsEventStatus_eIgnore;
130
0
          }
131
0
        }
132
0
        else if (nsGlobalWindowInner* win = xpc::WindowOrNull(global)) {
133
0
          MOZ_ASSERT(NS_IsMainThread());
134
0
135
0
          if (!win->HandleScriptError(init, &status)) {
136
0
            NS_WARNING("Failed to dispatch main thread error event!");
137
0
            status = nsEventStatus_eIgnore;
138
0
          }
139
0
        }
140
0
141
0
        // Was preventDefault() called?
142
0
        if (status == nsEventStatus_eConsumeNoDefault) {
143
0
          return;
144
0
        }
145
0
      }
146
0
    }
147
0
148
0
    // Now fire a runnable to do the same on the parent's thread if we can.
149
0
    if (aWorkerPrivate) {
150
0
      RefPtr<ReportErrorRunnable> runnable =
151
0
        new ReportErrorRunnable(aWorkerPrivate, aReport);
152
0
      runnable->Dispatch();
153
0
      return;
154
0
    }
155
0
156
0
    // Otherwise log an error to the error console.
157
0
    WorkerErrorReport::LogErrorToConsole(aReport, aInnerWindowId);
158
0
  }
159
160
  ReportErrorRunnable(WorkerPrivate* aWorkerPrivate,
161
                      const WorkerErrorReport& aReport)
162
  : WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount),
163
    mReport(aReport)
164
0
  { }
165
166
private:
167
  virtual void
168
  PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
169
0
  {
170
0
    aWorkerPrivate->AssertIsOnWorkerThread();
171
0
172
0
    // Dispatch may fail if the worker was canceled, no need to report that as
173
0
    // an error, so don't call base class PostDispatch.
174
0
  }
175
176
  virtual bool
177
  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
178
0
  {
179
0
    uint64_t innerWindowId;
180
0
    bool fireAtScope = true;
181
0
182
0
    bool workerIsAcceptingEvents = aWorkerPrivate->IsAcceptingEvents();
183
0
184
0
    WorkerPrivate* parent = aWorkerPrivate->GetParent();
185
0
    if (parent) {
186
0
      innerWindowId = 0;
187
0
    }
188
0
    else {
189
0
      AssertIsOnMainThread();
190
0
191
0
      if (aWorkerPrivate->IsFrozen() ||
192
0
          aWorkerPrivate->IsParentWindowPaused()) {
193
0
        MOZ_ASSERT(!IsDebuggerRunnable());
194
0
        aWorkerPrivate->QueueRunnable(this);
195
0
        return true;
196
0
      }
197
0
198
0
      if (aWorkerPrivate->IsSharedWorker()) {
199
0
        aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, &mReport,
200
0
                                                      /* isErrorEvent */ true);
201
0
        return true;
202
0
      }
203
0
204
0
      // Service workers do not have a main thread parent global, so normal
205
0
      // worker error reporting will crash.  Instead, pass the error to
206
0
      // the ServiceWorkerManager to report on any controlled documents.
207
0
      if (aWorkerPrivate->IsServiceWorker()) {
208
0
        RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
209
0
        if (swm) {
210
0
          swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
211
0
                           aWorkerPrivate->ServiceWorkerScope(),
212
0
                           aWorkerPrivate->ScriptURL(),
213
0
                           mReport.mMessage,
214
0
                           mReport.mFilename, mReport.mLine, mReport.mLineNumber,
215
0
                           mReport.mColumnNumber, mReport.mFlags,
216
0
                           mReport.mExnType);
217
0
        }
218
0
        return true;
219
0
      }
220
0
221
0
      // The innerWindowId is only required if we are going to ReportError
222
0
      // below, which is gated on this condition. The inner window correctness
223
0
      // check is only going to succeed when the worker is accepting events.
224
0
      if (workerIsAcceptingEvents) {
225
0
        aWorkerPrivate->AssertInnerWindowIsCorrect();
226
0
        innerWindowId = aWorkerPrivate->WindowID();
227
0
      }
228
0
    }
229
0
230
0
    // Don't fire this event if the JS object has been disconnected from the
231
0
    // private object.
232
0
    if (!workerIsAcceptingEvents) {
233
0
      return true;
234
0
    }
235
0
236
0
    ReportError(aCx, parent, fireAtScope,
237
0
                aWorkerPrivate->ParentEventTargetRef(),
238
0
                mReport, innerWindowId);
239
0
    return true;
240
0
  }
241
};
242
243
class ReportGenericErrorRunnable final : public WorkerRunnable
244
{
245
public:
246
  static void
247
  CreateAndDispatch(WorkerPrivate* aWorkerPrivate)
248
0
  {
249
0
    MOZ_ASSERT(aWorkerPrivate);
250
0
    aWorkerPrivate->AssertIsOnWorkerThread();
251
0
252
0
    RefPtr<ReportGenericErrorRunnable> runnable =
253
0
      new ReportGenericErrorRunnable(aWorkerPrivate);
254
0
    runnable->Dispatch();
255
0
  }
256
257
private:
258
  explicit ReportGenericErrorRunnable(WorkerPrivate* aWorkerPrivate)
259
    : WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount)
260
0
  {
261
0
    aWorkerPrivate->AssertIsOnWorkerThread();
262
0
  }
263
264
  void
265
  PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
266
0
  {
267
0
    aWorkerPrivate->AssertIsOnWorkerThread();
268
0
269
0
    // Dispatch may fail if the worker was canceled, no need to report that as
270
0
    // an error, so don't call base class PostDispatch.
271
0
  }
272
273
  bool
274
  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
275
0
  {
276
0
    if (aWorkerPrivate->IsFrozen() ||
277
0
        aWorkerPrivate->IsParentWindowPaused()) {
278
0
      MOZ_ASSERT(!IsDebuggerRunnable());
279
0
      aWorkerPrivate->QueueRunnable(this);
280
0
      return true;
281
0
    }
282
0
283
0
    if (aWorkerPrivate->IsSharedWorker()) {
284
0
      aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, nullptr,
285
0
                                                    /* isErrorEvent */ false);
286
0
      return true;
287
0
    }
288
0
289
0
    if (aWorkerPrivate->IsServiceWorker()) {
290
0
      RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
291
0
      if (swm) {
292
0
        swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
293
0
                         aWorkerPrivate->ServiceWorkerScope(),
294
0
                         aWorkerPrivate->ScriptURL(),
295
0
                         EmptyString(), EmptyString(), EmptyString(),
296
0
                         0, 0, JSREPORT_ERROR, JSEXN_ERR);
297
0
      }
298
0
      return true;
299
0
    }
300
0
301
0
    if (!aWorkerPrivate->IsAcceptingEvents()) {
302
0
      return true;
303
0
    }
304
0
305
0
    RefPtr<mozilla::dom::EventTarget> parentEventTarget =
306
0
      aWorkerPrivate->ParentEventTargetRef();
307
0
    RefPtr<Event> event =
308
0
      Event::Constructor(parentEventTarget, NS_LITERAL_STRING("error"),
309
0
                         EventInit());
310
0
    event->SetTrusted(true);
311
0
312
0
    parentEventTarget->DispatchEvent(*event);
313
0
    return true;
314
0
  }
315
};
316
317
} // anonymous
318
319
void
320
WorkerErrorBase::AssignErrorBase(JSErrorBase* aReport)
321
0
{
322
0
  mFilename = NS_ConvertUTF8toUTF16(aReport->filename);
323
0
  mLineNumber = aReport->lineno;
324
0
  mColumnNumber = aReport->column;
325
0
  mErrorNumber = aReport->errorNumber;
326
0
}
327
328
void
329
WorkerErrorNote::AssignErrorNote(JSErrorNotes::Note* aNote)
330
0
{
331
0
  WorkerErrorBase::AssignErrorBase(aNote);
332
0
  xpc::ErrorNote::ErrorNoteToMessageString(aNote, mMessage);
333
0
}
334
335
void
336
WorkerErrorReport::AssignErrorReport(JSErrorReport* aReport)
337
0
{
338
0
  WorkerErrorBase::AssignErrorBase(aReport);
339
0
  xpc::ErrorReport::ErrorReportToMessageString(aReport, mMessage);
340
0
341
0
  mLine.Assign(aReport->linebuf(), aReport->linebufLength());
342
0
  mFlags = aReport->flags;
343
0
  MOZ_ASSERT(aReport->exnType >= JSEXN_FIRST && aReport->exnType < JSEXN_LIMIT);
344
0
  mExnType = JSExnType(aReport->exnType);
345
0
  mMutedError = aReport->isMuted;
346
0
347
0
  if (aReport->notes) {
348
0
    if (!mNotes.SetLength(aReport->notes->length(), fallible)) {
349
0
      return;
350
0
    }
351
0
352
0
    size_t i = 0;
353
0
    for (auto&& note : *aReport->notes) {
354
0
      mNotes.ElementAt(i).AssignErrorNote(note.get());
355
0
      i++;
356
0
    }
357
0
  }
358
0
}
359
360
// aWorkerPrivate is the worker thread we're on (or the main thread, if null)
361
// aTarget is the worker object that we are going to fire an error at
362
// (if any).
363
/* static */ void
364
WorkerErrorReport::ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
365
                               bool aFireAtScope, DOMEventTargetHelper* aTarget,
366
                               const WorkerErrorReport& aReport,
367
                               uint64_t aInnerWindowId,
368
                               JS::Handle<JS::Value> aException)
369
0
{
370
0
  if (aWorkerPrivate) {
371
0
    aWorkerPrivate->AssertIsOnWorkerThread();
372
0
  } else {
373
0
    AssertIsOnMainThread();
374
0
  }
375
0
376
0
  // We should not fire error events for warnings but instead make sure that
377
0
  // they show up in the error console.
378
0
  if (!JSREPORT_IS_WARNING(aReport.mFlags)) {
379
0
    // First fire an ErrorEvent at the worker.
380
0
    RootedDictionary<ErrorEventInit> init(aCx);
381
0
382
0
    if (aReport.mMutedError) {
383
0
      init.mMessage.AssignLiteral("Script error.");
384
0
    } else {
385
0
      init.mMessage = aReport.mMessage;
386
0
      init.mFilename = aReport.mFilename;
387
0
      init.mLineno = aReport.mLineNumber;
388
0
      init.mError = aException;
389
0
    }
390
0
391
0
    init.mCancelable = true;
392
0
    init.mBubbles = false;
393
0
394
0
    if (aTarget) {
395
0
      RefPtr<ErrorEvent> event =
396
0
        ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
397
0
      event->SetTrusted(true);
398
0
399
0
      bool defaultActionEnabled =
400
0
        aTarget->DispatchEvent(*event, CallerType::System, IgnoreErrors());
401
0
      if (!defaultActionEnabled) {
402
0
        return;
403
0
      }
404
0
    }
405
0
406
0
    // Now fire an event at the global object, but don't do that if the error
407
0
    // code is too much recursion and this is the same script threw the error.
408
0
    // XXXbz the interaction of this with worker errors seems kinda broken.
409
0
    // An overrecursion in the debugger or debugger sandbox will get turned
410
0
    // into an error event on our parent worker!
411
0
    // https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks making this
412
0
    // better.
413
0
    if (aFireAtScope &&
414
0
        (aTarget || aReport.mErrorNumber != JSMSG_OVER_RECURSED)) {
415
0
      JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
416
0
      NS_ASSERTION(global, "This should never be null!");
417
0
418
0
      nsEventStatus status = nsEventStatus_eIgnore;
419
0
420
0
      if (aWorkerPrivate) {
421
0
        WorkerGlobalScope* globalScope = nullptr;
422
0
        UNWRAP_OBJECT(WorkerGlobalScope, &global, globalScope);
423
0
424
0
        if (!globalScope) {
425
0
          WorkerDebuggerGlobalScope* globalScope = nullptr;
426
0
          UNWRAP_OBJECT(WorkerDebuggerGlobalScope, &global, globalScope);
427
0
428
0
          MOZ_ASSERT_IF(globalScope, globalScope->GetWrapperPreserveColor() == global);
429
0
          if (globalScope || IsWorkerDebuggerSandbox(global)) {
430
0
            aWorkerPrivate->ReportErrorToDebugger(aReport.mFilename, aReport.mLineNumber,
431
0
                                                  aReport.mMessage);
432
0
            return;
433
0
          }
434
0
435
0
          MOZ_ASSERT(SimpleGlobalObject::SimpleGlobalType(global) ==
436
0
                       SimpleGlobalObject::GlobalType::BindingDetail);
437
0
          // XXXbz We should really log this to console, but unwinding out of
438
0
          // this stuff without ending up firing any events is ... hard.  Just
439
0
          // return for now.
440
0
          // https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks
441
0
          // making this better.
442
0
          return;
443
0
        }
444
0
445
0
        MOZ_ASSERT(globalScope->GetWrapperPreserveColor() == global);
446
0
447
0
        RefPtr<ErrorEvent> event =
448
0
          ErrorEvent::Constructor(aTarget, NS_LITERAL_STRING("error"), init);
449
0
        event->SetTrusted(true);
450
0
451
0
        if (NS_FAILED(EventDispatcher::DispatchDOMEvent(ToSupports(globalScope),
452
0
                                                        nullptr,
453
0
                                                        event, nullptr,
454
0
                                                        &status))) {
455
0
          NS_WARNING("Failed to dispatch worker thread error event!");
456
0
          status = nsEventStatus_eIgnore;
457
0
        }
458
0
      }
459
0
      else if (nsGlobalWindowInner* win = xpc::WindowOrNull(global)) {
460
0
        MOZ_ASSERT(NS_IsMainThread());
461
0
462
0
        if (!win->HandleScriptError(init, &status)) {
463
0
          NS_WARNING("Failed to dispatch main thread error event!");
464
0
          status = nsEventStatus_eIgnore;
465
0
        }
466
0
      }
467
0
468
0
      // Was preventDefault() called?
469
0
      if (status == nsEventStatus_eConsumeNoDefault) {
470
0
        return;
471
0
      }
472
0
    }
473
0
  }
474
0
475
0
  // Now fire a runnable to do the same on the parent's thread if we can.
476
0
  if (aWorkerPrivate) {
477
0
    RefPtr<ReportErrorRunnable> runnable =
478
0
      new ReportErrorRunnable(aWorkerPrivate, aReport);
479
0
    runnable->Dispatch();
480
0
    return;
481
0
  }
482
0
483
0
  // Otherwise log an error to the error console.
484
0
  WorkerErrorReport::LogErrorToConsole(aReport, aInnerWindowId);
485
0
}
486
487
/* static */ void
488
WorkerErrorReport::LogErrorToConsole(const WorkerErrorReport& aReport,
489
                                     uint64_t aInnerWindowId)
490
0
{
491
0
  AssertIsOnMainThread();
492
0
493
0
  RefPtr<nsScriptErrorBase> scriptError = new nsScriptError();
494
0
  NS_WARNING_ASSERTION(scriptError, "Failed to create script error!");
495
0
496
0
  if (scriptError) {
497
0
    nsAutoCString category("Web Worker");
498
0
    if (NS_FAILED(scriptError->InitWithWindowID(aReport.mMessage,
499
0
                                                aReport.mFilename,
500
0
                                                aReport.mLine,
501
0
                                                aReport.mLineNumber,
502
0
                                                aReport.mColumnNumber,
503
0
                                                aReport.mFlags,
504
0
                                                category,
505
0
                                                aInnerWindowId))) {
506
0
      NS_WARNING("Failed to init script error!");
507
0
      scriptError = nullptr;
508
0
    }
509
0
510
0
    for (size_t i = 0, len = aReport.mNotes.Length(); i < len; i++) {
511
0
      const WorkerErrorNote& note = aReport.mNotes.ElementAt(i);
512
0
513
0
      nsScriptErrorNote* noteObject = new nsScriptErrorNote();
514
0
      noteObject->Init(note.mMessage, note.mFilename,
515
0
                       note.mLineNumber, note.mColumnNumber);
516
0
      scriptError->AddNote(noteObject);
517
0
    }
518
0
  }
519
0
520
0
  nsCOMPtr<nsIConsoleService> consoleService =
521
0
    do_GetService(NS_CONSOLESERVICE_CONTRACTID);
522
0
  NS_WARNING_ASSERTION(consoleService, "Failed to get console service!");
523
0
524
0
  if (consoleService) {
525
0
    if (scriptError) {
526
0
      if (NS_SUCCEEDED(consoleService->LogMessage(scriptError))) {
527
0
        return;
528
0
      }
529
0
      NS_WARNING("LogMessage failed!");
530
0
    } else if (NS_SUCCEEDED(consoleService->LogStringMessage(
531
0
                              aReport.mMessage.BeginReading()))) {
532
0
      return;
533
0
    }
534
0
    NS_WARNING("LogStringMessage failed!");
535
0
  }
536
0
537
0
  NS_ConvertUTF16toUTF8 msg(aReport.mMessage);
538
0
  NS_ConvertUTF16toUTF8 filename(aReport.mFilename);
539
0
540
0
  static const char kErrorString[] = "JS error in Web Worker: %s [%s:%u]";
541
0
542
#ifdef ANDROID
543
  __android_log_print(ANDROID_LOG_INFO, "Gecko", kErrorString, msg.get(),
544
                      filename.get(), aReport.mLineNumber);
545
#endif
546
547
0
  fprintf(stderr, kErrorString, msg.get(), filename.get(), aReport.mLineNumber);
548
0
  fflush(stderr);
549
0
}
550
551
/* static */ void
552
WorkerErrorReport::CreateAndDispatchGenericErrorRunnableToParent(WorkerPrivate* aWorkerPrivate)
553
0
{
554
0
  ReportGenericErrorRunnable::CreateAndDispatch(aWorkerPrivate);
555
0
}
556
557
} // dom namespace
558
} // mozilla namespace