Bug 25151 - workers that fail to load scripts not firing error event
Summary: workers that fail to load scripts not firing error event
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: DOM (show other bugs)
Version: 528+ (Nightly build)
Hardware: Macintosh OS X 10.5
: P2 Normal
Assignee: Jian Li
URL:
Keywords:
Depends on:
Blocks: 27282
  Show dependency treegraph
 
Reported: 2009-04-12 16:35 PDT by jason a
Modified: 2009-07-15 16:18 PDT (History)
4 users (show)

See Also:


Attachments
Proposed Patch (24.75 KB, patch)
2009-07-08 17:42 PDT, Jian Li
levin: review-
Details | Formatted Diff | Diff
Proposed Patch (25.21 KB, application/octet-stream)
2009-07-14 17:06 PDT, Jian Li
no flags Details
Proposed Patch (25.21 KB, patch)
2009-07-14 17:07 PDT, Jian Li
no flags Details | Formatted Diff | Diff
Proposed Patch (22.97 KB, patch)
2009-07-15 14:33 PDT, Jian Li
levin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description jason a 2009-04-12 16:35:10 PDT
worker js files with syntax errors do not throw exception when worker is created or message is posted to worker.

Expected: exception during construction and/or onerror when message is posted.
Comment 1 Alexey Proskuryakov 2009-04-14 02:28:01 PDT
Exception during construction is definitely not possible - the constructor just starts a network load, and returns before the script is available.

What does the spec say about this situation?
Comment 2 Dmitry Titov 2009-06-24 14:15:24 PDT
Here is what the spec says:

---
Attempt to fetch the resource identified by url.
If the attempt fails, or if the attempt involves any redirects to URIs that do not have the same origin as url (even if the final URI is at the same origin as the original url), then for each Worker or SharedWorker object associated with worker global scope, queue a task to fire a simple event called error at that object. 
---

There is also a description on how exactly to fire this event.
Comment 3 Jian Li 2009-07-08 17:42:09 PDT
Created attachment 32493 [details]
Proposed Patch
Comment 4 David Levin 2009-07-14 15:45:09 PDT
Comment on attachment 32493 [details]
Proposed Patch

Just a few things to address/clarify.  Thanks.

> diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
> +2009-07-08  Jian Li  <jianli@chromium.org>
> +
> +        Reviewed by NOBODY (OOPS!).
> +
> +        Bug 25151 - workers with syntax errors not firing error event.
> +        https://bugs.webkit.org/show_bug.cgi?id=25151
> +
> +        This fixes the problem that an error event is not fired when failed

Consider this wording:

  This fixes the problem that an error event is not fired when the worker script
  fails to load.  Some reasons this may occur are an invalid URL for the worker 
  script, a cross-origin redirect, or a syntax error in the script.


Another problem is this changelog doesn't say much about why things were done.  When I
first looked at the patch I thought another issue was being fixed but some items were moved
around.  Function level comments in the changelog would be helpful here.

> diff --git a/WebCore/bindings/js/JSWorkerConstructor.cpp b/WebCore/bindings/js/JSWorkerConstructor.cpp
> -    ExceptionCode ec = 0;
> -    RefPtr<Worker> worker = Worker::create(scriptURL, window->document(), ec);
> -    setDOMException(exec, ec);
> +    RefPtr<Worker> worker = Worker::create(scriptURL, window->document());

Why is it ok to stop setting the dom exception?


> diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp
> -    ExceptionCode ec = 0;
> -    RefPtr<Worker> obj = Worker::create(toWebCoreString(scriptUrl), context, ec);
> -
> -    if (ec)
> -        return throwError(ec);
> +    RefPtr<Worker> obj = Worker::create(toWebCoreString(scriptUrl), context);

Same question as above (but here it is throwError).

> diff --git a/WebCore/workers/WorkerMessagingProxy.cpp b/WebCore/workers/WorkerMessagingProxy.cpp

