mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Support string literals+computed property names
With tests and associated baseline updates
This commit is contained in:
@@ -7856,9 +7856,11 @@ namespace ts {
|
||||
const name = declaration.propertyName || declaration.name;
|
||||
if (isVariableLike(parentDeclaration) &&
|
||||
parentDeclaration.type &&
|
||||
(name.kind === SyntaxKind.Identifier || name.kind == SyntaxKind.StringLiteral)) {
|
||||
const text = (<Identifier | LiteralExpression>name).text;
|
||||
return getTypeOfPropertyOfType(getTypeFromTypeNode(parentDeclaration.type), text);
|
||||
!isBindingPattern(name)) {
|
||||
const text = getTextOfPropertyName(name);
|
||||
if (text) {
|
||||
return getTypeOfPropertyOfType(getTypeFromTypeNode(parentDeclaration.type), text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ interface Show {
|
||||
show: (x: number) => string;
|
||||
}
|
||||
function f({ show = v => v.toString() }: Show) {}
|
||||
function f2({ "show": showRename = v => v.toString() }: Show) {}
|
||||
function f3({ ["show"]: showRename = v => v.toString() }: Show) {}
|
||||
|
||||
interface Nested {
|
||||
nested: Show
|
||||
@@ -23,12 +25,20 @@ interface StringIdentity {
|
||||
stringIdentity(s: string): string;
|
||||
}
|
||||
let { stringIdentity: id = arg => arg }: StringIdentity = { stringIdentity: x => x};
|
||||
|
||||
|
||||
|
||||
|
||||
//// [contextuallyTypedBindingInitializer.js]
|
||||
function f(_a) {
|
||||
var _b = _a.show, show = _b === void 0 ? function (v) { return v.toString(); } : _b;
|
||||
}
|
||||
function f2(_a) {
|
||||
var _b = _a["show"], showRename = _b === void 0 ? function (v) { return v.toString(); } : _b;
|
||||
}
|
||||
function f3(_a) {
|
||||
var _b = "show", _c = _a[_b], showRename = _c === void 0 ? function (v) { return v.toString(); } : _c;
|
||||
}
|
||||
function ff(_a) {
|
||||
var _b = _a.nested, nested = _b === void 0 ? { show: function (v) { return v.toString(); } } : _b;
|
||||
}
|
||||
|
||||
@@ -15,59 +15,79 @@ function f({ show = v => v.toString() }: Show) {}
|
||||
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
|
||||
>Show : Symbol(Show, Decl(contextuallyTypedBindingInitializer.ts, 0, 0))
|
||||
|
||||
function f2({ "show": showRename = v => v.toString() }: Show) {}
|
||||
>f2 : Symbol(f2, Decl(contextuallyTypedBindingInitializer.ts, 3, 49))
|
||||
>showRename : Symbol(showRename, Decl(contextuallyTypedBindingInitializer.ts, 4, 13))
|
||||
>v : Symbol(v, Decl(contextuallyTypedBindingInitializer.ts, 4, 34))
|
||||
>v.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
|
||||
>v : Symbol(v, Decl(contextuallyTypedBindingInitializer.ts, 4, 34))
|
||||
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
|
||||
>Show : Symbol(Show, Decl(contextuallyTypedBindingInitializer.ts, 0, 0))
|
||||
|
||||
function f3({ ["show"]: showRename = v => v.toString() }: Show) {}
|
||||
>f3 : Symbol(f3, Decl(contextuallyTypedBindingInitializer.ts, 4, 64))
|
||||
>showRename : Symbol(showRename, Decl(contextuallyTypedBindingInitializer.ts, 5, 13))
|
||||
>v : Symbol(v, Decl(contextuallyTypedBindingInitializer.ts, 5, 36))
|
||||
>v.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
|
||||
>v : Symbol(v, Decl(contextuallyTypedBindingInitializer.ts, 5, 36))
|
||||
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
|
||||
>Show : Symbol(Show, Decl(contextuallyTypedBindingInitializer.ts, 0, 0))
|
||||
|
||||
interface Nested {
|
||||
>Nested : Symbol(Nested, Decl(contextuallyTypedBindingInitializer.ts, 3, 49))
|
||||
>Nested : Symbol(Nested, Decl(contextuallyTypedBindingInitializer.ts, 5, 66))
|
||||
|
||||
nested: Show
|
||||
>nested : Symbol(nested, Decl(contextuallyTypedBindingInitializer.ts, 5, 18))
|
||||
>nested : Symbol(nested, Decl(contextuallyTypedBindingInitializer.ts, 7, 18))
|
||||
>Show : Symbol(Show, Decl(contextuallyTypedBindingInitializer.ts, 0, 0))
|
||||
}
|
||||
function ff({ nested = { show: v => v.toString() } }: Nested) {}
|
||||
>ff : Symbol(ff, Decl(contextuallyTypedBindingInitializer.ts, 7, 1))
|
||||
>nested : Symbol(nested, Decl(contextuallyTypedBindingInitializer.ts, 8, 13))
|
||||
>show : Symbol(show, Decl(contextuallyTypedBindingInitializer.ts, 8, 24))
|
||||
>v : Symbol(v, Decl(contextuallyTypedBindingInitializer.ts, 8, 30))
|
||||
>ff : Symbol(ff, Decl(contextuallyTypedBindingInitializer.ts, 9, 1))
|
||||
>nested : Symbol(nested, Decl(contextuallyTypedBindingInitializer.ts, 10, 13))
|
||||
>show : Symbol(show, Decl(contextuallyTypedBindingInitializer.ts, 10, 24))
|
||||
>v : Symbol(v, Decl(contextuallyTypedBindingInitializer.ts, 10, 30))
|
||||
>v.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
|
||||
>v : Symbol(v, Decl(contextuallyTypedBindingInitializer.ts, 8, 30))
|
||||
>v : Symbol(v, Decl(contextuallyTypedBindingInitializer.ts, 10, 30))
|
||||
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
|
||||
>Nested : Symbol(Nested, Decl(contextuallyTypedBindingInitializer.ts, 3, 49))
|
||||
>Nested : Symbol(Nested, Decl(contextuallyTypedBindingInitializer.ts, 5, 66))
|
||||
|
||||
interface Tuples {
|
||||
>Tuples : Symbol(Tuples, Decl(contextuallyTypedBindingInitializer.ts, 8, 64))
|
||||
>Tuples : Symbol(Tuples, Decl(contextuallyTypedBindingInitializer.ts, 10, 64))
|
||||
|
||||
prop: [string, number];
|
||||
>prop : Symbol(prop, Decl(contextuallyTypedBindingInitializer.ts, 10, 18))
|
||||
>prop : Symbol(prop, Decl(contextuallyTypedBindingInitializer.ts, 12, 18))
|
||||
}
|
||||
function g({ prop = ["hello", 1234] }: Tuples) {}
|
||||
>g : Symbol(g, Decl(contextuallyTypedBindingInitializer.ts, 12, 1))
|
||||
>prop : Symbol(prop, Decl(contextuallyTypedBindingInitializer.ts, 13, 12))
|
||||
>Tuples : Symbol(Tuples, Decl(contextuallyTypedBindingInitializer.ts, 8, 64))
|
||||
>g : Symbol(g, Decl(contextuallyTypedBindingInitializer.ts, 14, 1))
|
||||
>prop : Symbol(prop, Decl(contextuallyTypedBindingInitializer.ts, 15, 12))
|
||||
>Tuples : Symbol(Tuples, Decl(contextuallyTypedBindingInitializer.ts, 10, 64))
|
||||
|
||||
interface StringUnion {
|
||||
>StringUnion : Symbol(StringUnion, Decl(contextuallyTypedBindingInitializer.ts, 13, 49))
|
||||
>StringUnion : Symbol(StringUnion, Decl(contextuallyTypedBindingInitializer.ts, 15, 49))
|
||||
|
||||
prop: "foo" | "bar";
|
||||
>prop : Symbol(prop, Decl(contextuallyTypedBindingInitializer.ts, 15, 23))
|
||||
>prop : Symbol(prop, Decl(contextuallyTypedBindingInitializer.ts, 17, 23))
|
||||
}
|
||||
function h({ prop = "foo" }: StringUnion) {}
|
||||
>h : Symbol(h, Decl(contextuallyTypedBindingInitializer.ts, 17, 1))
|
||||
>prop : Symbol(prop, Decl(contextuallyTypedBindingInitializer.ts, 18, 12))
|
||||
>StringUnion : Symbol(StringUnion, Decl(contextuallyTypedBindingInitializer.ts, 13, 49))
|
||||
>h : Symbol(h, Decl(contextuallyTypedBindingInitializer.ts, 19, 1))
|
||||
>prop : Symbol(prop, Decl(contextuallyTypedBindingInitializer.ts, 20, 12))
|
||||
>StringUnion : Symbol(StringUnion, Decl(contextuallyTypedBindingInitializer.ts, 15, 49))
|
||||
|
||||
interface StringIdentity {
|
||||
>StringIdentity : Symbol(StringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 18, 44))
|
||||
>StringIdentity : Symbol(StringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 20, 44))
|
||||
|
||||
stringIdentity(s: string): string;
|
||||
>stringIdentity : Symbol(stringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 20, 26))
|
||||
>s : Symbol(s, Decl(contextuallyTypedBindingInitializer.ts, 21, 19))
|
||||
>stringIdentity : Symbol(stringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 22, 26))
|
||||
>s : Symbol(s, Decl(contextuallyTypedBindingInitializer.ts, 23, 19))
|
||||
}
|
||||
let { stringIdentity: id = arg => arg }: StringIdentity = { stringIdentity: x => x};
|
||||
>stringIdentity : Symbol(StringIdentity.stringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 20, 26))
|
||||
>id : Symbol(id, Decl(contextuallyTypedBindingInitializer.ts, 23, 5))
|
||||
>arg : Symbol(arg, Decl(contextuallyTypedBindingInitializer.ts, 23, 26))
|
||||
>arg : Symbol(arg, Decl(contextuallyTypedBindingInitializer.ts, 23, 26))
|
||||
>StringIdentity : Symbol(StringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 18, 44))
|
||||
>stringIdentity : Symbol(stringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 23, 59))
|
||||
>x : Symbol(x, Decl(contextuallyTypedBindingInitializer.ts, 23, 75))
|
||||
>x : Symbol(x, Decl(contextuallyTypedBindingInitializer.ts, 23, 75))
|
||||
>stringIdentity : Symbol(StringIdentity.stringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 22, 26))
|
||||
>id : Symbol(id, Decl(contextuallyTypedBindingInitializer.ts, 25, 5))
|
||||
>arg : Symbol(arg, Decl(contextuallyTypedBindingInitializer.ts, 25, 26))
|
||||
>arg : Symbol(arg, Decl(contextuallyTypedBindingInitializer.ts, 25, 26))
|
||||
>StringIdentity : Symbol(StringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 20, 44))
|
||||
>stringIdentity : Symbol(stringIdentity, Decl(contextuallyTypedBindingInitializer.ts, 25, 59))
|
||||
>x : Symbol(x, Decl(contextuallyTypedBindingInitializer.ts, 25, 75))
|
||||
>x : Symbol(x, Decl(contextuallyTypedBindingInitializer.ts, 25, 75))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,29 @@ function f({ show = v => v.toString() }: Show) {}
|
||||
>toString : (radix?: number) => string
|
||||
>Show : Show
|
||||
|
||||
function f2({ "show": showRename = v => v.toString() }: Show) {}
|
||||
>f2 : ({"show": showRename}: Show) => void
|
||||
>showRename : (x: number) => string
|
||||
>v => v.toString() : (v: number) => string
|
||||
>v : number
|
||||
>v.toString() : string
|
||||
>v.toString : (radix?: number) => string
|
||||
>v : number
|
||||
>toString : (radix?: number) => string
|
||||
>Show : Show
|
||||
|
||||
function f3({ ["show"]: showRename = v => v.toString() }: Show) {}
|
||||
>f3 : ({["show"]: showRename}: Show) => void
|
||||
>"show" : string
|
||||
>showRename : (x: number) => string
|
||||
>v => v.toString() : (v: number) => string
|
||||
>v : number
|
||||
>v.toString() : string
|
||||
>v.toString : (radix?: number) => string
|
||||
>v : number
|
||||
>toString : (radix?: number) => string
|
||||
>Show : Show
|
||||
|
||||
interface Nested {
|
||||
>Nested : Nested
|
||||
|
||||
@@ -83,3 +106,5 @@ let { stringIdentity: id = arg => arg }: StringIdentity = { stringIdentity: x =>
|
||||
>x : string
|
||||
>x : string
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +1,37 @@
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(4,20): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(9,23): error TS2322: Type '{ show: (v: number) => number; }' is not assignable to type 'Show'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(5,23): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(6,25): error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(11,23): error TS2322: Type '{ show: (v: number) => number; }' is not assignable to type 'Show'.
|
||||
Types of property 'show' are incompatible.
|
||||
Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(14,23): error TS2322: Type '(arg: string) => number' is not assignable to type '(s: string) => string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(16,23): error TS2322: Type '(arg: string) => number' is not assignable to type '(s: string) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(19,14): error TS2322: Type '[number, number]' is not assignable to type '[string, number]'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(21,14): error TS2322: Type '[number, number]' is not assignable to type '[string, number]'.
|
||||
Types of property '0' are incompatible.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(24,14): error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'.
|
||||
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts(26,14): error TS2322: Type '"baz"' is not assignable to type '"foo" | "bar"'.
|
||||
Type '"baz"' is not assignable to type '"bar"'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts (5 errors) ====
|
||||
==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedBindingInitializerNegative.ts (7 errors) ====
|
||||
interface Show {
|
||||
show: (x: number) => string;
|
||||
}
|
||||
function f({ show: showRename = v => v }: Show) {}
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
function f2({ "show": showRename = v => v }: Show) {}
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
function f3({ ["show"]: showRename = v => v }: Show) {}
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '(v: number) => number' is not assignable to type '(x: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
interface Nested {
|
||||
|
||||
@@ -3,6 +3,8 @@ interface Show {
|
||||
show: (x: number) => string;
|
||||
}
|
||||
function f({ show: showRename = v => v }: Show) {}
|
||||
function f2({ "show": showRename = v => v }: Show) {}
|
||||
function f3({ ["show"]: showRename = v => v }: Show) {}
|
||||
|
||||
interface Nested {
|
||||
nested: Show
|
||||
@@ -29,6 +31,12 @@ function h({ prop = "baz" }: StringUnion) {}
|
||||
function f(_a) {
|
||||
var _b = _a.show, showRename = _b === void 0 ? function (v) { return v; } : _b;
|
||||
}
|
||||
function f2(_a) {
|
||||
var _b = _a["show"], showRename = _b === void 0 ? function (v) { return v; } : _b;
|
||||
}
|
||||
function f3(_a) {
|
||||
var _b = "show", _c = _a[_b], showRename = _c === void 0 ? function (v) { return v; } : _c;
|
||||
}
|
||||
function ff(_a) {
|
||||
var _b = _a.nested, nestedRename = _b === void 0 ? { show: function (v) { return v; } } : _b;
|
||||
}
|
||||
|
||||
+4
@@ -3,6 +3,8 @@ interface Show {
|
||||
show: (x: number) => string;
|
||||
}
|
||||
function f({ show = v => v.toString() }: Show) {}
|
||||
function f2({ "show": showRename = v => v.toString() }: Show) {}
|
||||
function f3({ ["show"]: showRename = v => v.toString() }: Show) {}
|
||||
|
||||
interface Nested {
|
||||
nested: Show
|
||||
@@ -23,3 +25,5 @@ interface StringIdentity {
|
||||
stringIdentity(s: string): string;
|
||||
}
|
||||
let { stringIdentity: id = arg => arg }: StringIdentity = { stringIdentity: x => x};
|
||||
|
||||
|
||||
|
||||
+2
@@ -3,6 +3,8 @@ interface Show {
|
||||
show: (x: number) => string;
|
||||
}
|
||||
function f({ show: showRename = v => v }: Show) {}
|
||||
function f2({ "show": showRename = v => v }: Show) {}
|
||||
function f3({ ["show"]: showRename = v => v }: Show) {}
|
||||
|
||||
interface Nested {
|
||||
nested: Show
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
/// <reference path='..\src\harness\external\node.d.ts'/>
|
||||
"use strict";
|
||||
var http = require("http");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var url = require("url");
|
||||
var child_process = require("child_process");
|
||||
var os = require("os");
|
||||
/// Command line processing ///
|
||||
if (process.argv[2] == '--help') {
|
||||
console.log('Runs a node server on port 8888 by default, looking for tests folder in the current directory\n');
|
||||
console.log('Syntax: node nodeServer.js [port] [typescriptEnlistmentDirectory] [tests] [--browser] [--verbose]\n');
|
||||
console.log('Examples: \n\tnode nodeServer.js 8888 .');
|
||||
console.log('\tnode nodeServer.js 3000 D:/src/typescript/public --verbose IE');
|
||||
}
|
||||
function switchToForwardSlashes(path) {
|
||||
return path.replace(/\\/g, "/").replace(/\/\//g, '/');
|
||||
}
|
||||
var defaultPort = 8888;
|
||||
var port = process.argv[2] || defaultPort;
|
||||
var rootDir = switchToForwardSlashes(__dirname + '/../');
|
||||
var browser;
|
||||
if (process.argv[3]) {
|
||||
browser = process.argv[3];
|
||||
if (browser !== 'chrome' && browser !== 'IE') {
|
||||
console.log('Invalid command line arguments. Got ' + browser + ' but expected chrome, IE or nothing.');
|
||||
}
|
||||
}
|
||||
var grep = process.argv[4];
|
||||
var verbose = false;
|
||||
if (process.argv[5] == '--verbose') {
|
||||
verbose = true;
|
||||
}
|
||||
else if (process.argv[5] && process.argv[5] !== '--verbose') {
|
||||
console.log('Invalid command line arguments. Got ' + process.argv[5] + ' but expected --verbose or nothing.');
|
||||
}
|
||||
/// Utils ///
|
||||
function log(msg) {
|
||||
if (verbose) {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
// Copied from the compiler sources
|
||||
function dir(path, spec, options) {
|
||||
options = options || {};
|
||||
function filesInFolder(folder) {
|
||||
var folder = switchToForwardSlashes(folder);
|
||||
var paths = [];
|
||||
// Everything after the current directory is relative
|
||||
var baseDirectoryLength = process.cwd().length + 1;
|
||||
try {
|
||||
var files = fs.readdirSync(folder);
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var stat = fs.statSync(folder + "/" + files[i]);
|
||||
if (options.recursive && stat.isDirectory()) {
|
||||
paths = paths.concat(filesInFolder(folder + "/" + files[i]));
|
||||
}
|
||||
else if (stat.isFile() && (!spec || files[i].match(spec))) {
|
||||
var relativePath = folder.substring(baseDirectoryLength);
|
||||
paths.push(relativePath + "/" + files[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
return filesInFolder(path);
|
||||
}
|
||||
// fs.rmdirSync won't delete directories with files in it
|
||||
function deleteFolderRecursive(path) {
|
||||
if (fs.existsSync(path)) {
|
||||
fs.readdirSync(path).forEach(function (file, index) {
|
||||
var curPath = path + "/" + file;
|
||||
if (fs.statSync(curPath).isDirectory()) {
|
||||
deleteFolderRecursive(curPath);
|
||||
}
|
||||
else {
|
||||
fs.unlinkSync(curPath);
|
||||
}
|
||||
});
|
||||
fs.rmdirSync(path);
|
||||
}
|
||||
}
|
||||
;
|
||||
function writeFile(path, data, opts) {
|
||||
try {
|
||||
fs.writeFileSync(path, data);
|
||||
}
|
||||
catch (e) {
|
||||
// assume file was written to a directory that exists, if not, start recursively creating them as necessary
|
||||
var parts = switchToForwardSlashes(path).split('/');
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var subDir = parts.slice(0, i).join('/');
|
||||
if (!fs.existsSync(subDir)) {
|
||||
fs.mkdir(subDir);
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(path, data);
|
||||
}
|
||||
}
|
||||
/// Request Handling ///
|
||||
function handleResolutionRequest(filePath, res) {
|
||||
var resolvedPath = path.resolve(filePath, '');
|
||||
resolvedPath = resolvedPath.substring(resolvedPath.indexOf('tests'));
|
||||
resolvedPath = switchToForwardSlashes(resolvedPath);
|
||||
send('success', res, resolvedPath);
|
||||
return;
|
||||
}
|
||||
function send(result, res, contents, contentType) {
|
||||
if (contentType === void 0) { contentType = "binary"; }
|
||||
var responseCode = result === "success" ? 200 : result === "fail" ? 500 : result === 'unknown' ? 404 : parseInt(result);
|
||||
res.writeHead(responseCode, { "Content-Type": contentType });
|
||||
res.end(contents);
|
||||
return;
|
||||
}
|
||||
// Reads the data from a post request and passes it to the given callback
|
||||
function processPost(req, res, callback) {
|
||||
var queryData = "";
|
||||
if (typeof callback !== 'function')
|
||||
return null;
|
||||
if (req.method == 'POST') {
|
||||
req.on('data', function (data) {
|
||||
queryData += data;
|
||||
if (queryData.length > 1e8) {
|
||||
queryData = "";
|
||||
send("413", res, null);
|
||||
console.log("ERROR: destroying connection");
|
||||
req.connection.destroy();
|
||||
}
|
||||
});
|
||||
req.on('end', function () {
|
||||
//res.post = url.parse(req.url).query;
|
||||
callback(queryData);
|
||||
});
|
||||
}
|
||||
else {
|
||||
send("405", res, null);
|
||||
}
|
||||
}
|
||||
var RequestType;
|
||||
(function (RequestType) {
|
||||
RequestType[RequestType["GetFile"] = 0] = "GetFile";
|
||||
RequestType[RequestType["GetDir"] = 1] = "GetDir";
|
||||
RequestType[RequestType["ResolveFile"] = 2] = "ResolveFile";
|
||||
RequestType[RequestType["WriteFile"] = 3] = "WriteFile";
|
||||
RequestType[RequestType["DeleteFile"] = 4] = "DeleteFile";
|
||||
RequestType[RequestType["WriteDir"] = 5] = "WriteDir";
|
||||
RequestType[RequestType["DeleteDir"] = 6] = "DeleteDir";
|
||||
RequestType[RequestType["AppendFile"] = 7] = "AppendFile";
|
||||
RequestType[RequestType["Unknown"] = 8] = "Unknown";
|
||||
})(RequestType || (RequestType = {}));
|
||||
function getRequestOperation(req, filename) {
|
||||
if (req.method === 'GET' && req.url.indexOf('?') === -1) {
|
||||
if (req.url.indexOf('.') !== -1)
|
||||
return RequestType.GetFile;
|
||||
else
|
||||
return RequestType.GetDir;
|
||||
}
|
||||
else {
|
||||
var queryData = url.parse(req.url, true).query;
|
||||
if (req.method === 'GET' && queryData.resolve !== undefined)
|
||||
return RequestType.ResolveFile;
|
||||
// mocha uses ?grep=<regexp> query string as equivalent to the --grep command line option used to filter tests
|
||||
if (req.method === 'GET' && queryData.grep !== undefined)
|
||||
return RequestType.GetFile;
|
||||
if (req.method === 'POST' && queryData.action) {
|
||||
var path = req.url.substr(0, req.url.lastIndexOf('?'));
|
||||
var isFile = path.substring(path.lastIndexOf('/')).indexOf('.') !== -1;
|
||||
switch (queryData.action.toUpperCase()) {
|
||||
case 'WRITE':
|
||||
return isFile ? RequestType.WriteFile : RequestType.WriteDir;
|
||||
case 'DELETE':
|
||||
return isFile ? RequestType.DeleteFile : RequestType.DeleteDir;
|
||||
case 'APPEND':
|
||||
return isFile ? RequestType.AppendFile : RequestType.Unknown;
|
||||
}
|
||||
}
|
||||
return RequestType.Unknown;
|
||||
}
|
||||
}
|
||||
function handleRequestOperation(req, res, operation, reqPath) {
|
||||
switch (operation) {
|
||||
case RequestType.GetDir:
|
||||
var filesInFolder = dir(reqPath, "", { recursive: true });
|
||||
send('success', res, filesInFolder.join(','));
|
||||
break;
|
||||
case RequestType.GetFile:
|
||||
fs.readFile(reqPath, function (err, file) {
|
||||
var ext = reqPath.substr(reqPath.lastIndexOf('.'));
|
||||
var contentType = 'binary';
|
||||
if (ext === '.js')
|
||||
contentType = 'text/javascript';
|
||||
else if (ext === '.css')
|
||||
contentType = 'text/javascript';
|
||||
else if (ext === '.html')
|
||||
contentType = 'text/html';
|
||||
err
|
||||
? send('fail', res, err.message, contentType)
|
||||
: send('success', res, file, contentType);
|
||||
});
|
||||
break;
|
||||
case RequestType.ResolveFile:
|
||||
var resolveRequest = req.url.match(/(.*)\?resolve/);
|
||||
handleResolutionRequest(resolveRequest[1], res);
|
||||
break;
|
||||
case RequestType.WriteFile:
|
||||
processPost(req, res, function (data) {
|
||||
writeFile(reqPath, data, { recursive: true });
|
||||
});
|
||||
send('success', res, null);
|
||||
break;
|
||||
case RequestType.WriteDir:
|
||||
fs.mkdirSync(reqPath);
|
||||
send('success', res, null);
|
||||
break;
|
||||
case RequestType.DeleteFile:
|
||||
if (fs.existsSync(reqPath)) {
|
||||
fs.unlinkSync(reqPath);
|
||||
}
|
||||
send('success', res, null);
|
||||
break;
|
||||
case RequestType.DeleteDir:
|
||||
if (fs.existsSync(reqPath)) {
|
||||
fs.rmdirSync(reqPath);
|
||||
}
|
||||
send('success', res, null);
|
||||
break;
|
||||
case RequestType.AppendFile:
|
||||
processPost(req, res, function (data) {
|
||||
fs.appendFileSync(reqPath, data);
|
||||
});
|
||||
send('success', res, null);
|
||||
break;
|
||||
case RequestType.Unknown:
|
||||
default:
|
||||
send('unknown', res, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
console.log("Static file server running at\n => http://localhost:" + port + "/\nCTRL + C to shutdown");
|
||||
http.createServer(function (req, res) {
|
||||
log(req.method + ' ' + req.url);
|
||||
var uri = url.parse(req.url).pathname;
|
||||
var reqPath = path.join(process.cwd(), uri);
|
||||
var operation = getRequestOperation(req, reqPath);
|
||||
handleRequestOperation(req, res, operation, reqPath);
|
||||
}).listen(8888);
|
||||
var browserPath;
|
||||
if ((browser && browser === 'chrome')) {
|
||||
var defaultChromePath = "";
|
||||
switch (os.platform()) {
|
||||
case "win32":
|
||||
case "win64":
|
||||
defaultChromePath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe";
|
||||
break;
|
||||
case "darwin":
|
||||
defaultChromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
|
||||
break;
|
||||
case "linux":
|
||||
defaultChromePath = "/opt/google/chrome/chrome";
|
||||
break;
|
||||
default:
|
||||
console.log("default Chrome location is unknown for platform '" + os.platform() + "'");
|
||||
break;
|
||||
}
|
||||
if (fs.existsSync(defaultChromePath)) {
|
||||
browserPath = defaultChromePath;
|
||||
}
|
||||
else {
|
||||
browserPath = browser;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var defaultIEPath = 'C:/Program Files/Internet Explorer/iexplore.exe';
|
||||
if (fs.existsSync(defaultIEPath)) {
|
||||
browserPath = defaultIEPath;
|
||||
}
|
||||
else {
|
||||
browserPath = browser;
|
||||
}
|
||||
}
|
||||
console.log('Using browser: ' + browserPath);
|
||||
var queryString = grep ? "?grep=" + grep : '';
|
||||
child_process.spawn(browserPath, ['http://localhost:' + port + '/tests/webTestResults.html' + queryString], {
|
||||
stdio: 'inherit'
|
||||
});
|
||||
//# sourceMappingURL=file:///E:/ts/tests/webTestServer.js.map
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user