提交 1f78747a 编写于 作者: fxy060608's avatar fxy060608

Merge branch 'dev' of https://github.com/dcloudio/uni-app into dev

module.exports = async function checkUpdate () {
const {
isInHBuilderX
} = require('@dcloudio/uni-cli-shared')
if (isInHBuilderX) { // 仅 cli 提供检测更新
return
}
const pkg = require('../package.json')
const checkForUpdate = require('update-check')
let update = null
try {
const options = {}
if (pkg.version.indexOf('alpha') !== -1) {
options.distTag = 'alpha'
}
update = await checkForUpdate(pkg, options)
} catch (err) {
// console.error(`检查更新失败: ${err}`)
}
if (update) {
if (pkg.version.split('.')[0] !== update.latest.split('.')[0]) {
console.log(`发现 uni-app cli 新版本 ${update.latest}`)
console.log(`1.修改 package.json 中 @dcloudio 相关包版本为 ^${update.latest}`)
console.log('2.删除 package-lock.json 或 yarn.lock')
console.log('3.执行 npm install 或 yarn')
} else {
console.log(`发现 uni-app cli 新版本 ${update.latest}. 请执行 npm update 升级`)
}
}
const fs = require('fs')
const os = require('os')
const path = require('path')
class Upate {
constructor () {
this._https = null
this._crypto = null
this._interval = this.DEFAULT_INTERVAL
this._platform = process.env.UNI_PLATFORM
this._fileData = {}
this._compilerVersion = ''
this._isAlpha = false
this._uniId = ''
this._appId = ''
}
get uniId () {
return this._uniId
}
set uniId (value) {
this._uniId = value
}
get appId () {
return this._appId
}
set appId (value) {
this._appId = value
}
get compilerVersion () {
return this._compilerVersion
}
set compilerVersion (value) {
this._compilerVersion = value
}
get isAlpha () {
return this._isAlpha
}
set isAlpha (value) {
this._isAlpha = value
}
get versionType () {
return (this.isAlpha ? 'a' : 'r')
}
get https () {
if (this._https == null) {
this._https = require('https')
}
return this._https
}
get crypto () {
if (this._crypto == null) {
this._crypto = require('crypto')
}
return this._crypto
}
getBuildType () {
return (process.env.NODE_ENV === 'production' ? 'build' : 'dev')
}
async check () {
await this.readFile()
const fileData = this._fileData
const currentDate = Date.now()
if (!fileData.lastCheck || (Math.abs(currentDate - fileData.lastCheck) > this._interval)) {
this._fileData.lastCheck = currentDate
this.checkUpdate()
} else {
if (fileData.newVersion && fileData.newVersion !== this.compilerVersion) {
console.log()
console.log(fileData.note)
}
}
await this.update()
}
async readFile () {
const filePath = await this.getFilePath()
let fileData = {}
if (fs.existsSync(filePath)) {
fileData = require(filePath)
} else {
fileData.vid = this._buildUUID()
}
if (!fileData[this._platform]) {
fileData[this._platform] = {}
}
this._fileData = fileData
}
async update () {
const bt = this.getBuildType()
const info = this._fileData[this._platform]
const count = parseInt(info[bt] || 0)
info[bt] = (count + 1)
this.writeFile()
}
async writeFile (file) {
try {
const filePath = await this.getFilePath()
const content = JSON.stringify(file || this._fileData)
fs.writeFileSync(filePath, content, 'utf8')
} catch (error) {
}
}
checkUpdate () {
const postData = JSON.stringify({
id: this.getPostData()
})
var responseData = ''
const req = this.https.request({
hostname: this.HOST,
path: this.PATH,
port: 443,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': postData.length
}
}, (res) => {
res.setEncoding('utf8')
res.on('data', (chunk) => {
responseData += chunk
})
res.on('end', () => {
this.checkUpdateSuccess(JSON.parse(responseData))
})
})
req.write(postData)
req.end()
}
getPostData () {
var data = JSON.parse(JSON.stringify(this._fileData))
data.device = this._getMD5(this._getMac())
data.appid = this.uniId
data.vtype = this.versionType
data.vcode = this.compilerVersion
delete data.lastCheck
if (this.appId) {
data[this._platform].appid = this.appId
}
if (data.appid) {
delete data.vid
} else {
delete data.appid
}
return JSON.stringify(data)
}
checkUpdateSuccess (data) {
if (data.code !== 0) {
return
}
var fileData = {
vid: this._fileData.vid,
lastCheck: this._fileData.lastCheck
}
if (data.isUpdate === true) {
fileData.newVersion = data.newVersion
fileData.note = data.note
}
this.writeFile(fileData)
}
async getFilePath () {
const rootDir = os.tmpdir()
const fileName = this._getMD5(process.env.UNI_INPUT_DIR)
return path.join(rootDir, `${this.UPDATE_FILE_NAME}_${fileName}.json`)
}
_getMac () {
let mac
const network = os.networkInterfaces()
for (const key in network) {
const array = network[key]
for (let i = 0; i < array.length; i++) {
const item = array[i]
if (!item.family || (item.mac && item.mac === '00:00:00:00:00:00')) {
continue
}
if (item.family === 'IPv4' || item.family === 'IPv6') {
mac = item.mac
break
}
}
}
return mac
}
_getMD5 (str) {
return this.crypto.createHash('md5').update(str).digest('hex')
}
_buildUUID () {
var result = ''
for (let i = 0; i < 4; i++) {
result += (65536 * (1 + Math.random()) | 0).toString(16).substring(1)
}
return 'UNI_' + result.toUpperCase()
}
}
Object.assign(Upate.prototype, {
HOST: 'uniapp.dcloud.net.cn',
PATH: '/update/cli',
UPDATE_FILE_NAME: 'uni_app_cli_update',
DEFAULT_TIME: 2000,
DEFAULT_INTERVAL: 1000 * 60 * 60 * 24
})
module.exports = async function checkUpdate () {
const {
isInHBuilderX,
getManifestJson
} = require('@dcloudio/uni-cli-shared')
if (isInHBuilderX) { // 仅 cli 提供检测更新
return
}
const plp = require('@dcloudio/webpack-uni-pages-loader/package.json')
const ppj = require(path.join(process.env.UNI_CLI_CONTEXT, 'package.json'))
const manifest = getManifestJson()
try {
const update = new Upate()
update.compilerVersion = plp['uni-app'].compilerVersion
update.isAlpha = ppj.devDependencies['@dcloudio/vue-cli-plugin-uni'].includes('alpha')
update.uniId = manifest.appid
const appIdKey = process.env.UNI_PLATFORM.includes('quickapp') ? 'package' : 'appid'
update.appId = manifest[process.env.UNI_PLATFORM] ? (manifest[process.env.UNI_PLATFORM][appIdKey] || '') : ''
update.check()
} catch (e) {
}
}
const {
normalizePath,
isInHBuilderX
} = require('@dcloudio/uni-cli-shared/lib/util')
} = require('@dcloudio/uni-cli-shared/lib/util')
const plp = require('@dcloudio/webpack-uni-pages-loader/package.json')
class ErrorReport {
static get instance () {
......@@ -12,7 +13,8 @@ class ErrorReport {
}
constructor () {
this._instance = null
this._instance = null
this._os = null
this._https = null
this._crypto = null
this._cacheList = []
......@@ -20,6 +22,13 @@ class ErrorReport {
this._UNI_CLI_CONTEXT_REG = new RegExp(normalizePath(process.env.UNI_CLI_CONTEXT), 'g')
}
get os () {
if (this._os == null) {
this._os = require('os')
}
return this._os
}
get https () {
if (this._https == null) {
this._https = require('https')
......@@ -36,10 +45,12 @@ class ErrorReport {
err = err.replace(this._UNI_INPUT_DIR_REG, 'UNI_INPUT_DIR')
err = err.replace(this._UNI_CLI_CONTEXT_REG, 'UNI_CLI_CONTEXT')
const data = JSON.stringify({
const data = JSON.stringify({
di: this._getMD5(this._getMac()),
np: process.platform,
nv: process.version,
cp: process.env.UNI_PLATFORM,
cp: process.env.UNI_PLATFORM,
cv: plp['uni-app'].compilerVersion,
hx: isInHBuilderX ? 1 : 0,
et: type,
em: err
......@@ -96,6 +107,25 @@ class ErrorReport {
_getMD5 (str) {
return this.crypto.createHash('md5').update(str).digest('hex')
}
_getMac () {
let mac
const network = this.os.networkInterfaces()
for (const key in network) {
const array = network[key]
for (let i = 0; i < array.length; i++) {
const item = array[i]
if (!item.family || (item.mac && item.mac === '00:00:00:00:00:00')) {
continue
}
if (item.family === 'IPv4' || item.family === 'IPv6') {
mac = item.mac
break
}
}
}
return mac
}
get crypto () {
if (this._crypto == null) {
......@@ -107,7 +137,7 @@ class ErrorReport {
Object.assign(ErrorReport.prototype, {
HOST: '96f0e031-f37a-48ef-84c7-2023f6360c0a.bspapp.com',
PATH: '/http/uni-app-compiler',
EXCLUDE_ERROR_LIST: ['uni-app-compiler']
EXCLUDE_ERROR_LIST: ['uni-app-compiler', 'Error: ENOENT: no such file or directory']
})
function report (type, err) {
......
......@@ -187,6 +187,68 @@ global['__wxVueOptions'] = {
}
)
assertCodegenOptions(
`const options = {
name: 'test'
}
export default options`,
{
name: '"test"',
inheritAttrs: null,
props: null
}
)
assertCodegenOptions(
`let options
options = {
name: 'test'
}
export default options`,
{
name: '"test"',
inheritAttrs: null,
props: null
}
)
assertCodegenOptions(
`const options = Vue.extend({
name: 'test'
})
export default options`,
{
name: '"test"',
inheritAttrs: null,
props: null
}
)
assertCodegenOptions(
`let options
options = Vue.extend({
name: 'test'
})
export default options`,
{
name: '"test"',
inheritAttrs: null,
props: null
}
)
assertCodegenOptions(
`const options = {
name: 'test'
}
export default Vue.extend(options)`,
{
name: '"test"',
inheritAttrs: null,
props: null
}
)
assertCodegenOptions(
`export default {
props: ['id', 'test']
......
......@@ -60,6 +60,41 @@ function handleComponentsObjectExpression (componentsObjExpr, path, state, prepe
state.components = prepend ? components.concat(state.components) : components
}
function handleIdentifier ({ name }, path, state) {
// 仅做有限查找
for (let i = path.container.length; i > 0; i--) {
const node = path.container[i - 1]
let declarations = []
if (t.isExpressionStatement(node)) {
declarations = [node]
} else if (t.isVariableDeclaration(node)) {
declarations = node.declarations
}
for (let i = declarations.length; i > 0; i--) {
let declaration = declarations[i - 1]
let identifier
if (t.isVariableDeclarator(declaration)) {
identifier = declaration.id
declaration = declaration.init
} else if (t.isExpressionStatement(declaration)) {
identifier = declaration.expression.left
declaration = declaration.expression.right
}
if (identifier.name === name) {
if (t.isCallExpression(declaration) &&
t.isMemberExpression(declaration.callee) &&
declaration.arguments.length === 1) {
declaration = declaration.arguments[0]
}
if (t.isObjectExpression(declaration)) {
handleObjectExpression(declaration, path, state)
}
return
}
}
}
}
module.exports = function (ast, state = {
type: 'Component',
components: [],
......@@ -96,12 +131,19 @@ module.exports = function (ast, state = {
const declaration = path.node.declaration
if (t.isObjectExpression(declaration)) { // export default {components:{}}
handleObjectExpression(declaration, path, state)
} else if (t.isIdentifier(declaration)) {
handleIdentifier(declaration, path, state)
} else if (t.isCallExpression(declaration) &&
t.isMemberExpression(declaration.callee) &&
declaration.arguments.length === 1) { // export default Vue.extend({components:{}})
if (declaration.callee.object.name === 'Vue' && declaration.callee.property.name ===
'extend') {
handleObjectExpression(declaration.arguments[0], path, state)
const argument = declaration.arguments[0]
if (t.isObjectExpression(argument)) {
handleObjectExpression(argument, path, state)
} else if (t.isIdentifier(argument)) {
handleIdentifier(argument, path, state)
}
}
} else if (t.isClassDeclaration(declaration) &&
declaration.decorators &&
......
......@@ -64,6 +64,7 @@ module.exports = function generateComponent (compilation) {
const concatenatedModules = modules.filter(module => module.modules)
const uniModuleId = modules.find(module => module.resource && normalizePath(module.resource) === uniPath).id
const wxssImports = {}
Object.keys(assets).forEach(name => {
if (components.has(name.replace('.js', ''))) {
......@@ -81,7 +82,7 @@ module.exports = function generateComponent (compilation) {
let resource = normalizePath(path.resolve(process.env.UNI_INPUT_DIR, '..', modulePath))
const altResource = normalizePath(path.resolve(process.env.UNI_INPUT_DIR, modulePath))
if (
if (
/^win/.test(process.platform) &&
modulePath.includes('@dcloudio') &&
(
......@@ -125,6 +126,25 @@ module.exports = function generateComponent (compilation) {
assets[name].source = newSource
}
}
if (name.endsWith('.wxss')) {
// 移除部分含有错误引用的 wxss 文件
let origSource = assets[name].source()
origSource = origSource.trim ? origSource.trim() : ''
const result = origSource.match(/^@import ["'](.+?)["']$/)
if (result) {
const wxssPath = path.join(path.dirname(name), result[1])
if (Object.keys(assets).includes(wxssPath)) {
wxssImports[wxssPath] = wxssImports[wxssPath] || []
wxssImports[wxssPath].push(name)
} else {
if (wxssImports[name]) {
wxssImports[name].forEach(name => delete assets[name])
delete wxssImports[name]
}
delete assets[name]
}
}
}
})
}
if (process.env.UNI_FEATURE_OBSOLETE !== 'false') {
......@@ -158,4 +178,4 @@ function removeUnusedComponent (name) {
fs.renameSync(path.join(process.env.UNI_OUTPUT_DIR, name + '.json'), path.join(process.env.UNI_OUTPUT_DIR, name +
'.bak.json'))
} catch (e) {}
}
}
......@@ -179,8 +179,8 @@ module.exports = function (pagesJson, userManifestJson) {
if (!manifestJson.permissions) {
manifestJson.permissions = {}
}
const nvuePages = pagesJson.nvue && pagesJson.nvue.pages
const nvuePages = process.env.UNI_USING_V3_NATIVE ? pagesJson.pages : (pagesJson.nvue && pagesJson.nvue.pages)
if (nvuePages && nvuePages.length) {
const pages = {}
......@@ -197,10 +197,13 @@ module.exports = function (pagesJson, userManifestJson) {
appJson.nvue = {
pages
}
if (process.env.UNI_USING_V3_NATIVE) {
appJson.nvue.entryPagePath = nvuePages[0]
} else if (pagesJson.nvue.entryPagePath) {
appJson.nvue.entryPagePath = pagesJson.nvue.entryPagePath
}
if (pagesJson.nvue.entryPagePath) {
appJson.nvue.entryPagePath = pagesJson.nvue.entryPagePath
}
// nvue 权限
manifestJson.permissions.UniNView = {
description: 'UniNView原生渲染'
......@@ -344,9 +347,10 @@ module.exports = function (pagesJson, userManifestJson) {
resources[key.replace(/\.nvue$/, '.js')] = confusion.resources[key]
}
if (!Object.keys(nvuePages).find(path => {
const subNVues = nvuePages[path].window.subNVues || []
return path.replace(/\.html$/, '.nvue') === key || subNVues.find(({
path
const subNVues = nvuePages[path].window.subNVues || []
// TODO
return (path.replace(/\.html$/, '.nvue') === key || path.replace(/\.html$/, '.nvue') + '.nvue' === key) || subNVues.find(({
path
}) => path === key.replace(/\.nvue$/, ''))
}) && !pagesJson.pages.find(({
style = {}
......
import Vue from 'vue'
const getEmitter = (function () {
if (typeof getUniEmitter === 'function') {
/* eslint-disable no-undef */
return getUniEmitter
}
let Emitter
return function getUniEmitter () {
if (!Emitter) {
......
......@@ -9,8 +9,8 @@ import {
export const PAGE_EVENT_HOOKS = [
'onPullDownRefresh',
'onReachBottom',
'onAddToFavorites',
'onReachBottom',
'onAddToFavorites',
'onShareTimeline',
'onShareAppMessage',
'onPageScroll',
......@@ -471,6 +471,15 @@ function isMatchEventType (eventType, optType) {
)
}
function getContextVm (vm) {
let $parent = vm.$parent
// 父组件是 scoped slots 或者其他自定义组件时继续查找
while ($parent && $parent.$parent && ($parent.$options.generic || $parent.$parent.$options.generic || $parent.$scope._$vuePid)) {
$parent = $parent.$parent
}
return $parent && $parent.$parent
}
export function handleEvent (event) {
event = wrapper(event)
......@@ -503,12 +512,8 @@ export function handleEvent (event) {
const methodName = eventArray[0]
if (methodName) {
let handlerCtx = this.$vm
if (
handlerCtx.$options.generic &&
handlerCtx.$parent &&
handlerCtx.$parent.$parent
) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = handlerCtx.$parent.$parent
if (handlerCtx.$options.generic) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = getContextVm(handlerCtx) || handlerCtx
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
......@@ -552,4 +557,4 @@ export function handleEvent (event) {
) {
return ret[0]
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册