>      virtual void performTask(ScriptExecutionContext* context)
>      {
> -        if (!m_messagingProxy->askedToTerminate())
> -            context->reportException(m_errorMessage, m_lineNumber, m_sourceURL);
> +        Worker* workerObject = m_messagingProxy->workerObject();
> +        if (!workerObject || m_messagingProxy->askedToTerminate())
> +            return;
> +
> +        context->reportException(m_errorMessage, m_lineNumber, m_sourceURL);
> +        workerObject->dispatchErrorEvent();

This changes the behavior for more than just the case that you're fixing.  Any code that calls ScriptExecutionContext->reportException will get this behavior.  Why is that the correct thing to do?

Also, is there a chromium change corresponding to this?

> diff --git a/WebCore/workers/WorkerMessagingProxy.h b/WebCore/workers/WorkerMessagingProxy.h
> namespace WebCore {
...
> +        friend class WorkerExceptionTask;

Why is this being added here?

> diff --git a/WebCore/workers/WorkerScriptLoader.cpp b/WebCore/workers/WorkerScriptLoader.cpp
> +void WorkerScriptLoader::loadSynchronously(ScriptExecutionContext* scriptExecutionContext, const String& url, URLCompletionPolicy urlCompletionPolicy, CrossOriginLoadPolicy crossOriginLoadPolicy)
...
> +    CrossOriginRedirectPolicy crossOriginRedirectPolicy = (crossOriginLoadPolicy == DenyCrossOriginLoad) ? DenyCrossOriginRedirect : AllowCrossOriginRedirect;
    
> +void WorkerScriptLoader::loadAsynchronously(ScriptExecutionContext* scriptExecutionContext, const String& url, URLCompletionPolicy urlCompletionPolicy, CrossOriginLoadPolicy crossOriginLoadPolicy, WorkerScriptLoaderClient* client)
...
> +    CrossOriginRedirectPolicy crossOriginRedirectPolicy = (crossOriginLoadPolicy == DenyCrossOriginLoad) ? DenyCrossOriginRedirect : AllowCrossOriginRedirect;

It would be nice to only have one place that does the conversion of CrossOriginLoadPolicy to CrossOriginRedirectPolicy.  Right now there are two in this file.

> +ResourceRequest* WorkerScriptLoader::createResourceRequest(ScriptExecutionContext* scriptExecutionContext, const String& url, URLCompletionPolicy urlCompletionPolicy, CrossOriginLoadPolicy crossOriginLoadPolicy)

This should return a PassOwnPtr<ResourceRequest>
Comment 5 Jian Li 2009-07-14 17:05:07 PDT
(In reply to comment #4)
> (From update of attachment 32493 [details])
> Just a few things to address/clarify.  Thanks.
> 
> > diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
> > +2009-07-08  Jian Li  <jianli@chromium.org>
> > +
> > +        Reviewed by NOBODY (OOPS!).
> > +
> > +        Bug 25151 - workers with syntax errors not firing error event.
> > +        https://bugs.webkit.org/show_bug.cgi?id=25151
> > +
> > +        This fixes the problem that an error event is not fired when failed
> 
> Consider this wording:
> 
>   This fixes the problem that an error event is not fired when the worker
> script
>   fails to load.  Some reasons this may occur are an invalid URL for the worker 
>   script, a cross-origin redirect, or a syntax error in the script.
> 
> 
> Another problem is this changelog doesn't say much about why things were done. 
> When I
> first looked at the patch I thought another issue was being fixed but some
> items were moved
> around.  Function level comments in the changelog would be helpful here.
> 
Updated.

> > diff --git a/WebCore/bindings/js/JSWorkerConstructor.cpp b/WebCore/bindings/js/JSWorkerConstructor.cpp
> > -    ExceptionCode ec = 0;
> > -    RefPtr<Worker> worker = Worker::create(scriptURL, window->document(), ec);
> > -    setDOMException(exec, ec);
> > +    RefPtr<Worker> worker = Worker::create(scriptURL, window->document());
> 
> Why is it ok to stop setting the dom exception?
> 
This is because the worker constructor will never return an exception code to indicate a DOM exception.
> 
> > diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp
> > -    ExceptionCode ec = 0;
> > -    RefPtr<Worker> obj = Worker::create(toWebCoreString(scriptUrl), context, ec);
> > -
> > -    if (ec)
> > -        return throwError(ec);
> > +    RefPtr<Worker> obj = Worker::create(toWebCoreString(scriptUrl), context);
> 
> Same question as above (but here it is throwError).

This is because the worker constructor will never return an exception code to indicate a DOM exception.
> 
> > diff --git a/WebCore/workers/WorkerMessagingProxy.cpp b/WebCore/workers/WorkerMessagingProxy.cpp
> 
> >      virtual void performTask(ScriptExecutionContext* context)
> >      {
> > -        if (!m_messagingProxy->askedToTerminate())
> > -            context->reportException(m_errorMessage, m_lineNumber, m_sourceURL);
> > +        Worker* workerObject = m_messagingProxy->workerObject();
> > +        if (!workerObject || m_messagingProxy->askedToTerminate())
> > +            return;
> > +
> > +        context->reportException(m_errorMessage, m_lineNumber, m_sourceURL);
> > +        workerObject->dispatchErrorEvent();
> 
> This changes the behavior for more than just the case that you're fixing.  Any
> code that calls ScriptExecutionContext->reportException will get this behavior.
>  Why is that the correct thing to do?
> 
This indeed fixes a bug here. Previously we only called "context->reportException(...)" that only reported an exception to the ScriptExecutionContext that put the error message in the console. We need to also call onerror event handler of the worker object.

> Also, is there a chromium change corresponding to this?
> 
Yes, I will have another patch for corresponding chromium change for review after I land this.

> > diff --git a/WebCore/workers/WorkerMessagingProxy.h b/WebCore/workers/WorkerMessagingProxy.h
> > namespace WebCore {
> ...
> > +        friend class WorkerExceptionTask;
> 
> Why is this being added here?

This is because WorkerExceptionTask::performTask needs to access private function WorkerMessagingProxy::workerObject.
> 
> > diff --git a/WebCore/workers/WorkerScriptLoader.cpp b/WebCore/workers/WorkerScriptLoader.cpp
> > +void WorkerScriptLoader::loadSynchronously(ScriptExecutionContext* scriptExecutionContext, const String& url, URLCompletionPolicy urlCompletionPolicy, CrossOriginLoadPolicy crossOriginLoadPolicy)
> ...
> > +    CrossOriginRedirectPolicy crossOriginRedirectPolicy = (crossOriginLoadPolicy == DenyCrossOriginLoad) ? DenyCrossOriginRedirect : AllowCrossOriginRedirect;
> 
> > +void WorkerScriptLoader::loadAsynchronously(ScriptExecutionContext* scriptExecutionContext, const String& url, URLCompletionPolicy urlCompletionPolicy, CrossOriginLoadPolicy crossOriginLoadPolicy, WorkerScriptLoaderClient* client)
> ...
> > +    CrossOriginRedirectPolicy crossOriginRedirectPolicy = (crossOriginLoadPolicy == DenyCrossOriginLoad) ? DenyCrossOriginRedirect : AllowCrossOriginRedirect;
> 
> It would be nice to only have one place that does the conversion of
> CrossOriginLoadPolicy to CrossOriginRedirectPolicy.  Right now there are two in
> this file.

Fixed.
> 
> > +ResourceRequest* WorkerScriptLoader::createResourceRequest(ScriptExecutionContext* scriptExecutionContext, const String& url, URLCompletionPolicy urlCompletionPolicy, CrossOriginLoadPolicy crossOriginLoadPolicy)
> 
> This should return a PassOwnPtr<ResourceRequest>

Fixed.
Comment 6 Jian Li 2009-07-14 17:06:20 PDT
Created attachment 32747 [details]
Proposed Patch
Comment 7 Jian Li 2009-07-14 17:07:10 PDT
Created attachment 32749 [details]
Proposed Patch
Comment 8 Jian Li 2009-07-15 14:33:42 PDT
Created attachment 32814 [details]
Proposed Patch

Uploaded a new pacth per discussion with levin. Removed the handling of syntax error in the script from this patch.
Comment 9 David Levin 2009-07-15 14:55:30 PDT
Comment on attachment 32814 [details]
Proposed Patch

Looks good.

Please file a bug about the error not being fired on WorkerContext when there is a syntax error in the script.
Comment 10 Jian Li 2009-07-15 16:18:19 PDT
Committed as http://trac.webkit.org/changeset/45958