Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: polyfill.js

Issue 29582716: Issue 4579 - Ignore runtime.lastError caused by wrapper (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Left Patch Set: Created Oct. 19, 2017, 1:56 a.m.
Right Patch Set: Use regex Created Oct. 20, 2017, 1:43 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH 3 * Copyright (C) 2006-present eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 25 matching lines...) Expand all
36 "tabs.query", 36 "tabs.query",
37 "tabs.reload", 37 "tabs.reload",
38 "tabs.sendMessage", 38 "tabs.sendMessage",
39 "tabs.update", 39 "tabs.update",
40 "webNavigation.getAllFrames", 40 "webNavigation.getAllFrames",
41 "webRequest.handlerBehaviorChanged", 41 "webRequest.handlerBehaviorChanged",
42 "windows.create", 42 "windows.create",
43 "windows.update" 43 "windows.update"
44 ]; 44 ];
45 45
46 // Errors that occur only when we show an interest in the response from an 46 // Since we add a callback for all messaging API calls in our wrappers,
47 // API call. 47 // Chrome assumes we're interested in the response; when there's no response,
48 const noFulfillmentErrors = [ 48 // it sets runtime.lastError
49 "The message port closed before a response was received." 49 const portClosedBeforeResponseError =
50 ]; 50 // Older versions of Chrome have a typo:
51 51 // https://crrev.com/c33f51726eacdcc1a487b21a13611f7eab580d6d
52 const fulfillmentInterestFlag = Symbol(); 52 /^The message port closed before a res?ponse was received\.$/;
Manish Jethani 2017/10/19 01:59:46 We use a symbol here so it becomes like a private
53
54 function SpecialPromise(...args)
55 {
56 return Reflect.construct(Promise, args, SpecialPromise);
Manish Jethani 2017/10/19 01:59:46 Essentially an extended promise.
57 }
58
59 SpecialPromise.prototype = Object.create(
60 Object.assign({}, Promise.prototype, {
61 then(...args)
62 {
63 // Set this flag to indicate that there is interest in the fulfillment
64 // of this promise.
65 this[fulfillmentInterestFlag] = true;
66
67 return Promise.prototype.then.apply(this, args);
68 }
69 })
70 );
71 53
72 function wrapAPI(api) 54 function wrapAPI(api)
73 { 55 {
74 let object = browser; 56 let object = browser;
75 let path = api.split("."); 57 let path = api.split(".");
76 let name = path.pop(); 58 let name = path.pop();
77 59
78 for (let node of path) 60 for (let node of path)
79 { 61 {
80 object = object[node]; 62 object = object[node];
81 63
82 if (!object) 64 if (!object)
83 return; 65 return;
84 } 66 }
85 67
86 let func = object[name]; 68 let func = object[name];
87 object[name] = function(...args) 69 object[name] = function(...args)
88 { 70 {
71 let callStack = new Error().stack;
72
89 if (typeof args[args.length - 1] == "function") 73 if (typeof args[args.length - 1] == "function")
90 return func.apply(object, args); 74 return func.apply(object, args);
91 75
92 // If the last argument is undefined, we drop it from the list assuming 76 // If the last argument is undefined, we drop it from the list assuming
93 // it stands for the optional callback. We must do this, because we have 77 // it stands for the optional callback. We must do this, because we have
94 // to replace it with our own callback. If we simply append our own 78 // to replace it with our own callback. If we simply append our own
95 // callback to the list, it won't match the signature of the function and 79 // callback to the list, it won't match the signature of the function and
96 // will cause an exception. 80 // will cause an exception.
97 if (typeof args[args.length - 1] == "undefined") 81 if (typeof args[args.length - 1] == "undefined")
98 args.pop(); 82 args.pop();
99 83
100 let promise = new SpecialPromise((resolve, reject) => 84 return new Promise((resolve, reject) =>
101 { 85 {
102 func.call(object, ...args, result => 86 func.call(object, ...args, result =>
103 { 87 {
104 let error = browser.runtime.lastError; 88 let error = browser.runtime.lastError;
105 if (error) 89 if (error && !portClosedBeforeResponseError.test(error.message))
106 { 90 {
107 // If is this an error we got only because we passed in a callback 91 // runtime.lastError is already an Error instance on Edge, while on
108 // and there's no actual interest in the response, ignore the 92 // Chrome it is a plain object with only a message property.
109 // error. 93 if (!(error instanceof Error))
110 if (noFulfillmentErrors.includes(error.message) &&
111 !promise[fulfillmentInterestFlag])
112 { 94 {
113 return; 95 error = new Error(error.message);
96
97 // Add a more helpful stack trace.
98 error.stack = callStack;
114 } 99 }
115 100
116 reject(error); 101 reject(error);
117 } 102 }
118 else 103 else
119 { 104 {
120 resolve(result); 105 resolve(result);
121 } 106 }
122 }); 107 });
123 }); 108 });
124
125 return promise;
126 }; 109 };
127 } 110 }
128 111
129 function shouldWrapAPIs() 112 function shouldWrapAPIs()
130 { 113 {
131 try 114 try
132 { 115 {
133 return !(browser.storage.local.get([]) instanceof Promise); 116 return !(browser.storage.local.get([]) instanceof Promise);
134 } 117 }
135 catch (error) 118 catch (error)
(...skipping 17 matching lines...) Expand all
153 136
154 // Workaround since HTMLCollection, NodeList, StyleSheetList, and CSSRuleList 137 // Workaround since HTMLCollection, NodeList, StyleSheetList, and CSSRuleList
155 // didn't have iterator support before Chrome 51. 138 // didn't have iterator support before Chrome 51.
156 // https://bugs.chromium.org/p/chromium/issues/detail?id=401699 139 // https://bugs.chromium.org/p/chromium/issues/detail?id=401699
157 for (let object of [HTMLCollection, NodeList, StyleSheetList, CSSRuleList]) 140 for (let object of [HTMLCollection, NodeList, StyleSheetList, CSSRuleList])
158 { 141 {
159 if (!(Symbol.iterator in object.prototype)) 142 if (!(Symbol.iterator in object.prototype))
160 object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; 143 object.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
161 } 144 }
162 } 145 }
LEFTRIGHT
« no previous file | no next file » | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
This is Rietveld