Skip to content

Commit

Permalink
Merge 2eebaaa into c6c9122
Browse files Browse the repository at this point in the history
  • Loading branch information
DylanPiercey committed Dec 14, 2018
2 parents c6c9122 + 2eebaaa commit dd1f961
Show file tree
Hide file tree
Showing 22 changed files with 595 additions and 124 deletions.
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/work
/build
/.idea/
/npm-debug.log
/node_modules
/*.sublime-workspace
.idea/
npm-debug.log
node_modules
*.sublime-workspace
*.orig
.DS_Store
.vscode
Expand Down
302 changes: 300 additions & 2 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"warp10": "^1.0.0"
},
"devDependencies": {
"@marko/migrate": "^1.2.0",
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-plugin-minprops": "^2.0.1",
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/CompileContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,10 @@ class CompileContext extends EventEmitter {
isServerTarget() {
return this.target === "server";
}

addMigration() {
// Actual functionality implemented by marko migrate cli command.
}
}

CompileContext.prototype.util = {
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ function parse(templateSrc, filename, options) {
filename,
Builder.DEFAULT_BUILDER
);

if (options.onContext) {
options.onContext(context);
}
var parsed = defaultParser.parse(templateSrc, context, options);

if (context.hasErrors()) {
Expand Down
7 changes: 5 additions & 2 deletions src/components/taglib/TransformHelper/convertToComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ module.exports = function handleComponentBind(options) {

context.firstBind = true;

let isLegacyComponent = (this.isLegacyComponent =
options.isLegacyComponent === true);
if (options.isLegacyComponent) {
context.setMeta("legacy", true);
}

let isLegacyComponent = this.isLegacyComponent;
let componentModule = options.componentModule;
let rendererModule = options.rendererModule;
let componentProps = options.componentProps || {};
Expand Down
151 changes: 37 additions & 114 deletions src/components/taglib/TransformHelper/handleLegacyBind.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,4 @@
"use strict";
const resolveFrom = require("resolve-from");

function legacyGetDefaultComponentModule(dirname) {
var filename;
var legacy = true;

if ((filename = resolveFrom(dirname, "./widget"))) {
return {
filename,
requirePath: "./widget",
legacy
};
} else if ((filename = resolveFrom(dirname, "./component"))) {
return {
filename,
requirePath: "./component",
legacy
};
} else if ((filename = resolveFrom(dirname, "./"))) {
return {
filename,
requirePath: "./",
legacy
};
} else {
return null;
}
}

function checkIsInnerBind(el) {
var curNode = el;
Expand All @@ -45,107 +17,58 @@ module.exports = function handleLegacyBind() {
let context = this.context;
let builder = this.builder;

let componentModule;
let rendererModule;
let componentModule = context.legacyComponentModule;
let rendererModule = context.legacyRendererModule;

if (el.hasAttribute("w-bind")) {
let bindAttr = el.getAttribute("w-bind");
let bindAttr = el.getAttribute("w-bind");

context.deprecate(
"Legacy components using w-bind and defineRenderer/defineComponent or defineComponent are deprecated. See: https://github.com/marko-js/marko/issues/421"
);
this.isLegacyComponent = true;
context.setMeta("legacy", true);
el.data.hasBoundComponent = true;

// Remove the w-bind attribute since we don't want it showing up in the output DOM
el.removeAttribute("w-bind");
// Remove the w-bind attribute since we don't want it showing up in the output DOM
el.removeAttribute("w-bind");

// Set key value so we can get the root using this.el
el.setAttributeValue("key", builder.literal("_wbind"));
// Set key value so we can get the root using this.el
el.setAttributeValue("key", builder.literal("_wbind"));

// Read the value for the w-bind attribute. This will be an AST node for the parsed JavaScript
let bindAttrValue = bindAttr.value;
// Read the value for the w-bind attribute. This will be an AST node for the parsed JavaScript
let bindAttrValue = bindAttr.value;

const hasWidgetTypes = context.isFlagSet("hasWidgetTypes");
const hasWidgetTypes = context.isFlagSet("hasWidgetTypes");

if (hasWidgetTypes) {
context.deprecate(
"The <widget-types> tag is deprecated. Please remove it. See: https://github.com/marko-js/marko/issues/514"
if (hasWidgetTypes) {
context.deprecate(
"The <widget-types> tag is deprecated. Please remove it. See: https://github.com/marko-js/marko/issues/514"
);
}

if (bindAttrValue != null && !bindAttr.isLiteralValue()) {
// This is a dynamic expression. The <widget-types> should have been found.
if (!hasWidgetTypes) {
this.addError(
'The <widget-types> tag must be used to declare components when the value of the "w-bind" attribute is a dynamic expression.'
);
return;
}

if (bindAttrValue == null) {
componentModule = legacyGetDefaultComponentModule(this.dirname);
if (!componentModule) {
this.addError(
'No corresponding JavaScript module found in the same directory (either "component.js" or "index.js").'
);
return;
}
if (componentModule.requirePath === "./") {
rendererModule = componentModule;
}
} else if (bindAttr.isLiteralValue()) {
if (typeof bindAttr.literalValue !== "string") {
this.addError(
'The value for the "w-bind" attribute should be a string. Actual: ' +
componentModule
);
return;
}

let requirePath = bindAttr.literalValue;
let filename = resolveFrom(this.dirname, requirePath);

if (!filename) {
this.addError(
"Target file not found: " +
requirePath +
" (from: " +
this.dirname +
")"
);
return;
}

componentModule = {
legacy: true,
filename,
requirePath
};
} else {
// This is a dynamic expression. The <widget-types> should have been found.
if (!hasWidgetTypes) {
this.addError(
'The <widget-types> tag must be used to declare components when the value of the "w-bind" attribute is a dynamic expression.'
);
return;
}

el.insertSiblingBefore(
builder.functionCall(
el.insertSiblingBefore(
builder.functionCall(
builder.memberExpression(
builder.identifier("__component"),
builder.identifier("t")
),
[
builder.memberExpression(
builder.identifier("__component"),
builder.identifier("t")
),
[
builder.memberExpression(
builder.identifier("marko_componentTypes"),
bindAttrValue,
true /* computed */
)
]
)
);
}
} else {
return;
builder.identifier("marko_componentTypes"),
bindAttrValue,
true /* computed */
)
]
)
);
}

