Skip to content

Commit ab0d393

Browse files
committed
Port boot code race condition fix to Giraffe
See: #51
1 parent 006e041 commit ab0d393

2 files changed

Lines changed: 65 additions & 82 deletions

File tree

src/Aardvark.Service.Giraffe/MutableApp.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ module MutableApp =
209209
printfn "%A" e
210210
)
211211

212-
213-
let r = send (Text.Encoding.UTF8.GetBytes("x" + code))
212+
let tag = if state.references.Count > 0 then "r" else "x"
213+
let r = send (Text.Encoding.UTF8.GetBytes(tag + code))
214214
r.Result |> ignore
215215

216216

src/Aardvark.Service.Giraffe/resources/aardvark.js

Lines changed: 63 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,12 @@ if (!aardvark.channels) {
9999
aardvark.channels = {};
100100
}
101101

102-
if (!aardvark.referencedScripts) {
103-
console.debug("[Aardvark] creating aardvark-script-references");
104-
aardvark.referencedScripts = {};
102+
if (!aardvark.references) {
103+
console.debug("[Aardvark] creating aardvark-references");
104+
aardvark.references = {};
105105
}
106106

107-
if (!aardvark.referencedStyles) {
108-
console.debug("[Aardvark] creating aardvark-stylesheet-references");
109-
aardvark.referencedStyles = {};
110-
}
111-
112-
aardvark.referencedScripts["jquery"] = true;
107+
aardvark.references["jquery-script"] = true;
113108

114109
if (!aardvark.processEvent) {
115110
console.debug("[Aardvark] creating aardvark-event-processor");
@@ -883,73 +878,56 @@ class Renderer {
883878
}
884879

885880
if (!aardvark.addReferences) {
886-
aardvark.addReferences = function (refs, realCont) {
887-
888-
aardvark.promise = aardvark.promise.then(function () {
889-
return new Promise(function (s, e) {
890-
var cont = function () { realCont(); s(); };
881+
aardvark.addReferences = function (refs, userCode) {
891882

892-
function acc(i) {
893-
if (i >= refs.length) {
894-
return cont;
895-
}
896-
else {
897-
var ref = refs[i];
898-
var kind = ref.kind;
899-
var name = ref.name;
900-
var url = ref.url;
901-
if (kind === "script" || kind === "module") {
902-
if (!aardvark.referencedScripts[name]) {
903-
aardvark.referencedScripts[name] = true;
904-
return function () {
905-
var script = document.createElement("script");
906-
var cc = function (evt) {
907-
console.debug(`[Aardvark] referenced ${kind} "${name}" (${url})`);
908-
acc(i + 1)();
909-
};
910-
var err = function (evt) {
911-
console.warn(`[Aardvark] failed to referenced ${kind} "${name}" (${url})`);
912-
acc(i + 1)();
913-
};
914-
script.src = url;
915-
script.async = true;
916-
if (kind === "module") script.type = "module";
917-
script.addEventListener("load", cc);
918-
script.addEventListener("error", err);
919-
document.getElementsByTagName("script")[0].parentNode.appendChild(script);
920-
};
921-
}
922-
else return acc(i + 1);
923-
}
924-
else {
925-
if (!aardvark.referencedStyles[name]) {
926-
aardvark.referencedStyles[name] = true;
927-
return function () {
928-
var script = document.createElement("link");
929-
var cc = function (evt) {
930-
console.debug("[Aardvark] referenced stylesheet \"" + name + "\" (" + url + ")");
931-
acc(i + 1)();
932-
};
933-
var err = function (evt) {
934-
console.warn("[Aardvark] failed to reference stylesheet \"" + name + "\" (" + url + ")");
935-
acc(i + 1)();
936-
};
937-
script.addEventListener("load", cc);
938-
script.addEventListener("error", err);
939-
script.setAttribute("rel", "stylesheet");
940-
script.setAttribute("href", url);
941-
document.head.appendChild(script);
942-
};
943-
}
944-
else return acc(i + 1);
945-
}
883+
function loadScript(ref) {
884+
return new Promise((resolve, reject) => {
885+
886+
const name = ref.name;
887+
const kind = ref.kind; // "script", "module", or "stylesheet"
888+
const url = ref.url;
889+
890+
const key = `${name}-${kind}`; // allow using identical names for different kinds
891+
892+
if (aardvark.references[key]) {
893+
return resolve();
894+
}
895+
896+
aardvark.references[key] = true;
897+
898+
const isScript = kind === "script" || kind === "module";
899+
const refElem = document.createElement(isScript ? "script" : "link");
900+
const cc = function (evt) {
901+
console.debug(`[Aardvark] referenced ${kind} "${name}" (${url})`);
902+
resolve();
903+
};
904+
const err = function (evt) {
905+
console.warn(`[Aardvark] failed to reference ${kind} "${name}" (${url})`);
906+
resolve();
907+
};
946908

909+
refElem.addEventListener("load", cc);
910+
refElem.addEventListener("error", err);
911+
912+
if (isScript) {
913+
if (kind === "module") {
914+
refElem.type = "module";
947915
}
916+
refElem.src = url;
917+
refElem.async = true;
918+
document.getElementsByTagName("script")[0].parentNode.appendChild(refElem);
919+
}
920+
else {
921+
refElem.setAttribute("rel", "stylesheet");
922+
refElem.setAttribute("href", url);
923+
document.head.appendChild(refElem);
948924
}
949-
var real = acc(0);
950-
real();
951925
});
952-
});
926+
}
927+
928+
aardvark.promise = aardvark.promise.then(() => Promise.all(refs.map(loadScript)));
929+
930+
aardvark.promise = aardvark.promise.then(() => userCode());
953931
};
954932
}
955933

@@ -1099,19 +1077,24 @@ if (!aardvark.connect) {
10991077

11001078
eventSocket.onmessage = function (m) {
11011079
var c = m.data.substring(0, 1);
1102-
if (c === "x") {
1103-
var data = m.data.substring(1, m.data.length);
1104-
aardvark.promise = aardvark.promise.then(function () {
1080+
if (c === "r" || c === "x") {
1081+
const code = m.data.substring(1, m.data.length);
1082+
const evaluate = function () {
11051083
try {
1106-
//exectutedCode = exectutedCode + "\r\n\r\n\r\n" + data;
1107-
(new Function("{\r\n" + data + "\r\n}"))();
1084+
(new Function(`{ ${code} }`))();
11081085
} catch (e) {
1109-
console.warn("could not execute event message with exn " + e + ":\n" + data);
1086+
console.warn("could not execute event message with exn " + e + ":\n" + code);
11101087
debugger;
11111088
}
1112-
});
1113-
}
1114-
else {
1089+
}
1090+
1091+
if (c === "r") {
1092+
// addReferences function directly chains script/stylesheet loading and user code execution in aardvark.promise chain
1093+
evaluate();
1094+
} else {
1095+
aardvark.promise = aardvark.promise.then(evaluate);
1096+
}
1097+
} else {
11151098
var data = m.data;
11161099
// { targetId : string; channel : string; data : 'a }
11171100
var message = JSON.parse(data);

0 commit comments

Comments
 (0)