1 2browserInterop = new (function () { 3 var jsObjectRefs = {}; 4 var jsObjectRefId = 0; 5 var me = this; 6 7 const jsRefKey = '__jsObjectRefId'; // Keep in sync with ElementRef.cs 8 9 //reviver will help me store js object ref on .net like the .net do with elementreference or dotnetobjectreference 10 this.jsObjectRefRevive = function (key, value) { 11 if (value && 12 typeof value === 'object' && 13 value.hasOwnProperty(jsRefKey) && 14 typeof value[jsRefKey] === 'number') { 15 16 var id = value[jsRefKey]; 17 if (!(id in jsObjectRefs)) { 18 throw new Error("This JS object reference does not exists : " + id); 19 } 20 return jsObjectRefs[id]; 21 } else { 22 return value; 23 } 24 }; 25 //this simple method will be used for getting the content of a given js object ref because js interop will call the reviver with the given C# js object ref 26 this.returnInstance = function (instance, serializationSpec) { 27 return me.getSerializableObject(instance, [], serializationSpec); 28 } 29 DotNet.attachReviver(this.jsObjectRefRevive); 30 //this reviver change a given parameter to a method, it's usefull for sending .net callback to js 31 DotNet.attachReviver(function (key, value) { 32 if (value && 33 typeof value === 'object' && 34 value.hasOwnProperty("__isCallBackWrapper")) { 35 36 37 var netObjectRef = value.callbackRef; 38 39 return function () { 40 var args = []; 41 if (!value.getJsObjectRef) { 42 for (let index = 0; index < arguments.length; index++) { 43 const element = arguments[index]; 44 args.push(me.getSerializableObject(element, [], value.serializationSpec)); 45 } 46 } else { 47 for (let index = 0; index < arguments.length; index++) { 48 const element = arguments[index]; 49 args.push(me.storeObjectRef(element)); 50 } 51 } 52 return netObjectRef.invokeMethodAsync('Invoke', ...args); 53 }; 54 } else { 55 return value; 56 } 57 }); 58 var eventListenersIdCurrent = 0; 59 var eventListeners = {}; 60 this.addEventListener = function (instance, propertyPath, eventName, callback) { 61 var target = me.getInstanceProperty(instance, propertyPath); 62 target.addEventListener(eventName, callback); 63 var eventId = eventListenersIdCurrent++; 64 eventListeners[eventId] = callback; 65 return eventId; 66 }; 67 this.removeEventListener = function (instance, propertyPath, eventName, eventListenersId) { 68 var target = me.getInstanceProperty(instance, propertyPath); 69 target.removeEventListener(eventName, eventListeners[eventListenersId]); 70 delete eventListeners[eventListenersId]; 71 }; 72 this.getProperty = function (propertyPath) { 73 return me.getInstanceProperty(window, propertyPath); 74 }; 75 this.hasProperty = function (instance, propertyPath) { 76 return me.getInstanceProperty(instance, propertyPath) !== null; 77 }; 78 this.getPropertyRef = function (propertyPath) { 79 return me.getInstancePropertyRef(window, propertyPath); 80 }; 81 this.getInstancePropertyRef = function (instance, propertyPath) { 82 return me.storeObjectRef(me.getInstanceProperty(instance, propertyPath)); 83 }; 84 this.storeObjectRef = function (obj) { 85 var id = jsObjectRefId++; 86 jsObjectRefs[id] = obj; 87 var jsRef = {}; 88 jsRef[jsRefKey] = id; 89 return jsRef; 90 } 91 this.removeObjectRef = function (id) { 92 delete jsObjectRefs[id]; 93 } 94 function getPropertyList(path) { 95 var res = path.replace('[', '.').replace(']', '').split('.'); 96 if (res[0] === "") { // if we pass "[0].id" we want to return [0,'id'] 97 res.shift(); 98 } 99 return res; 100 } 101 this.getInstanceProperty = function (instance, propertyPath) { 102 if (propertyPath === '') { 103 return instance; 104 } 105 var currentProperty = instance; 106 var splitProperty = getPropertyList(propertyPath); 107 108 for (i = 0; i < splitProperty.length; i++) { 109 if (splitProperty[i] in currentProperty) { 110 currentProperty = currentProperty[splitProperty[i]]; 111 } else { 112 return null; 113 } 114 } 115 return currentProperty; 116 }; 117 this.setInstanceProperty = function (instance, propertyPath, value) { 118 var currentProperty = instance; 119 var splitProperty = getPropertyList(propertyPath); 120 for (i = 0; i < splitProperty.length; i++) { 121 if (splitProperty[i] in currentProperty) { 122 if (i === splitProperty.length - 1) { 123 currentProperty[splitProperty[i]] = value; 124 return; 125 } else { 126 currentProperty = currentProperty[splitProperty[i]]; 127 } 128 } else { 129 return; 130 } 131 } 132 }; 133 this.getInstancePropertySerializable = function (instance, propertyName, serializationSpec) { 134 var data = me.getInstanceProperty(instance, propertyName); 135 if (data instanceof Promise) {//needed when some properties like beforeinstallevent.userChoice are promise 136 return data; 137 } 138 var res = me.getSerializableObject(data, [], serializationSpec); 139 return res; 140 }; 141 this.callInstanceMethod = function (instance, methodPath, ...args) { 142 if (methodPath.indexOf('.') >= 0) { 143 //if it's a method call on a child object we get this child object so the method call will happen in the context of the child object 144 //some method like window.locaStorage.setItem will throw an exception if the context is not expected 145 var instancePath = methodPath.substring(0, methodPath.lastIndexOf('.')); 146 instance = me.getInstanceProperty(instance, instancePath); 147 methodPath = methodPath.substring(methodPath.lastIndexOf('.') + 1); 148 } 149 for (let index = 0; index < args.length; index++) { 150 const element = args[index]; 151 //we change null value to undefined as there is no way to pass undefined value from C# and most of the browser API use undefined instead of null value for "no value" 152 if (element === null) { 153 args[index] = undefined; 154 } 155 } 156 var method = me.getInstanceProperty(instance, methodPath); 157 return method.apply(instance, args); 158 }; 159 this.callInstanceMethodGetRef = function (instance, methodPath, ...args) { 160 return this.storeObjectRef(this.callInstanceMethod(instance, methodPath, ...args)); 161 };
162 this.getSerializableObject = function (data, alreadySerialized, serializationSpec) { 163 if (serializationSpec === false) { 164 return undefined; 165 } 166 if (!alreadySerialized) { 167 alreadySerialized = []; 168 } 169 if (typeof data == "undefined" || 170 data === null) { 171 return null; 172 } 173 if (typeof data === "number" || 174 typeof data === "string" || 175 typeof data == "boolean") { 176 return data; 177 } 178 var res = (Array.isArray(data)) ? [] : {}; 179 if (!serializationSpec) { 180 serializationSpec = "*"; 181 } 182 for (var i in data) { 183 var currentMember = data[i]; 184 185 if (typeof currentMember === 'function' || currentMember === null) { 186 continue; 187 } 188 var currentMemberSpec; 189 if (serializationSpec != "*") { 190 currentMemberSpec = Array.isArray(data) ? serializationSpec : serializationSpec[i]; 191 if (!currentMemberSpec) { 192 continue; 193 } 194 } else { 195 currentMemberSpec = "*" 196 } 197 if (typeof currentMember === 'object') { 198 if (alreadySerialized.indexOf(currentMember) >= 0) { 199 continue; 200 } 201 alreadySerialized.push(currentMember); 202 if (Array.isArray(currentMember) || currentMember.length) { 203 res[i] = []; 204 for (var j = 0; j < currentMember.length; j++) { 205 const arrayItem = currentMember[j]; 206 if (typeof arrayItem === 'object') { 207 res[i].push(me.getSerializableObject(arrayItem, alreadySerialized, currentMemberSpec)); 208 } else { 209 res[i].push(arrayItem); 210 } 211 } 212 } else { 213 //the browser provides some member (like plugins) as hash with index as key, if length == 0 we shall not convert it 214 if (currentMember.length === 0) { 215 res[i] = []; 216 } else { 217 res[i] = me.getSerializableObject(currentMember, alreadySerialized, currentMemberSpec); 218 } 219 } 220 221 222 } else { 223 // string, number or boolean 224 if (currentMember === Infinity) { //inifity is not serialized by JSON.stringify 225 currentMember = "Infinity"; 226 } 227 if (currentMember !== null) { //needed because the default json serializer in jsinterop serialize null values 228 res[i] = currentMember; 229 } 230 } 231 } 232 return res; 233 }; 234 this.navigator = new (function () { 235 this.geolocation = new (function () { 236 this.getCurrentPosition = function (options) { 237 return new Promise(function (resolve) { 238 navigator.geolocation.getCurrentPosition( 239 position => resolve({ location: me.getSerializableObject(position) }), 240 error => resolve({ error: me.getSerializableObject(error) }), 241 options) 242 }); 243 }; 244 this.watchPosition = function (options, wrapper) { 245 return navigator.geolocation.watchPosition( 246 position => { 247 const result = { location: me.getSerializableObject(position) }; 248 return wrapper.invokeMethodAsync('Invoke', result); 249 }, 250 error => wrapper.invokeMethodAsync('Invoke', { error: me.getSerializableObject(error) }), 251 options 252 ); 253 }; 254 })(); 255 this.getBattery = function () { 256 return new Promise(function (resolve, reject) { 257 if (navigator.battery) {//some browser does not implement getBattery but battery instead see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/battery 258 var res = me.getSerializableObject(navigator.battery); 259 resolve(res); 260 } 261 else if ('getBattery' in navigator) { 262 navigator.getBattery().then( 263 function (battery) { 264 var res = me.getSerializableObject(battery); 265 resolve(res); 266 } 267 ); 268 } 269 else { 270 resolve(null); 271 } 272 }); 273 } 274 })(); 275})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.