OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights |
6 * reserved. | 6 * reserved. |
7 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> | 7 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 | 104 |
105 ScriptLoader::~ScriptLoader() {} | 105 ScriptLoader::~ScriptLoader() {} |
106 | 106 |
107 DEFINE_TRACE(ScriptLoader) { | 107 DEFINE_TRACE(ScriptLoader) { |
108 visitor->trace(m_element); | 108 visitor->trace(m_element); |
109 visitor->trace(m_resource); | 109 visitor->trace(m_resource); |
110 visitor->trace(m_pendingScript); | 110 visitor->trace(m_pendingScript); |
111 PendingScriptClient::trace(visitor); | 111 PendingScriptClient::trace(visitor); |
112 } | 112 } |
113 | 113 |
| 114 // static |
| 115 AccessControlStatus ScriptLoader::accessControlStatusForScript( |
| 116 bool isExternalScript, |
| 117 const ScriptResource* resource, |
| 118 const SecurityOrigin* scriptElementOrigin) { |
| 119 if (!isExternalScript) |
| 120 return SharableCrossOrigin; |
| 121 |
| 122 // TODO(jbroman): DCHECK(resource)? |
| 123 if (!resource) |
| 124 return NotSharableCrossOrigin; |
| 125 |
| 126 const auto& response = resource->response(); |
| 127 if (response.wasFetchedViaServiceWorker()) { |
| 128 return response.serviceWorkerResponseType() == |
| 129 WebServiceWorkerResponseTypeOpaque |
| 130 ? OpaqueResource |
| 131 : SharableCrossOrigin; |
| 132 } |
| 133 |
| 134 return resource->passesAccessControlCheck(scriptElementOrigin) |
| 135 ? SharableCrossOrigin |
| 136 : NotSharableCrossOrigin; |
| 137 } |
| 138 |
114 void ScriptLoader::setFetchDocWrittenScriptDeferIdle() { | 139 void ScriptLoader::setFetchDocWrittenScriptDeferIdle() { |
115 DCHECK(!m_createdDuringDocumentWrite); | 140 DCHECK(!m_createdDuringDocumentWrite); |
116 m_documentWriteIntervention = | 141 m_documentWriteIntervention = |
117 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle; | 142 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle; |
118 } | 143 } |
119 | 144 |
120 void ScriptLoader::didNotifySubtreeInsertionsToDocument() { | 145 void ScriptLoader::didNotifySubtreeInsertionsToDocument() { |
121 if (!m_parserInserted) | 146 if (!m_parserInserted) |
122 prepareScript(); // FIXME: Provide a real starting line number here. | 147 prepareScript(); // FIXME: Provide a real starting line number here. |
123 } | 148 } |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 ? (isText ? UseCounter::SameOriginTextScript | 678 ? (isText ? UseCounter::SameOriginTextScript |
654 : isApplication ? UseCounter::SameOriginApplicationScript | 679 : isApplication ? UseCounter::SameOriginApplicationScript |
655 : UseCounter::SameOriginOtherScript) | 680 : UseCounter::SameOriginOtherScript) |
656 : (isText ? UseCounter::CrossOriginTextScript | 681 : (isText ? UseCounter::CrossOriginTextScript |
657 : isApplication ? UseCounter::CrossOriginApplicationScript | 682 : isApplication ? UseCounter::CrossOriginApplicationScript |
658 : UseCounter::CrossOriginOtherScript); | 683 : UseCounter::CrossOriginOtherScript); |
659 | 684 |
660 UseCounter::count(frame, feature); | 685 UseCounter::count(frame, feature); |
661 } | 686 } |
662 | 687 |
663 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) { | 688 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode, |
| 689 CompiledScript* compiledScript) { |
664 double scriptExecStartTime = monotonicallyIncreasingTime(); | 690 double scriptExecStartTime = monotonicallyIncreasingTime(); |
665 bool result = doExecuteScript(sourceCode); | 691 bool result = doExecuteScript(sourceCode, compiledScript); |
666 | 692 |
667 // NOTE: we do not check m_willBeParserExecuted here, since | 693 // NOTE: we do not check m_willBeParserExecuted here, since |
668 // m_willBeParserExecuted is false for inline scripts, and we want to | 694 // m_willBeParserExecuted is false for inline scripts, and we want to |
669 // include inline script execution time as part of parser blocked script | 695 // include inline script execution time as part of parser blocked script |
670 // execution time. | 696 // execution time. |
671 if (m_asyncExecType == ScriptRunner::None) | 697 if (m_asyncExecType == ScriptRunner::None) |
672 DocumentParserTiming::from(m_element->document()) | 698 DocumentParserTiming::from(m_element->document()) |
673 .recordParserBlockedOnScriptExecutionDuration( | 699 .recordParserBlockedOnScriptExecutionDuration( |
674 monotonicallyIncreasingTime() - scriptExecStartTime, | 700 monotonicallyIncreasingTime() - scriptExecStartTime, |
675 wasCreatedDuringDocumentWrite()); | 701 wasCreatedDuringDocumentWrite()); |
676 return result; | 702 return result; |
677 } | 703 } |
678 | 704 |
679 // https://html.spec.whatwg.org/#execute-the-script-block | 705 // https://html.spec.whatwg.org/#execute-the-script-block |
680 // with additional support for HTML imports. | 706 // with additional support for HTML imports. |
681 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(), | 707 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(), |
682 // i.e. load/error events are dispatched by the caller. | 708 // i.e. load/error events are dispatched by the caller. |
683 // Steps 3--7 are implemented here in doExecuteScript(). | 709 // Steps 3--7 are implemented here in doExecuteScript(). |
684 // TODO(hiroshige): Move event dispatching code to doExecuteScript(). | 710 // TODO(hiroshige): Move event dispatching code to doExecuteScript(). |
685 bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) { | 711 bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode, |
| 712 CompiledScript* compiledScript) { |
686 DCHECK(m_alreadyStarted); | 713 DCHECK(m_alreadyStarted); |
687 | 714 |
688 if (sourceCode.isEmpty()) | 715 if (sourceCode.isEmpty()) |
689 return true; | 716 return true; |
690 | 717 |
691 Document* elementDocument = &(m_element->document()); | 718 Document* elementDocument = &(m_element->document()); |
692 Document* contextDocument = elementDocument->contextDocument(); | 719 Document* contextDocument = elementDocument->contextDocument(); |
693 if (!contextDocument) | 720 if (!contextDocument) |
694 return true; | 721 return true; |
695 | 722 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 UseCounter::count(frame, UseCounter::BlockedSniffingVideoToScript); | 772 UseCounter::count(frame, UseCounter::BlockedSniffingVideoToScript); |
746 else if (mimeType == "text/csv") | 773 else if (mimeType == "text/csv") |
747 UseCounter::count(frame, UseCounter::BlockedSniffingCSVToScript); | 774 UseCounter::count(frame, UseCounter::BlockedSniffingCSVToScript); |
748 return false; | 775 return false; |
749 } | 776 } |
750 | 777 |
751 logScriptMIMEType(frame, resource, mimeType); | 778 logScriptMIMEType(frame, resource, mimeType); |
752 } | 779 } |
753 } | 780 } |
754 | 781 |
755 AccessControlStatus accessControlStatus = NotSharableCrossOrigin; | 782 AccessControlStatus accessControlStatus = |
756 if (!m_isExternalScript) { | 783 accessControlStatusForScript(m_isExternalScript, sourceCode.resource(), |
757 accessControlStatus = SharableCrossOrigin; | 784 elementDocument->getSecurityOrigin()); |
758 } else if (sourceCode.resource()) { | |
759 if (sourceCode.resource()->response().wasFetchedViaServiceWorker()) { | |
760 if (sourceCode.resource()->response().serviceWorkerResponseType() == | |
761 WebServiceWorkerResponseTypeOpaque) | |
762 accessControlStatus = OpaqueResource; | |
763 else | |
764 accessControlStatus = SharableCrossOrigin; | |
765 } else if (sourceCode.resource()->passesAccessControlCheck( | |
766 m_element->document().getSecurityOrigin())) { | |
767 accessControlStatus = SharableCrossOrigin; | |
768 } | |
769 } | |
770 | 785 |
771 const bool isImportedScript = contextDocument != elementDocument; | 786 const bool isImportedScript = contextDocument != elementDocument; |
772 | 787 |
773 // 3. "If the script is from an external file, | 788 // 3. "If the script is from an external file, |
774 // or the script's type is module", | 789 // or the script's type is module", |
775 // then increment the ignore-destructive-writes counter of the | 790 // then increment the ignore-destructive-writes counter of the |
776 // script element's node document. Let neutralized doc be that Document." | 791 // script element's node document. Let neutralized doc be that Document." |
777 // TODO(hiroshige): Implement "module" case. | 792 // TODO(hiroshige): Implement "module" case. |
778 IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer( | 793 IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer( |
779 m_isExternalScript || isImportedScript ? contextDocument : 0); | 794 m_isExternalScript || isImportedScript ? contextDocument : 0); |
780 | 795 |
781 // 4. "Let old script element be the value to which the script element's | 796 // 4. "Let old script element be the value to which the script element's |
782 // node document's currentScript object was most recently set." | 797 // node document's currentScript object was most recently set." |
783 // This is implemented as push/popCurrentScript(). | 798 // This is implemented as push/popCurrentScript(). |
784 | 799 |
785 // 5. "Switch on the script's type:" | 800 // 5. "Switch on the script's type:" |
786 // - "classic": | 801 // - "classic": |
787 // 1. "If the script element's root is not a shadow root, | 802 // 1. "If the script element's root is not a shadow root, |
788 // then set the script element's node document's currentScript | 803 // then set the script element's node document's currentScript |
789 // attribute to the script element. Otherwise, set it to null." | 804 // attribute to the script element. Otherwise, set it to null." |
790 if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) | 805 if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) |
791 contextDocument->pushCurrentScript(m_element); | 806 contextDocument->pushCurrentScript(m_element); |
792 | 807 |
793 // 2. "Run the classic script given by the script's script." | 808 // 2. "Run the classic script given by the script's script." |
794 // Note: This is where the script is compiled and actually executed. | 809 // Note: This is where the script is compiled and actually executed. |
795 frame->script().executeScriptInMainWorld(sourceCode, accessControlStatus); | 810 if (compiledScript) { |
| 811 frame->script().executeScriptInMainWorld(*compiledScript); |
| 812 } else { |
| 813 frame->script().executeScriptInMainWorld(sourceCode, accessControlStatus); |
| 814 } |
796 | 815 |
797 // - "module": | 816 // - "module": |
798 // TODO(hiroshige): Implement this. | 817 // TODO(hiroshige): Implement this. |
799 | 818 |
800 // 6. "Set the script element's node document's currentScript attribute | 819 // 6. "Set the script element's node document's currentScript attribute |
801 // to old script element." | 820 // to old script element." |
802 if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) { | 821 if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) { |
803 DCHECK(contextDocument->currentScript() == m_element); | 822 DCHECK(contextDocument->currentScript() == m_element); |
804 contextDocument->popCurrentScript(); | 823 contextDocument->popCurrentScript(); |
805 } | 824 } |
806 | 825 |
807 return true; | 826 return true; |
808 | 827 |
809 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, | 828 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, |
810 // if it was incremented in the earlier step." | 829 // if it was incremented in the earlier step." |
811 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. | 830 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. |
812 } | 831 } |
813 | 832 |
814 void ScriptLoader::execute() { | 833 void ScriptLoader::execute() { |
815 DCHECK(!m_willBeParserExecuted); | 834 DCHECK(!m_willBeParserExecuted); |
816 DCHECK(m_asyncExecType != ScriptRunner::None); | 835 DCHECK(m_asyncExecType != ScriptRunner::None); |
817 DCHECK(m_pendingScript->resource()); | 836 DCHECK(m_pendingScript->resource()); |
818 bool errorOccurred = false; | 837 bool errorOccurred = false; |
819 ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred); | 838 ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred); |
| 839 CompiledScript* compiledScript = m_pendingScript->getCompiledScript(); |
820 detachPendingScript(); | 840 detachPendingScript(); |
821 if (errorOccurred) { | 841 if (errorOccurred) { |
822 dispatchErrorEvent(); | 842 dispatchErrorEvent(); |
823 } else if (!m_resource->wasCanceled()) { | 843 } else if (!m_resource->wasCanceled()) { |
824 if (executeScript(source)) | 844 if (executeScript(source, compiledScript)) |
825 dispatchLoadEvent(); | 845 dispatchLoadEvent(); |
826 else | 846 else |
827 dispatchErrorEvent(); | 847 dispatchErrorEvent(); |
828 } | 848 } |
829 m_resource = nullptr; | 849 m_resource = nullptr; |
830 } | 850 } |
831 | 851 |
832 void ScriptLoader::pendingScriptFinished(PendingScript* pendingScript) { | 852 void ScriptLoader::pendingScriptFinished(PendingScript* pendingScript) { |
| 853 LOG(ERROR) << "Finished loading pending script of size " |
| 854 << pendingScript->resource()->size(); |
833 DCHECK(!m_willBeParserExecuted); | 855 DCHECK(!m_willBeParserExecuted); |
834 DCHECK_EQ(m_pendingScript, pendingScript); | 856 DCHECK_EQ(m_pendingScript, pendingScript); |
835 DCHECK_EQ(pendingScript->resource(), m_resource); | 857 DCHECK_EQ(pendingScript->resource(), m_resource); |
836 | 858 |
837 // We do not need this script in the memory cache. The primary goals of | 859 // We do not need this script in the memory cache. The primary goals of |
838 // sending this fetch request are to let the third party server know | 860 // sending this fetch request are to let the third party server know |
839 // about the document.write scripts intervention and populate the http | 861 // about the document.write scripts intervention and populate the http |
840 // cache for subsequent uses. | 862 // cache for subsequent uses. |
841 if (m_documentWriteIntervention == | 863 if (m_documentWriteIntervention == |
842 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { | 864 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
916 if (isHTMLScriptLoader(element)) | 938 if (isHTMLScriptLoader(element)) |
917 return toHTMLScriptElement(element)->loader(); | 939 return toHTMLScriptElement(element)->loader(); |
918 | 940 |
919 if (isSVGScriptLoader(element)) | 941 if (isSVGScriptLoader(element)) |
920 return toSVGScriptElement(element)->loader(); | 942 return toSVGScriptElement(element)->loader(); |
921 | 943 |
922 return 0; | 944 return 0; |
923 } | 945 } |
924 | 946 |
925 } // namespace blink | 947 } // namespace blink |
OLD | NEW |