mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 10:33:59 -05:00
Merge branch 'master' into mg/async_tweaks
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Contributing to Compiler Explorer
|
||||
|
||||
First of, if you're reading this: thank you! Even considering contributing to
|
||||
First off, if you're reading this: thank you! Even considering contributing to
|
||||
**Compiler Explorer** is very much appreciated!
|
||||
Before we go too far, an apology: **Compiler Explorer** grew out of a bit of
|
||||
hacky JavaScript into a pretty large and well-used project pretty quickly.
|
||||
|
||||
16
app.js
16
app.js
@@ -40,6 +40,7 @@ const nopt = require('nopt'),
|
||||
urljoin = require('url-join'),
|
||||
_ = require('underscore'),
|
||||
express = require('express'),
|
||||
responseTime = require('response-time'),
|
||||
Sentry = require('@sentry/node'),
|
||||
{logger, logToPapertrail, suppressConsoleLog} = require('./lib/logger'),
|
||||
utils = require('./lib/utils'),
|
||||
@@ -462,16 +463,30 @@ async function main() {
|
||||
rescanCompilerSecs * 1000);
|
||||
}
|
||||
|
||||
const sentrySlowRequestMs = ceProps("sentrySlowRequestMs", 0);
|
||||
|
||||
webServer
|
||||
.set('trust proxy', true)
|
||||
.set('view engine', 'pug')
|
||||
.on('error', err => logger.error('Caught error in web handler; continuing:', err))
|
||||
// sentry request handler must be the first middleware on the app
|
||||
.use(Sentry.Handlers.requestHandler())
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
.use(responseTime((req, res, time) => {
|
||||
if (sentrySlowRequestMs > 0 && time >= sentrySlowRequestMs) {
|
||||
Sentry.withScope(scope => {
|
||||
scope.setExtra('duration_ms', time);
|
||||
Sentry.captureMessage('SlowRequest', 'warning');
|
||||
});
|
||||
}
|
||||
}))
|
||||
// Handle healthchecks at the root, as they're not expected from the outside world
|
||||
.use('/healthcheck', new healthCheck.HealthCheckHandler(healthCheckFilePath).handle)
|
||||
.use(httpRoot, router)
|
||||
.use((req, res, next) => {
|
||||
next({status: 404, message: `page "${req.path}" could not be found`});
|
||||
})
|
||||
// sentry error handler must be the first error handling middleware
|
||||
.use(Sentry.Handlers.errorHandler)
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
.use((err, req, res) => {
|
||||
@@ -565,7 +580,6 @@ async function main() {
|
||||
});
|
||||
|
||||
router
|
||||
.use(Sentry.Handlers.requestHandler())
|
||||
.use(morgan(morganFormat, {
|
||||
stream: logger.stream,
|
||||
// Skip for non errors (2xx, 3xx)
|
||||
|
||||
@@ -28,4 +28,5 @@ eventLoopLagThresholdWarn=100
|
||||
eventLoopLagThresholdErr=1000
|
||||
|
||||
staticUrl=https://static.ce-cdn.net/
|
||||
sentryEnvironment=prod
|
||||
sentryEnvironment=prod
|
||||
sentrySlowRequestMs=20000
|
||||
|
||||
@@ -2,7 +2,7 @@ compilers=&swift
|
||||
demangler=/opt/compiler-explorer/swift-5.1/usr/bin/swift-demangle
|
||||
defaultCompiler=swift51
|
||||
|
||||
group.swift.compilers=swift311:swift402:swift403:swift41:swift411:swift412:swift42:swift50:swift51
|
||||
group.swift.compilers=swift311:swift402:swift403:swift41:swift411:swift412:swift42:swift50:swift51:swiftnightly
|
||||
group.swift.isSemVer=true
|
||||
group.swift.baseName=x86-64 swiftc
|
||||
compiler.swift311.exe=/opt/compiler-explorer/swift-3.1.1/usr/bin/swiftc
|
||||
@@ -23,7 +23,8 @@ compiler.swift50.exe=/opt/compiler-explorer/swift-5.0/usr/bin/swiftc
|
||||
compiler.swift50.semver=5.0
|
||||
compiler.swift51.exe=/opt/compiler-explorer/swift-5.1/usr/bin/swiftc
|
||||
compiler.swift51.semver=5.1
|
||||
|
||||
compiler.swiftnightly.exe=/opt/compiler-explorer/swift-nightly/usr/bin/swiftc
|
||||
compiler.swiftnightly.semver=nightly
|
||||
|
||||
#################################
|
||||
#################################
|
||||
|
||||
@@ -141,17 +141,14 @@ class Demangler extends AsmRegex {
|
||||
* @param {string} translation
|
||||
*/
|
||||
addTranslation(symbol, translation) {
|
||||
let metadataStr = "";
|
||||
|
||||
if (this.includeMetadata) {
|
||||
const metadata = this.getMetadata(symbol);
|
||||
metadataStr = metadata.map((meta) => " [" + meta.description + "]").join();
|
||||
translation += this.getMetadata(symbol).map((meta) => " [" + meta.description + "]").join();
|
||||
}
|
||||
|
||||
if (this.symbolstore.contains(symbol)) {
|
||||
this.symbolstore.add(symbol, translation + metadataStr);
|
||||
this.symbolstore.add(symbol, translation);
|
||||
} else {
|
||||
this.othersymbols.add(symbol, translation + metadataStr);
|
||||
this.othersymbols.add(symbol, translation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,27 +162,19 @@ class Demangler extends AsmRegex {
|
||||
for (let i = 0; i < lines.length; ++i)
|
||||
this.addTranslation(this.input[i], lines[i]);
|
||||
|
||||
let translations = [];
|
||||
translations = translations.concat(this.symbolstore.listTranslations());
|
||||
translations = translations.concat(this.othersymbols.listTranslations());
|
||||
const translations = [...this.symbolstore.listTranslations(), ...this.othersymbols.listTranslations()]
|
||||
.filter(elem => elem[0] !== elem[1]);
|
||||
|
||||
for (let i = 0; i < this.result.asm.length; ++i) {
|
||||
let line = this.result.asm[i].text;
|
||||
for (let j = 0; j < translations.length; ++j) {
|
||||
const oldValue = translations[j][0];
|
||||
const newValue = translations[j][1];
|
||||
|
||||
line = line.replace(oldValue, newValue);
|
||||
line = line.replace(oldValue, newValue);
|
||||
|
||||
this.demangleLabels(this.result.asm[i].labels,
|
||||
oldValue, newValue);
|
||||
for (const asm of this.result.asm) {
|
||||
let line = asm.text;
|
||||
for (const [oldValue, newValue] of translations) {
|
||||
line = utils.replaceAll(line, oldValue, newValue);
|
||||
this.demangleLabels(asm.labels, oldValue, newValue);
|
||||
}
|
||||
this.result.asm[i].text = line;
|
||||
asm.text = line;
|
||||
}
|
||||
|
||||
this.demangleLabelDefinitions(
|
||||
this.result.labelDefinitions, translations);
|
||||
this.demangleLabelDefinitions(this.result.labelDefinitions, translations);
|
||||
|
||||
return this.result;
|
||||
}
|
||||
|
||||
15
lib/utils.js
15
lib/utils.js
@@ -205,3 +205,18 @@ exports.toProperty = function toProperty(prop) {
|
||||
if (prop.match(/^-?[0-9]*\.[0-9]+$/)) return parseFloat(prop);
|
||||
return prop;
|
||||
};
|
||||
|
||||
// This function replaces all the "oldValues" in line with "newValue". It handles overlapping string replacement cases,
|
||||
// and is careful to return the exact same line object if there's no matches. This turns out to be super important for
|
||||
// performance.
|
||||
exports.replaceAll = function replaceAll(line, oldValue, newValue) {
|
||||
if (oldValue.length === 0) return line;
|
||||
let startPoint = 0;
|
||||
for (; ;) {
|
||||
const index = line.indexOf(oldValue, startPoint);
|
||||
if (index === -1) break;
|
||||
line = line.substr(0, index) + newValue + line.substr(index + oldValue.length);
|
||||
startPoint = index + newValue.length;
|
||||
}
|
||||
return line;
|
||||
};
|
||||
|
||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -7473,6 +7473,15 @@
|
||||
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
|
||||
"dev": true
|
||||
},
|
||||
"response-time": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz",
|
||||
"integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=",
|
||||
"requires": {
|
||||
"depd": "~1.1.0",
|
||||
"on-headers": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"restore-cursor": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"promise-queue": "2.2.3",
|
||||
"pug": "^2.0.4",
|
||||
"request": "^2.88.0",
|
||||
"response-time": "^2.3.2",
|
||||
"selectize": "0.12.4",
|
||||
"semver": "^5.7.1",
|
||||
"serve-favicon": "^2.4.5",
|
||||
|
||||
@@ -83,6 +83,10 @@
|
||||
<li>Nathan Bronson</li>
|
||||
<li>Kaz Tros</li>
|
||||
<li>Jean-François</li>
|
||||
<li>Charles Wilkes</li>
|
||||
<li>Kaido Kert</li>
|
||||
<li>Carsten Schultz</li>
|
||||
<li>Cornel Izbasa</li>
|
||||
<li>Stefan Groth</li>
|
||||
<li>Sorin Suciu</li>
|
||||
<li>Andreas Gravgaard Andersen</li>
|
||||
|
||||
@@ -319,3 +319,34 @@ describe('squashes horizontal whitespace', () => {
|
||||
utils.squashHorizontalWhitespace(' abc abc').should.equals(' abc abc');
|
||||
});
|
||||
});
|
||||
|
||||
describe('replaces all substrings', () => {
|
||||
it('works with no substitutions', () => {
|
||||
const string = "This is a line with no replacements";
|
||||
utils.replaceAll(string, "not present", "won't be substituted").should.equal(string);
|
||||
});
|
||||
it('handles odd cases', () => {
|
||||
utils.replaceAll("", "", "").should.equal("");
|
||||
utils.replaceAll("Hello", "", "").should.equal("Hello");
|
||||
});
|
||||
it('works with single replacement', () => {
|
||||
utils.replaceAll("This is a line with a mistook in it", "mistook", "mistake")
|
||||
.should.equal("This is a line with a mistake in it");
|
||||
utils.replaceAll("This is a line with a mistook", "mistook", "mistake")
|
||||
.should.equal("This is a line with a mistake");
|
||||
utils.replaceAll("Mistooks were made", "Mistooks", "Mistakes")
|
||||
.should.equal("Mistakes were made");
|
||||
});
|
||||
|
||||
it('works with multiple replacements', () => {
|
||||
utils.replaceAll("A mistook is a mistook", "mistook", "mistake")
|
||||
.should.equal("A mistake is a mistake");
|
||||
utils.replaceAll("aaaaaaaaaaaaaaaaaaaaaaaaaaa", "a", "b")
|
||||
.should.equal("bbbbbbbbbbbbbbbbbbbbbbbbbbb");
|
||||
});
|
||||
|
||||
it('works with overlapping replacements', () => {
|
||||
utils.replaceAll("aaaaaaaa", "a", "ba")
|
||||
.should.equal("babababababababa");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user