let isLegacyInnerBind = checkIsInnerBind(el.parentNode);

el.data.hasBoundComponent = true;

// A component is bound to the el...

if (el.hasAttribute("w-config")) {
Expand Down
4 changes: 4 additions & 0 deletions src/components/taglib/TransformHelper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ class TransformHelper {
return this.context.data[MARKO_WIDGETS_VAR_KEY];
}

get isLegacyComponent() {
return this.context.meta.legacy;
}

buildComponentElIdFunctionCall(id) {
var builder = this.builder;

Expand Down
2 changes: 1 addition & 1 deletion src/components/taglib/widget-types-tag.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = function codeGenerator(el, codegen) {
var context = codegen.context;
var transformHelper = getTransformHelper(el, context);

transformHelper.isLegacyComponent = true;
context.setMeta("legacy", true);

var builder = codegen.builder;

Expand Down
118 changes: 118 additions & 0 deletions src/taglibs/migrate/common/w-bind.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
const resolveFrom = require("resolve-from");

module.exports = function migrate(el, context) {
const attr = el.getAttribute("w-bind");

if (!attr) {
return;
}

const value = attr.value;
const hasWidgetTypes = context.isFlagSet("hasWidgetTypes");
let componentModule;
let rendererModule;

context.setMeta("legacy", true);

context.deprecate(
"Legacy components using w-bind and defineRenderer/defineComponent or defineComponent are deprecated. See: https://github.com/marko-js/marko/issues/421"
);

if (value == null) {
componentModule = getDefaultWidgetFile(context.dirname);

if (!componentModule) {
context.addError(
'No corresponding JavaScript module found in the same directory (either "widget.js", "component.js" or "index.js").'
);
return;
}

if (componentModule.requirePath === "./") {
rendererModule = componentModule;
}
} else if (attr.isLiteralValue()) {
const literalValue = attr.literalValue;

if (typeof literalValue !== "string") {
context.addError(
'The value for the "w-bind" attribute should be a string. Actual: ' +
literalValue
);
return;
}

const filename = resolveFrom(context.dirname, literalValue);

if (!filename) {
this.addError(
"Target file not found: " +
literalValue +
" (from: " +
context.dirname +
")"
);
return;
}

componentModule = {
legacy: true,
filename,
requirePath: literalValue
};
}

context.legacyComponentModule = componentModule;
context.legacyRendererModule = rendererModule;

context.addMigration({
description: "Migrate legacy widget with w-bind",
apply(helpers) {
if (hasWidgetTypes) {
return;
}

return helpers
.prompt({
type: "confirm",
message:
"A widget file was discovered, would you like to migrate that as well?\n" +
"Note: widget migrations are not 100% safe and should be tested after migration.",
initial: true
})
.then(shouldMigrate => {
if (shouldMigrate) {
el.removeAttribute("w-bind");
return helpers.run("componentFile", componentModule);
}
});
}
});
};

function getDefaultWidgetFile(dirname) {
var filename;
var legacy = true;

if ((filename = resolveFrom(dirname, "./widget"))) {
return {
filename,
requirePath: "./widget",
legacy
};
} else if ((filename = resolveFrom(dirname, "./component"))) {
return {
filename,
requirePath: "./component",
legacy
};
} else if ((filename = resolveFrom(dirname, "./"))) {
return {
filename,
requirePath: "./",
legacy
};
} else {
return null;
}
}
3 changes: 2 additions & 1 deletion test/__util__/patch-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ Module._resolveFilename = function(request, parent, isMain) {
request === "marko/components" ||
request === "marko/jquery" ||
request === "marko/legacy-components" ||
request === "marko/ready"
request === "marko/ready" ||
request === "marko/env"
) {
request = nodePath.join(
rootDir,
Expand Down
3 changes: 3 additions & 0 deletions test/migrate/fixtures/w-bind-prompt-n/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = require("marko-widgets").defineComponent({
template: require("./template")
});
7 changes: 7 additions & 0 deletions test/migrate/fixtures/w-bind-prompt-n/prompts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = [
{
question:
"A widget file was discovered, would you like to migrate that as well?\nNote: widget migrations are not 100% safe and should be tested after migration.",
answer: false
}
];
Loading

0 comments on commit dd1f961

Please sign in to comment.